/**
 * Ext JS Library 3.4.0
 * Copyright(c) 2006-2011 Sencha Inc.
 * licensing@sencha.com
 * http://www.sencha.com/license
 */
Ext.ns('Ext.ux.tree');

/**
 * @class Ext.ux.tree.TreeGridSorter
 * @extends Ext.tree.TreeSorter
 * Provides sorting of nodes in a {@link Ext.ux.tree.TreeGrid}.  The TreeGridSorter automatically monitors events on the
 * associated TreeGrid that might affect the tree's sort order (beforechildrenrendered, append, insert and textchange).
 * Example usage:<br />
 * <pre><code>
 new Ext.ux.tree.TreeGridSorter(myTreeGrid, {
     folderSort: true,
     dir: "desc",
     sortType: function(node) {
         // sort by a custom, typed attribute:
         return parseInt(node.id, 10);
     }
 });
 </code></pre>
 * @constructor
 * @param {TreeGrid} tree
 * @param {Object} config
 */
Ext.ux.tree.TreeGridSorter = Ext.extend(Ext.tree.TreeSorter, {
    /**
     * @cfg {Array} sortClasses The CSS classes applied to a header when it is sorted. (defaults to <tt>['sort-asc', 'sort-desc']</tt>)
     */
    sortClasses: ['sort-asc', 'sort-desc'],
    /**
     * @cfg {String} sortAscText The text displayed in the 'Sort Ascending' menu item (defaults to <tt>'Sort Ascending'</tt>)
     */
    sortAscText: 'Sort Ascending',
    /**
     * @cfg {String} sortDescText The text displayed in the 'Sort Descending' menu item (defaults to <tt>'Sort Descending'</tt>)
     */
    sortDescText: 'Sort Descending',

    constructor: function(tree, config) {
        if (!Ext.isObject(config)) {
            config = {
                property: tree.columns[0].dataIndex || 'text',
                folderSort: true,
            };
        }

        Ext.ux.tree.TreeGridSorter.superclass.constructor.apply(
            this,
            arguments
        );

        this.tree = tree;
        tree.on('headerclick', this.onHeaderClick, this);
        tree.ddAppendOnly = true;

        var me = this;
        this.defaultSortFn = function(n1, n2) {
            var desc = me.dir && me.dir.toLowerCase() == 'desc',
                prop = me.property || 'text',
                sortType = me.sortType,
                caseSensitive = me.caseSensitive === true,
                leafAttr = me.leafAttr || 'leaf',
                attr1 = n1.attributes,
                attr2 = n2.attributes;

            if (me.folderSort) {
                if (attr1[leafAttr] && !attr2[leafAttr]) {
                    return 1;
                }
                if (!attr1[leafAttr] && attr2[leafAttr]) {
                    return -1;
                }
            }
            var prop1 = attr1[prop],
                prop2 = attr2[prop],
                v1 = sortType
                    ? sortType(prop1)
                    : caseSensitive
                    ? prop1
                    : prop1.toUpperCase();
            v2 = sortType
                ? sortType(prop2)
                : caseSensitive
                ? prop2
                : prop2.toUpperCase();

            if (v1 < v2) {
                return desc ? +1 : -1;
            } else if (v1 > v2) {
                return desc ? -1 : +1;
            } else {
                return 0;
            }
        };

        tree.on('afterrender', this.onAfterTreeRender, this, { single: true });
        tree.on('headermenuclick', this.onHeaderMenuClick, this);
    },

    onAfterTreeRender: function() {
        if (this.tree.hmenu) {
            this.tree.hmenu.insert(
                0,
                {
                    itemId: 'asc',
                    text: this.sortAscText,
                    cls: 'xg-hmenu-sort-asc',
                },
                {
                    itemId: 'desc',
                    text: this.sortDescText,
                    cls: 'xg-hmenu-sort-desc',
                }
            );
        }
        this.updateSortIcon(0, 'asc');
    },

    onHeaderMenuClick: function(c, id, index) {
        if (id === 'asc' || id === 'desc') {
            this.onHeaderClick(c, null, index);
            return false;
        }
    },

    onHeaderClick: function(c, el, i) {
        if (c && !this.tree.headersDisabled) {
            var me = this;

            me.property = c.dataIndex;
            me.dir = c.dir = c.dir === 'desc' ? 'asc' : 'desc';
            me.sortType = c.sortType;
            me.caseSensitive === Ext.isBoolean(c.caseSensitive)
                ? c.caseSensitive
                : this.caseSensitive;
            me.sortFn = c.sortFn || this.defaultSortFn;

            this.tree.root.cascade(function(n) {
                if (!n.isLeaf()) {
                    me.updateSort(me.tree, n);
                }
            });

            this.updateSortIcon(i, c.dir);
        }
    },

    // private
    updateSortIcon: function(col, dir) {
        var sc = this.sortClasses,
            hds = this.tree.innerHd.select('td').removeClass(sc);
        hds.item(col).addClass(sc[dir == 'desc' ? 1 : 0]);
    },
});
