/**
 * Encapsulates a group of records. Can provide a
 * {@link #getSummaryRecord} summary record.
 *
 * @since 6.5.0
 */
Ext.define('Ext.data.Group', {
    extend: 'Ext.util.Group',
 
    isDataGroup: true,
 
    store: null,
    isCollapsed: false,
 
    updateParent: function(parent, oldParent) {
        if (!this.isCollapsed && parent && parent.isGroup) {
            this.isCollapsed = parent.isCollapsed;
        }
 
        this.callParent([parent, oldParent]);
    },
 
    /**
     * Mark this group as expanded.
     * @param {Boolean} [includeChildren=false] Set to true to expand the children groups too.
     */
    expand: function(includeChildren) {
        this.doExpandCollapse(true, includeChildren);
    },
 
    /**
     * Mark this group as collapsed.
     * @param {Boolean} [includeChildren=false] Set to true to collapse the children groups too.
     */
    collapse: function(includeChildren) {
        this.doExpandCollapse(false, includeChildren);
    },
 
    doExpandCollapse: function(expanded, includeChildren) {
        var groups = this.getGroups(),
            len, i;
 
        this.isCollapsed = !expanded;
 
        if (includeChildren && groups) {
            len = groups.length;
 
            for (= 0; i < len; i++) {
                groups.items[i].doExpandCollapse(expanded, includeChildren);
            }
        }
    },
 
    /**
     * Mark this group as collapsed or expanded depending on the current state.
     */
    toggleCollapsed: function() {
        this.doExpandCollapse(this.isCollapsed);
    },
 
    /**
     * Returns the group header summary results for the group.
     * @return {Ext.data.Model} 
     */
    getGroupRecord: function() {
        var record = this.getNewSummaryRecord('groupRecord', true);
 
        record.isGroup = true;
 
        return record;
    },
 
    /**
     * Returns the summary results for the group.
     * @return {Ext.data.Model} 
     */
    getSummaryRecord: function() {
        var record = this.getNewSummaryRecord('summaryRecord', true);
 
        record.isSummary = true;
 
        return record;
    },
 
    getNewSummaryRecord: function(property, calculate) {
        var me = this,
            summaryRecord = me[property],
            store = me.store,
            generation = store.getData().generation,
            M, T, idProperty;
 
        if (!summaryRecord) {
            M = store.getModel();
            T = M.getSummaryModel();
            me[property] = summaryRecord = new T();
            idProperty = M.idField.name;
            summaryRecord.data[idProperty] = summaryRecord.id = M.identifier.generate();
            summaryRecord.group = me;
            summaryRecord.commit();
        }
 
        if (!store.getRemoteSummary() && !summaryRecord.isRemote &&
            summaryRecord.summaryGeneration !== generation && calculate === true) {
            summaryRecord.calculateSummary(me.items);
            summaryRecord.summaryGeneration = generation;
        }
        else if (store.getRemoteSummary() && summaryRecord.isRemote) {
            // reset values that have no summary config anymore
            me.fixRemoteSummary(summaryRecord);
        }
 
        summaryRecord.isNonData = true;
 
        return summaryRecord;
    },
 
    // remove all data for the summaries that are no more available
    fixRemoteSummary: function(summaryRecord) {
        var fields = summaryRecord.getFields(),
            len = fields.length,
            i, result, summary, name, field;
 
        for (= 0; i < len; ++i) {
            field = fields[i];
            summary = field.getSummary();
            result = result || {};
            name = field.name;
 
            if (name !== 'id' && !summary) {
                result[name] = null;
            }
        }
 
        if (result) {
            summaryRecord.set(result, summaryRecord._commitOptions);
        }
    },
 
    recalculateSummaries: function() {
        var items = this.items;
 
        this.getGroupRecord().calculateSummary(items);
        this.getSummaryRecord().calculateSummary(items);
    },
 
    eject: function() {
        var me = this;
 
        me.callParent();
 
        if (me.groupRecord) {
            me.groupRecord.summaryGeneration = 0;
        }
 
        if (me.summaryRecord) {
            me.summaryRecord.summaryGeneration = 0;
        }
    }
 
});