/*
Class: Dictionary

  Dictionary object that can accept any elemente as key.  see also an [entry on Feb 13, 2008](http://furyu.tea-nifty.com/annex/2008/02/javascript_bc80.html)

License:
  (pending) MIT-style license

Author:
  - H.IDER (original idea)
  - Takashi Mizohata (namespace changed) <beatak@nydd.org>

Copyright:
  (pending)

Code & Documentation:
  [nydd jslib](http://code.nydd.org/).

Inspiration:
  Everything is worthwhile / if the soul isn't small.
*/


/*
  Method: constructor

  Generates dictionary object.

  Examples:
    var dict = new Dictionary();

  Retruns:
    (Dictionay)
*/

var Dictionary = function ()
{
  var count           = 0;
  var _SELF           = this;
  var keys            = [];
  var assocastr       = '__associativeArray' + (count++) + '__';
  var assoca          = [];
      assoca.number   = [];
      assoca.string   = [];
      assoca.boolean  = [];

/*
  Method: set

  Set a key-value pair to a dictionary instance

  Type:
    prototype

  Parameters:
    key - any variable
    value - any value

  Examples:
    - dict.set('abc', 123);
    - dict.set(document.getElementById('container'), (function(){...})());

  Retruns:
    (*) pass through 'value' argument
*/
  this.set = function (key, value)
  {
    if (assoca[typeof key]) 
    {
      if (assoca[typeof key][key] === undefined)
      {
        keys[keys.length] = key;
      }
      assoca[typeof key][key] = value;
    }
    else 
    {
      if (!key.toString.__associativeFlag__) 
      {
        var orgToString = key.toString;
        key.toString = function ()
        {
          return orgToString.apply(key,arguments)
        };
        key.toString.__associativeFlag__ = true;
      }
      if (key.toString[assocastr] === undefined) 
      {
        keys[keys.length] = key;
      }
      key.toString[assocastr] = value;
    }
    return value;
  }

/*
  Method: get

  get a value associated by the given key ahead.  If no value is associated, will return undefined

  Type:
    prototype

  Parameters:
    key - any variable

  Examples:
    - dict.get('abc');
    - dict.set(document.getElementById('container'));

  Retruns:
    (*)
*/
  this.get = function (key)
  {
    if (assoca[typeof key]) 
    {
      return assoca[typeof key][key];
    }
    else 
    {
      return key.toString[assocastr];
    }
  }

/*
  Method: remove

  destructive get().  it will remove a key and return the value associated with it.  If no value is associated, will return undefined.

  Type:
    prototype

  Parameters:
    key - any variable

  Examples:
    - dict.remove('abc');
    - dict.remove(document.getElementById('container'));

  Retruns:
    (*)
*/
  this.remove = function (key)
  {
    var value = _SELF.get(key);
    var tmpKeys = [];
    for (var ci = 0,len = keys.length; ci < len; ++ci) 
    {
      if (keys[ci] !== key) 
      {
        tmpKeys[tmpKeys.length] = keys[ci];
      }
    }
    keys = tmpKeys;
    if (assoca[typeof key]) 
    {
      assoca[typeof key][key] = undefined;
    }
    else 
    {
      key.toString[assocastr] = undefined;
    }
    return value;
  }

/*
  Method: getKeys

  return an array contains all keys inside this dictionary instance.

  Type:
    prototype

  Examples:
    dict.getKeys();

  Retruns:
    (Array)
*/
  this.getKeys = function (key)
  {
    return keys.concat([]);
  }

/*
  Method: collect

  return an array contains all values inside this dictionary instance associated with the given keys.  If no keys are passed, will return all values.

  Type:
    prototype

  Examples:
    - dict.collect(['abc']);
    - dict.collect();

  Retruns:
    (Array)
*/
  this.collect = function (keyList)
  {
    var collection = [];
    if (!keyList) 
    {
      keyList = keys;
    }
    for (var ci = 0, len = keyList.length; ci < len; ++ci) 
    {
      collection[collection.length] = _SELF.get(keyList[ci]);
    }
    return collection;
  }

}


