// initPackage (###PACKAGE###);

//--------------------------------------------------------------------
/** 
 * This class handles parameters in form of key value(s) pairs.
 * "(key1:value1)(key2:value2,value3)..."
 * List of methods:
 *  asObject()
 *  asString()
 *  toString()
 *  add()
 *  get()
 *  getLength()
 *  remove()
 *  reset()
 *  isIndexOf()
 *  getVersion()
 *  
 * @author sweber
 */
// <JSClass Name="ParameterHandler">

  /**
   * The ParameterHandler constructor.
   *
   * @param aParam: string: The parameter string.
   */
  function ParameterHandler (aParam)
  {
    if ( aParam == "__proto__" )
      return;

    // ###MEMBER DESCRIPTION###
    this.data_ = {};
    // default version is 2, because of the encodeURIComponent stuff
    this.version_ = 2;
    if (typeof aParam == 'undefined' || aParam == "")
    {
      return;
    }
    var has_version = false;

    var idx = 0;
    var str = aParam.substring((idx = aParam.indexOf('(')), aParam.lastIndexOf(')') + 1);
    if (idx >= 4) {
      if (aParam.substr(idx - 4, 4) == "[v2]") {
        has_version = true;
      }
    }
    if (str.length < 2)
    {
      return;
    }
    var arr = str.substring(1, str.length - 1).split(')(');
    var has_data = arr.length > 0;

    // contains data but no version number -> so it's version 1
    if (has_data && !has_version) {
      this.version_ = 1;
    }

    for (var i = 0; i < arr.length; i ++)
    {
      var temp = arr[i].split(':');
      if (temp.length < 2)
      {
        continue;
      }
      if (this.version_ == 1) {
        var key  = unescape(temp[0]);
      }
      else {
        var key  = decodeURIComponent(temp[0]);
      }
      if (temp[1] == '')
      {
        var vals = [];
      }
      else
      {
        var vals = temp[1].split(',');
        for (var j = 0; j < vals.length; j ++)
        {
          if (this.version_ == 1) {
            vals[j] = unescape(vals[j]);
          }
          else {
            vals[j] = decodeURIComponent(vals[j]);
          }
        }
      }
      this.data_[key] = vals;
    }
  }
  //--------------------------------------------------------------------
  // Inheritance call for JavaScript.
  class$ = doInherit (ParameterHandler);

  //--------------------------------------------------------------------
  /**
   * This method returns a java script object including all key value(s) pairs.
   * The value(s) type is an array. Empty keys will be returned as an empty array.
   * A single value will be returned as an array with the length 1.
   *
   * @param aParams: object: additional parameters
   * @param aParams.reduce: boolean: If true, all empty keys will be ignored in
   *        the returned object and keys with the length 1 will be transformed
   *        to strings.
   * @param aParams.omitDisabled: boolean: Special Default dialog switch.
   *        If true, all elements disabled in default dialog will be truncated.
   *
   * @return object: The key value(s) pairs java script object.
   * e.g.
   * {key1: [value1], key2: [value2, value3]}
   */
  class$.asObject = function (aParams)
  {
    var p = aParams || {};
    var ret_obj = this.data_;
    if (p.omitDisabled) {
      var new_data = {};
      var maybe_inactive = [];
      var active = [];
      var state = {};
      for (var i in ret_obj) {
        // mark all fields as active
        state[i] = true;
        if (i.indexOf("dd_groupfields_") == 0) {
          // this field(s) contains the information about the related (deactivateable) fields
          // this fields maybe inactive
          maybe_inactive = maybe_inactive.concat(ret_obj[i]);
          // mark myself as inactive
          state[i] = false;
        }
        if (i.indexOf("dd_group_") == 0) {
          // this field contains the information about the activated fields
          // this fields are active (maybe separated by "|")
          var tmp_arr = ret_obj[i];
          for (var j = 0; j < tmp_arr.length; j ++) {
            active = active.concat(tmp_arr[j].split("|"));
          }
          // mark myself as inactive
          state[i] = false;
        }
      }
      for (var i = 0; i < maybe_inactive.length; i ++) {
        // mark "maybe inactive" fields as inactive
        state[maybe_inactive[i]] = false;
      }
      for (var i = 0; i < active.length; i ++) {
        // mark "active" fields as active
        state[active[i]] = true;
      }
      for (var i in ret_obj) {
        if (state[i]) {
          new_data[i] = ret_obj[i];
        }
      }
      ret_obj = new_data;
    }
    if (p.reduce)
    {
      var new_data = {};
      for (var i in ret_obj)
      {
        if (ret_obj[i].length == 0)
          continue;
        else if (ret_obj[i].length == 1)
          new_data[i] = ret_obj[i].toString();
        else
          new_data[i] = ret_obj[i];
      }
      ret_obj = new_data;
    }
    return ret_obj;
  }

  //--------------------------------------------------------------------
  /**
   * This method returnes the key value(s) pairs string.
   * "(key1:value1)(key2:value2,value3)"
   *
   * @ return string: String including the key value(s) pairs.
   */
  class$.asString = function ()
  {
    var ret = [];
    for (var i in this.data_)
    {
      if (this.data_[i].length)
      {
        var vals = [];
        for (var j = 0; j < this.data_[i].length; j ++)
        {
          vals[vals.length] = encodeURIComponent(this.data_[i][j]);
        }
        ret[ret.length] = '(' + encodeURIComponent(i) + ':' + vals + ')';
      }
      else
      {
        ret[ret.length] = '(' + encodeURIComponent(i) + ':)';
      }
    }
    return "[v2]" + ret.join('');
  }

  //--------------------------------------------------------------------
  /**
   * This returnes the key value(s) pairs string as action parameter if there are
   * keys and values.
   * It can be used building a new url.
   * e.g.
   * var parameters = new ParameterHandler(the_String);
   * [...]
   * var url = the_url + ";internal&action=xyz" + parameters;
   *
   * @ return string: String including "&Parameter=" + the key values as string.
   */
  class$.toString = function ()
  {
    var str = this.asString();
    if (str == '')
    {
      return '';
    }
    return '&Parameter=' + encodeURIComponent(str);
  }

  //--------------------------------------------------------------------
  /**
   * This method returnes a pointer to a key. If the key doesn't exist at this time,
   * a new empty key will be created.
   *
   * @param name: string: Name of the key
   */
  class$.getPtr = function (name)
  {
    if (typeof this.data_[name] == 'undefined')
    {
      this.data_[name] = [];
    }
    return this.data_[name];
  }

  //--------------------------------------------------------------------
  /**
   * This method add a new key or add value(s) to an existing key.
   *
   * @param name: string: Name of the key.
   * @param value: string|array: The new value(s) to add.
   *
   * @return string|array|boolean: If adding was successful the added value(s) will be returned. If not false.
   */
  class$.add = function (name, value)
  {
    var ptr = this.getPtr(name);
    if (typeof value == 'undefined')
    {
      return false;
    }
    if (typeof value == 'string')
    {
      ptr[ptr.length] = value;
    }
    else if (typeof value == 'number')
    {
      ptr[ptr.length] = value.toString();
    }
    else if (value.length)
    {
      for (var i = 0; i < value.length; i ++)
      {
        ptr[ptr.length] = value[i];
      }
    }
    else
    {
      return false;
    }
    return value;
  }

  //--------------------------------------------------------------------
  /**
   * This method returnes values of a given key.
   * By default all keys will be returned as array.
   * Optional a start and end index can be declared.
   * Negativ indices are allowed and will be handled from the end of the values.
   *
   * @param name: string: Name of the key.
   * @param start: number: The start index.
   * @param end: number: The end index.
   */
  class$.get = function (name, start, end)
  {
    var ptr = this.getPtr(name);
    if (!ptr.length)
    {
      return ptr;
    }
    if (typeof start == 'undefined' || typeof start != 'number')
    {
      var start = 0;
    }
    if (typeof end == 'undefined' || typeof end != 'number')
    {
      var end = ptr.length;
    }
    if (start < 0)
    {
      start += ptr.length;
    }
    if (end < 0)
    {
      end += ptr.length;
    }
    return ptr.slice(start, end);
  }

  //--------------------------------------------------------------------
  /**
   * This method return the length of a given entry.
   *
   * @param name: string: Name of the key.
   *
   * @return number: The length of the given entry.
   */
  class$.getLength = function (name)
  {
    var ptr = this.getPtr(name);
    return ptr.length;
  }

  //--------------------------------------------------------------------
  /**
   * This method get and remove values from a given key.
   * By default the last value will be returned and remove.
   * The number of the values to be returned and remove can be declared.
   *
   * @param name: string: The name of the key.
   * @param length: number(1): The number of values to get and remove.
   *
   * @return array: The removed values.
   */
  class$.remove = function (name, length)
  {
    var ptr = this.getPtr(name);
    if (typeof length == 'undefined' || typeof length != 'number')
    {
      var length = 1;
    }
    if (length == -1)
    {
      length = ptr.length;
    }
    var pos = ptr.length - length;
    var extract = this.get(name, pos);
    this.reset(name, ptr.slice(0, pos));
    return extract;
  }

  //--------------------------------------------------------------------
  /**
   * This method overwrite all values of a given key.
   *
   * @param name: string: The name of the key.
   * @param values: string|array: The new value(s) of the declared key.
   */
  class$.reset = function (name, values)
  {
    var ptr = this.getPtr(name);
    ptr.length = 0;
    this.add(name, values);
  }

  //--------------------------------------------------------------------
  /**
   * ###METHOD DESCRIPTION###
   *
   * @param name: string: ###PARAMETER DESCRIPTION###
   * @param value: string: ###PARAMETER DESCRIPTION###
   * @return boolean: ###PARAMETER DESCRIPTION###
   */
  class$.isIndexOf = function (name, value)
  {
    var arr = this.get(name);
    for (var i = 0; i < arr.length; i++)
    {
      if (arr[i] == value)
      {
        return true;
      }
    }
    return false;
  }

  //--------------------------------------------------------------------
  /**
   * return version of parameter handler string
   *
   * @return number: version number
   */
  class$.getVersion = function ()
  {
    return this.version_;
  }
// </JSClass>
