/**
 * This class stores the matrix results. When the pivot component uses the
 * {@link Ext.pivot.matrix.Local} matrix then this class does
 * calculations in the browser.
 */
Ext.define('Ext.pivot.result.Collection', {
    alternateClassName: [
        'Mz.aggregate.matrix.Results'
    ],

    requires: [
        'Ext.pivot.MixedCollection',
        'Ext.pivot.result.Base'
    ],

    /**
     * @cfg {String} resultType
     *
     * Define here what class to be used when creating {@link Ext.pivot.result.Base Result} objects
     */
    resultType: 'base',

    /**
     * @property {Ext.pivot.MixedCollection} items
     *
     * Collection of {@link Ext.pivot.result.Base Result} objects
     *
     * @private
     */
    items: null,

    /**
     * @cfg {Ext.pivot.matrix.Base} matrix
     *
     * Reference to the matrix object
     */
    matrix: null,

    constructor: function(config) {
        var me = this;

        Ext.apply(me, config || {});

        me.items = new Ext.pivot.MixedCollection();

        me.items.getKey = function(obj) {
            return obj.leftKey + '/' + obj.topKey;
        };

        return me.callParent(arguments);
    },

    destroy: function() {
        var me = this;

        Ext.destroy(me.items);
        me.matrix = me.items = null;

        me.callParent(arguments);
    },

    /**
     * Clear all calculated results.
     *
     */
    clear: function() {
        this.items.clear();
    },

    /**
     * Add a new Result object by left/top axis keys.
     *
     * If there is already a Result object for the left/top axis pair then return that one.
     *
     * @param leftKey
     * @param topKey
     * @returns {Ext.pivot.result.Base}
     */
    add: function(leftKey, topKey) {
        var obj = this.get(leftKey, topKey);

        if (!obj) {

            obj = this.items.add(Ext.Factory.pivotresult({
                type: this.resultType,
                leftKey: leftKey,
                topKey: topKey,
                matrix: this.matrix
            }));
        }

        return obj;
    },

    /**
     * Returns the Result object for the specified left/top axis keys
     *
     * @param leftKey
     * @param topKey
     * @returns {Ext.pivot.result.Base}
     */
    get: function(leftKey, topKey) {
        return this.items.getByKey(leftKey + '/' + topKey);
    },

    remove: function(leftKey, topKey) {
        this.items.removeAtKey(leftKey + '/' + topKey);
    },

    /**
     * Return all Result objects for the specified leftKey
     *
     * @param leftKey
     * @returns Array
     */
    getByLeftKey: function(leftKey) {
        var col = this.items.filterBy(function(item, key) {
            var keys = String(key).split('/');

            return (leftKey === keys[0]);
        });

        return col.getRange();
    },

    /**
     * Return all Result objects for the specified topKey
     *
     * @param topKey
     * @returns Array
     */
    getByTopKey: function(topKey) {
        var col = this.items.filterBy(function(item, key) {
            var keys = String(key).split('/');

            return (keys.length > 1 && topKey === keys[1]);
        });

        return col.getRange();
    },

    /**
     * Calculate aggregate values for each available Result object
     *
     */
    calculate: function() {
        var len = this.items.getCount(),
            i;

        for (i = 0; i < len; i++) {
            this.items.getAt(i).calculate();
        }
    }
});
