/**
 *  A Key/Value store where the data is persisted to an encrypted store inside of Sencha Web Application Client instead of plain text.
 *  This class should not be created directly but instead should be obtained via Ext.space.SecureLocalStorage
 *
 */
Ext.define("Ext.space.localstorage.Collection", {
    /**
     * @private
     */
    queries: null,
 
    /**
     * @private
     */
    activeQuery: null,
 
    /**
    * @private
    */
    constructor: function(name, loaded) {
        //add code to normalize name to sql table name limits 
        this.name = name;
        this.loaded = loaded;
        this.queries = [];
    },
 
    /**
     * @private
     */
    runQueries: function() {
        var collection = this;
 
        function next(query) {
            collection.activeQuery = query || null;
 
            if (collection.activeQuery) {
                collection.loaded.then(function(db) {
                    var transaction = db.createTransaction();
                    transaction.sql(query.query, query.params).then(function(results) {
                        query.promise.fulfill(results);
                        next(collection.queries.shift());
                    });
                    return transaction.execute();
 
                }).error(function(e) {
                    query.promise.reject(e);
                });
            }
        }
 
        next(this.queries.shift());
    },
 
    /**
    * @private
    */
    query: function(query, params) {
        var queryPromise = new Ext.space.Promise();
        this.queries.push({
            query: query,
            params: params,
            promise: queryPromise
        });
        if (!this.activeQuery) {
            this.runQueries();
        }
        return queryPromise;
    },
 
 
 
    /**
    * Get the value for a key
 
        var secrets = Ext.space.SecureLocalStore.get('secrets');
 
        secrets.get('myKey').then(function(object){
            var a = object.field;
        });
 
    * @param {String} key  The key to get a value for.
    * @return {Ext.space.Promise} the promise that will resolve when the value is fetched.
    *
    */
    get: function(key){
        return this.query("select value from item where collection = ? and name = ?", [this.name, key]).then(function(rs){
            Ext.space.Logger.debug("value ", rs.rows.length);
            if(rs.rows.length > 0){
                return JSON.parse(rs.rows[0][0]);
            } else {
                return undefined;
            }
        });
    },
 
 
 
    /**
    * Get the value for a key
 
        var secrets = Ext.space.SecureLocalStore.get('secrets');
 
        secrets.set('myKey',object).then(function(){
            //do something when done.
        });
 
 
 
    * @param {String} key  The key to store the value at.
    * @param {Object} value The JSON object to store.
    * @return {Ext.space.Promise} the promise that will resolve when the value is stored.
    *
    */
    set: function(key, value){
        return this.query("INSERT OR REPLACE into item values(?,?,?)", [this.name, key, JSON.stringify(value)]).then(function(rs){
            if(rs.value){
                return rs.value;
            } else {
                return undefined;
            }
        });
    },
 
    /**
    * Checks to see if key is present in collection without fetching and de-serializing the value.
 
        var secrets = Ext.space.SecureLocalStore.get('secrets');
 
        secrets.has('myKey').then(function(hasKey){
 
        });
 
    * @param {String} key  The key to get a value for.
    * @return {Ext.space.Promise} the promise that will resolve when the value is checked.
    *
    */
    has: function(key){
        return this.query("select count(*) from item where collection = ? and name = ?", [this.name, key]).then(function(rs){
            Ext.space.Logger.debug("value ", rs.rows.length );
            return (rs.rows[0][0] > 0);
        });
    },
 
    /**
    * Deletes the key if present in collection.
 
        var secrets = Ext.space.SecureLocalStore.get('secrets');
 
        secrets.remove('myKey').then(function(done){
 
        });
 
    * @param {String} key The key to delete
    * @return {Ext.space.Promise} the promise that will resolve when the value is checked.
    *
    */
    remove: function(key){
        return this.query("delete from item where collection = ? and name = ?", [this.name, key]).then(function(rs){
            Ext.space.Logger.debug("value ", rs.rowsAffected);
            return (rs.rowsAffected > 0);
        });
    },
 
    /**
    * Gets an array of all the keys in a collection
 
        var secrets = Ext.space.SecureLocalStore.get('secrets');
 
        secrets.keys().then(function(keys){
           Ext.space.Logger.log(keys.length);
        });
 
    * @return {Ext.space.Promise} the promise that will resolve when all of the keys have been collected.
    *
    */
    keys: function() {
        return this.query("select name from item where collection = ?", [this.name]).then(function(rs){
            var results = [];
            for(var i =0, l = rs.rows.length; i < l; i++ ){
                results.push(rs.rows[i][0]);
            }
            return results;
        });
    },
 
    /**
    * Iterates over all the items in a collection
 
        var secrets = Ext.space.SecureLocalStore.get('secrets');
 
         secrets.forEach(function(key, value){}).then(function(){
            // done.
        });
 
 
    * @param {Function}  callback this function will be called once for each item in the collection.
    * @return {Ext.space.Promise} the promise that will resolve when all of the itmes have been iterated.
    *
    */
    forEach: function(callback) {
        return this.query("select name, value from item where collection = ?", [this.name]).then(function(rs){
            for(var i =0, l = rs.rows.length; i < l; i++ ){
                callback(rs.rows[i][0], JSON.parse(rs.rows[i][1]));
            }
        });
    },
 
    /**
    * Returns a count of the total number of items in the collection
 
        var secrets = Ext.space.SecureLocalStore.get('secrets');
 
         secrets.count().then(function(count){
            // done.
        });
 
    * @return {Ext.space.Promise} the promise that will resolve with a the number of items in the collection.
    *
    */
    count: function() {
        return this.query("select count(*) from item where collection = ?", [this.name]).then(function(rs){
            Ext.space.Logger.debug("value ", rs.rows[0][0]);
            return parseInt(rs.rows[0][0], 10);
        });
    },
 
    /**
    * Deletes all of the items in a collection.
 
        var secrets = Ext.space.SecureLocalStore.get('secrets');
 
         secrets.clear().then(function(){
            // done.
        });
 
    * @return {Ext.space.Promise} the promise that will resolve with a the number of items in the collection.
    *
    */
    clear: function(){
        return this.query("DELETE FROM item where collection = ?", [this.name]);
    }
});