/*
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 3.3.0
build: 3167
*/
YUI.add('recordset-indexer', function(Y) {

/**
 * Provides the ability to store multiple custom hash tables referencing records in the recordset.
 * @module recordset
 * @submodule recordset-indexer
 */
/**
 * Plugin that provides the ability to store multiple custom hash tables referencing records in the recordset.
 * This utility does not support any collision handling. New hash table entries with a used key overwrite older ones.
 * @class RecordsetIndexer
 */
function RecordsetIndexer(config) {
    RecordsetIndexer.superclass.constructor.apply(this, arguments);
}

Y.mix(RecordsetIndexer, {
    NS: "indexer",

    NAME: "recordsetIndexer",

    ATTRS: {
        /**
	    * @description Collection of all the hashTables created by the plugin. 
		* The individual tables can be accessed by the key they are hashing against. 
	    *
	    * @attribute hashTables
	    * @public
	    * @type object
	    */
        hashTables: {
            value: {

            }
        },


        keys: {
            value: {

            }
        }
    }
});


Y.extend(RecordsetIndexer, Y.Plugin.Base, {

    initializer: function(config) {
        var host = this.get('host');

        //setup listeners on recordset events
        this.onHostEvent('add', Y.bind("_defAddHash", this), host);
        this.onHostEvent('remove', Y.bind('_defRemoveHash', this), host);
        this.onHostEvent('update', Y.bind('_defUpdateHash', this), host);

    },

    destructor: function(config) {
    
    },


    /**
     * @description Setup the hash table for a given key with all existing records in the recordset
     *
     * @method _setHashTable
     * @param key {string} A key to hash by.
	 * @return obj {object} The created hash table
     * @private
     */
    _setHashTable: function(key) {
        var host = this.get('host'),
        obj = {},
        i = 0,
        len = host.getLength();

        for (; i < len; i++) {
            obj[host._items[i].getValue(key)] = host._items[i];
        }
        return obj;
    },

    //---------------------------------------------
    // Syncing Methods
    //---------------------------------------------

    /**
     * @description Updates all hash tables when a record is added to the recordset
	 *
     * @method _defAddHash
     * @private
     */
    _defAddHash: function(e) {
        var tbl = this.get('hashTables');


        //Go through every hashtable that is stored.
        //in each hashtable, look to see if the key is represented in the object being added.
        Y.each(tbl,
        function(v, key) {
            Y.each(e.added || e.updated,
            function(o) {
                //if the object being added has a key which is being stored by hashtable v, add it into the table.
                if (o.getValue(key)) {
                    v[o.getValue(key)] = o;
                }
            });
        });

    },

    /**
     * @description Updates all hash tables when a record is removed from the recordset
	 *
     * @method _defRemoveHash
     * @private
     */
    _defRemoveHash: function(e) {
        var tbl = this.get('hashTables'),
        reckey;

        //Go through every hashtable that is stored.
        //in each hashtable, look to see if the key is represented in the object being deleted.
        Y.each(tbl,
        function(v, key) {
            Y.each(e.removed || e.overwritten,
            function(o) {
                reckey = o.getValue(key);

                //if the hashtable has a key storing a record, and the key and the record both match the record being deleted, delete that row from the hashtable
                if (reckey && v[reckey] === o) {
                    delete v[reckey];
                }
            });
        });
    },

    /**
     * @description Updates all hash tables when the recordset is updated (a combination of add and remove)
	 *
     * @method _defUpdateHash
     * @private
     */
    _defUpdateHash: function(e) {

        //TODO: It will be more performant to create a new method rather than using _defAddHash, _defRemoveHash, due to the number of loops. See commented code.
        e.added = e.updated;
        e.removed = e.overwritten;
        this._defAddHash(e);
        this._defRemoveHash(e);

        /*
					var tbl = this.get('hashTables'), reckey;
					
					Y.each(tbl, function(v, key) {
						Y.each(e.updated, function(o, i) {
							
							//delete record from hashtable if it has been overwritten
							reckey = o.getValue(key);
							
							if (reckey) {
								v[reckey] = o;
							}
							
							//the undefined case is if more records are updated than currently exist in the recordset. 
							if (e.overwritten[i] && (v[e.overwritten[i].getValue(key)] === e.overwritten[i])) {
								delete v[e.overwritten[i].getValue(key)];
							}
							
							// if (v[reckey] === o) {
							// 	delete v[reckey];
							// }
							// 				
							// //add the new updated record if it has a key that corresponds to a hash table
							// if (o.getValue(key)) {
							// 	v[o.getValue(key)] = o;
							// }
															
						});
					});
			*/
    },

    //---------------------------------------------
    // Public Methods
    //---------------------------------------------

    /**
     * @description Creates a new hash table.
	 *
     * @method createTable
     * @param key {string} A key to hash by.
	 * @return tbls[key] {object} The created hash table
     * @public
     */
    createTable: function(key) {
        var tbls = this.get('hashTables');
        tbls[key] = this._setHashTable(key);
        this.set('hashTables', tbls);

        return tbls[key];
    },


    /**
     * @description Get a hash table that hashes records by a given key.
	 *
	 * @method getTable
     * @param key {string} A key to hash by.
	 * @return table {object} The created hash table
     * @public
     */
    getTable: function(key) {
        return this.get('hashTables')[key];
    }





});
Y.namespace("Plugin").RecordsetIndexer = RecordsetIndexer;




}, '3.3.0' ,{requires:['recordset-base','plugin']});
