/*
* Ext JS Library 2.2
* Copyright(c) 2006-2008, Ext JS, LLC.
* licensing@extjs.com
* 
* http://extjs.com/license
*/

Ext.grid.GroupSummary = function (config) {
    Ext.apply(this, config);
};

Ext.extend(Ext.grid.GroupSummary, Ext.util.Observable, {
    init: function (grid) {
        this.grid = grid;
        this.cm = grid.getColumnModel();
        this.view = grid.getView();
        
        this.grid.getGroupingSummary = (function () {return this;}).createDelegate(this);

        var v = this.view;
        v.doGroupEnd = this.doGroupEnd.createDelegate(this);

        v.afterMethod('onColumnWidthUpdated', this.doWidth, this);
        v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);
        v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);
        v.afterMethod('onUpdate', this.doUpdate, this);
        v.afterMethod('onRemove', this.doRemove, this);

        if (!this.rowTpl) {
            this.rowTpl = new Ext.Template(
                '<div class="x-grid3-summary-row" style="{tstyle}">',
                '<table class="x-grid3-summary-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
                    '<tbody><tr>{cells}</tr></tbody>',
                '</table></div>'
            );
            this.rowTpl.disableFormats = true;
        }
        this.rowTpl.compile();

        if (!this.cellTpl) {
            this.cellTpl = new Ext.Template(
                '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',
                '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on">{value}</div>',
                "</td>"
            );
            this.cellTpl.disableFormats = true;
        }
        this.cellTpl.compile();
    },

    toggleSummaries: function (visible) {
        var el = this.grid.getGridEl();
        if (el) {
            if (visible === undefined) {
                visible = el.hasClass('x-grid-hide-summary');
            }
            el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary');
        }
    },

    renderSummary: function (o, cs) {
        cs = cs || this.view.getColumnData();
        var cfg = this.grid.getColumnModel().config,
            buf = [], c, p = {}, cf, last = cs.length-1;
        for (var i = 0, len = cs.length; i < len; i++) {
            c = cs[i];
            cf = cfg[i];
            p.id = c.id;
            p.style = c.style;
            p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');

            if (cf.summaryType || cf.summaryRenderer) {
                p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o, 0, i, this.grid.store);
            } else {
                p.value = '';
            }
            if (p.value == undefined || p.value === "") p.value = "&#160;";
            buf[buf.length] = this.cellTpl.apply(p);
        }

        return this.rowTpl.apply({
            tstyle: 'width:' + this.view.getTotalWidth() + ';',
            cells: buf.join('')
        });
    },

    calculate: function (rs, cs) {
        var data = {}, r, c, cfg = this.grid.getColumnModel().config, cf;
        for (var j = 0, jlen = rs.length; j < jlen; j++) {
            r = rs[j];
            for (var i = 0, len = cs.length; i < len; i++) {
                c = cs[i];
                cf = cfg[i];

                if (cf.summaryType) {
                    data[c.name] = Ext.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data);
                }
            }
        }
        return data;
    },

    doGroupEnd: function (buf, g, cs, ds, colCount) {
        var data = this.calculate(g.rs, cs);
        buf.push('</div>', this.renderSummary({ data: data }, cs), '</div>');
    },

    doWidth: function (col, w, tw) {
        if (!this.isGrouped()) {
            return;
        }
        var gs = this.view.getGroups(), s;
        for (var i = 0, len = gs.length; i < len; i++) {
            if (gs[i].childNodes.length>2) {
                s = gs[i].childNodes[2];
                s.style.width = tw;
                s.firstChild.style.width = tw;
                s.firstChild.rows[0].childNodes[col].style.width = w;
            }
        }
    },

    doAllWidths: function (ws, tw) {
        if (!this.isGrouped()) {
            return;
        }
        var gs = this.view.getGroups(), s, cells, wlen = ws.length;
        for (var i = 0, len = gs.length; i < len; i++) {
            if (gs[i].childNodes.length>2) {
                s = gs[i].childNodes[2];
                s.style.width = tw;
                s.firstChild.style.width = tw;
                cells = s.firstChild.rows[0].childNodes;
                for (var j = 0; j < wlen; j++) {
                    cells[j].style.width = ws[j];
                }
            }
        }
    },

    doHidden: function (col, hidden, tw) {
        if (!this.isGrouped()) {
            return;
        }
        var gs = this.view.getGroups(), s, display = hidden ? 'none' : '';
        for (var i = 0, len = gs.length; i < len; i++) {
            if (gs[i].childNodes.length>2) {
                s = gs[i].childNodes[2];
                s.style.width = tw;
                s.firstChild.style.width = tw;
                s.firstChild.rows[0].childNodes[col].style.display = display;
            }
        }
    },
    
    isGrouped : function () {
        return !Ext.isEmpty(this.grid.getStore().groupField);
    },
    

    // Note: requires that all (or the first) record in the 
    // group share the same group value. Returns false if the group
    // could not be found.
    refreshSummary: function (groupValue) {
        return this.refreshSummaryById(this.view.getGroupId(groupValue));
    },

    getSummaryNode: function (gid) {
        var g = Ext.fly(gid, '_gsummary');
        if (g) {
            return g.down('.x-grid3-summary-row', true);
        }
        return null;
    },

    refreshSummaryById : function (gid) {
        var g = Ext.getDom(gid);
        if (!g) {
            return false;
        }
        var rs = [];
        this.grid.store.each(function (r) {
            if (Ext.util.Format.htmlDecode(r._groupId) == gid) {
                rs[rs.length] = r;
            }
        });
        var cs = this.view.getColumnData();
        var data = this.calculate(rs, cs);
        var markup = this.renderSummary({ data: data }, cs);

        var existing = this.getSummaryNode(gid);
        if (existing) {
            g.removeChild(existing);
        }
        Ext.DomHelper.append(g, markup);
        return true;
    },

    doUpdate: function (ds, record) {
        this.refreshSummaryById(Ext.util.Format.htmlDecode(record._groupId));
    },

    doRemove: function (ds, record, index, isUpdate) {
        if (!isUpdate) {
            this.refreshSummaryById(Ext.util.Format.htmlDecode(record._groupId));
        }
    },

    showSummaryMsg: function (groupValue, msg) {
        var gid = this.view.getGroupId(groupValue);
        var node = this.getSummaryNode(gid);
        if (node) {
            node.innerHTML = '<div class="x-grid3-summary-msg">' + msg + '</div>';
        }
    }
});

Ext.grid.GroupSummary.Calculations = {
    'sum': function (v, record, field) {
        return v + (record.data[field] || 0);
    },

    'count': function (v, record, field, data) {
        return data[field + 'count'] ? ++data[field + 'count'] : (data[field + 'count'] = 1);
    },

    'max': function (v, record, field, data) {
        var v = record.data[field];
        var max = data[field + 'max'] === undefined ? (data[field + 'max'] = v) : data[field + 'max'];
        return v > max ? (data[field + 'max'] = v) : max;
    },

    'min': function (v, record, field, data) {
        var v = record.data[field];
        var min = data[field + 'min'] === undefined ? (data[field + 'min'] = v) : data[field + 'min'];
        return v < min ? (data[field + 'min'] = v) : min;
    },

    'average': function (v, record, field, data) {
        var c = data[field + 'count'] ? ++data[field + 'count'] : (data[field + 'count'] = 1);
        var t = (data[field + 'total'] = ((data[field + 'total'] || 0) + (record.data[field] || 0)));
        return t === 0 ? 0 : t / c;
    }
}

Ext.grid.HybridSummary = Ext.extend(Ext.grid.GroupSummary, {
    calculate: function (rs, cs) {
        var gcol = this.view.getGroupField();
        var gvalue = rs[0].data[gcol];
        var gdata = this.getSummaryData(gvalue);
        return gdata || Ext.grid.HybridSummary.superclass.calculate.call(this, rs, cs);
    },

    updateSummaryData: function (groupValue, data, skipRefresh) {
        var json = this.grid.store.reader.jsonData;
        if (!json.summaryData) {
            json.summaryData = {};
        }
        json.summaryData[groupValue] = data;
        if (!skipRefresh) {
            this.refreshSummary(groupValue);
        }
    },

    getSummaryData: function (groupValue) {
        var reader = this.grid.getStore().reader,
            json = reader.jsonData,
            fields = reader.recordType.prototype.fields,
            v;
            
        if (json && json.summaryData) {
            v = json.summaryData[groupValue];
            if (v) {
                return reader.extractValues(v, fields.items, fields.length);
            }
        }
        return null;
    }
});

if (typeof Sys!=="undefined") {Sys.Application.notifyScriptLoaded();}
