/*
 * File: app/view/yearMonthSelect.js
 *
 * This file was generated by Sencha Architect version 3.2.0.
 * http://www.sencha.com/products/architect/
 *
 * This file requires use of the Sencha Touch 2.4.x library, under independent license.
 * License of Sencha Architect does not include license for Sencha Touch 2.4.x. For more
 * details see http://www.sencha.com/license or contact license@sencha.com.
 *
 * This file will be auto-generated each and everytime you save your project.
 *
 * Do NOT hand edit this file.
 */

Ext.define('CalendarPicker.view.yearMonthSelect', {
    extend: 'Ext.Panel',
    alias: 'widget.yearMonthSelect',

    requires: [
        'Ext.Container'
    ],

    config: {
        yearMoSel: '',
        yearInit: '',
        numCols: 3,
        backMonths: 0,
        forwardMonths: 0,
        backYears: 2,
        forwardYears: 10,
        yearMoCurr: '',
        height: '85%',
        itemId: 'yearMoSel',
        maxHeight: '85%',
        maxWidth: '8em',
        width: '8em',
        layout: 'fit',
        modal: true,
        firstSelDt: {
            
        },
        items: [
            {
                xtype: 'touchtreegrid',
                variableHeights: false,
                itemHeight: 32,
                listItemId: 'yearMoList',
                includeFooter: false,
                categIndentPct: '0',
                renderers: {
                    cls_renderer: function(col, values) {
                    var isCurr = values['isCurr_'+col];
                    return 'yearMoSel-months' + (isCurr ? ' yearMoSel-months-curr' : '');
                }
                },
                includeHeader: false,
                defaultCollapseLevel: 1,
                singleExpand: true,
                arrowPctWidth: '0',
                hideExpandCollapseBtns: true,
                cls: [
                    'x-touchtreegrid-list',
                    'x-touchtreegrid-list-yearMoCont'
                ],
                itemId: 'yearMoCont'
            }
        ]
    },

    initialize: function() {
        var me = this;
        me.callParent();

        me.setModal({ transparent: true });  // Keep background transaparent instead of gray since IOS calendar is already gray

        var gridcont = me.down('#yearMoCont');
        var gridlist = me.down('#yearMoList');
        var scroller = gridlist.getScrollable().getScroller();

        var i, j, thisRow, yearArr=[], tempDt, currYrIdx=0;

        var today    = Ext.Date.clearTime(new Date(Date(Ext.Date.now())), true);
        var thisYear = Ext.Date.format(today, 'Y');
        var thisMo   = Ext.Date.format(today, 'm');

        var yearInit     = (Ext.isEmpty(me.getYearInit()) ? thisYear : me.getYearInit());
        var yearMoCurr   = me.getYearMoCurr();
        var yearCurr     = (Ext.isEmpty(me.getYearMoCurr()) ? yearInit : yearMoCurr.substring(0,4));
        var moCurr       =(Ext.isEmpty(me.getYearMoCurr()) ? thisMo : yearMoCurr.substring(4,7));

        var backYears    = me.getBackYears();
        var forwardYears = me.getForwardYears();

        var startYr = (parseInt(yearInit) - backYears).toString();
        var endYr   = (parseInt(yearInit) + forwardYears).toString();

        var numCols = me.getNumCols();
        numCols = Math.max(Math.min(numCols, 4),1);  // Override if not between 1 and 4 columns
        numRows = 12/numCols;

        var myWidth = (100/numCols).toString()+'%';

        var categColumns = [{
            dataIndex: 'year',
            width: '100%',
            css: 'yearMoSel-years'
        }];
        me.down('#yearMoCont').setCategColumns(categColumns);


        var columns=[];
        for (j=0; j<numCols; j++) {
            columns.push({
                dataIndex: 'col'+j.toString(),
                width: myWidth,
                addDataIndexToDiv: true,
                css: "{[this.cls_renderer('col" + j.toString() + "', values)]}"
            });
        }
        me.down('#yearMoCont').setColumns(columns);

        thisYear = startYr;
        var k=0, yr=0;
        do { // Loop for each year
            if (thisYear === yearCurr) {currYrIdx=yr;}

            yearArr.push({
                year: thisYear,
                ID: thisYear,
                PARENT_ID: null,
                row: null,
                col0: null, isCurr_col0: null,
                col1: null, isCurr_col1: null,
                col2: null, isCurr_col2: null,
                col3: null, isCurr_col3: null
            });
            k++;
            yr++;

            // Build month selection rows as array of objects
            for (i=0; i<numRows; i++) {
                thisRow = {year: thisYear,
                    PARENT_ID: thisYear,
                    ID: k.toString(),
                row: i};

                for (j=0; j<numCols; j++) {
                    tempDt = new Date(parseInt(thisYear), (i*numCols) + j, 1); // Create date as 1st day of current month and year
                    thisRow['col'+j.toString()] = Ext.Date.format(tempDt, 'M');  // Jan, Feb, etc.. format
                    thisRow['isCurr_col'+j.toString()] = ((thisYear === yearCurr) && (Ext.Date.format(tempDt, 'm') === moCurr));
                }
                yearArr.push(thisRow);
                k++;
            }

            thisYear = (parseInt(thisYear)+1).toString();
        } while (thisYear <= endYr);

        var fields = [{name: 'year',type: 'string'},
        {name: 'ID',type: 'string'},{name: 'PARENT_ID',type: 'string'},
        {name: 'row',type: 'int'},
        {name: 'col0'},{name: 'isCurr_col0', type: 'boolean'},
        {name: 'col1'},{name: 'isCurr_col1', type: 'boolean'},
        {name: 'col2'},{name: 'isCurr_col2', type: 'boolean'},
        {name: 'col3'},{name: 'isCurr_col3', type: 'boolean'}
        ];

        var tempstore = gridlist.getStore(); // Created when TouchTreeGrid is instantiated

        var gridstore = Ext.create('Ext.data.TreeStore', {root: {children: []}, fields: fields});

        gridlist.setStore(gridstore);
        me.storeId = gridstore.getStoreId();  // Save so that we can destroy it in onDestroy() method when cleaning up

        if (!Ext.isEmpty(tempstore)) {
            Ext.data.StoreManager.unregister(tempstore);
        }

        gridlist.yearArr = yearArr; // Store for resuse on expand/collapse all

        var treejson = me.getTree(yearArr, null, gridcont.getDefaultCollapseLevel(), [], false, {});

        gridstore.suspendEvents();
        gridstore.removeAll();  // Mainly useful for expand/collapse all where we are rebuilding treestore
        gridstore.resumeEvents(true); // "discard queued events" improves performance when filtering and/or expanding all

        var gridloaded = gridstore.setData(treejson);  // setRoot() not working => http://www.sencha.com/forum/showthread.php?242257


        // Expand current month  (unless specifically collapsing all)
        var currRec = gridstore.getAt(currYrIdx);
        if (!Ext.isEmpty(currRec)) {currRec.set('expanded', true);}


        var refreshed = gridcont.doRefreshList(true);

        // Handle leafItemTap event from TouchTreeGrid for day selection processing
        gridcont.on('leafItemTap', me.onLeafItemTap, me);


        // Add listener when this component is destroyed to also destroy associated Store
        me.on('destroy', me.onDestroy, me);
    },

    onLeafItemTap: function(me, list, index, target, record, e) {

        var i, innerText, tgt, dt, doRefresh=false;

        innerText = e.target.innerText;
        var store = list.getStore();
        var gridcont = me;
        var dtPkr = list.parent.parent;

        tgt = e.getTarget(null,null,true);

        var myField = e.target.getAttribute('dataIndex');
        if (Ext.isEmpty(myField)) {
            myField = e.target.parentElement.getAttribute('dataIndex');  // check parent element also
            if (Ext.isEmpty(myField)) {return;}
            tgt=tgt.getParent();
        }


        var myDate = record.get(myField);
        if (Ext.isEmpty(myDate)) {return;}

        var myYear = record.get('year');

        var monthNames, monArr=[];
        monthNames = Ext.Date.monthNames;
        for (i=0; i< monthNames.length; i++) {
            monArr.push(Ext.Date.getShortMonthName(i));
        }

        //var monArr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
        var myMonth = monArr.indexOf(myDate);

        function pad(n, width, z) {
            z = z || '0';
            n = n + '';
            return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
        }

        var yearMoSel = myYear+pad(myMonth.toString(), 2);
        dtPkr.setYearMoSel(yearMoSel);

        // Compute backMonths from today for selection of new month in calling routine
        var today= Ext.Date.clearTime(new Date(Date(Ext.Date.now())), true);
        var firstdt = Ext.Date.clearTime(Ext.Date.getFirstDateOfMonth(today), true);

        var firstSelDt = new Date(parseInt(myYear), parseInt(myMonth), 1); // Create date as 1st day of current month and year
        var backMonths = Ext.Date.diff(firstSelDt, firstdt, Ext.Date.MONTH);

        dtPkr.setBackMonths(backMonths);
        dtPkr.setForwardMonths(-1*backMonths);
        dtPkr.setFirstSelDt(firstSelDt);

        tgt.toggleCls('yearMoSel-selected');  // temporarily toggle selection appearance

        // Slight delay so user sees selection in calendar
        setTimeout(function(){
            tgt.toggleCls('yearMoSel-selected');  // reset selection appearance
            dtPkr.fireEvent('yearMoSel', dtPkr, yearMoSel);
        },100);


    },

    onDestroy: function() {
        // Up to Developer to destroy each instance of CalendarPicker component upon selection.
        // This method does additional cleanup triggered off destroy event to clean up Stores, etc...
        var me = this;

        var storeId = me.storeId; // saved in createStore() method

        var stores = Ext.data.StoreManager;

        var gridstore = stores.lookup(storeId);
        if (!Ext.isEmpty(gridstore)) {
            stores.unregister(gridstore);
        }

    },

    getTree: function(list, rootId, expLevel, fldListArr, hasTopRoot, filterOpts) {
        expLevel = (Ext.isEmpty(expLevel) ? 99 : expLevel);  // Level for initial expansion ...Defaults to fully expanded if not provided

        if (fldListArr.length===0) {
            // Initialize fldListArr with default values from all data fields in first row of list[]
            for (fld in list[0]) {
                if (fld !== 'ID' && fld !== 'PARENT_ID') {  // These are auto-added in createTreeStructure()
                    fldListArr.push([fld, 0]);
                }
            }
        }
        var tree, root = {}, result = []; // fetch list from database
        root.ID = rootId;
        tree = {text : "."};
        result.push(this.createTreeStructure(tree, root, list, 1, expLevel, fldListArr, hasTopRoot, filterOpts).result);
        return result[0][0];
    },

    createTreeStructure: function(tree, root, list, level, expLevel, fldListArr, hasTopRoot, filterOpts) {
        var i=0, result = [], child, childList = [], children = [], temptree = {}, thisExp,
            has_nonfiltered_child = false;

        // Initialize Filter option variables
        filterOpts = (Ext.isEmpty(filterOpts) ? {} : filterOpts);
        var filtEnabled = (Ext.isEmpty(filterOpts.enabled) ? false : filterOpts.enabled);
        var filtNodesAsLeafs = (Ext.isEmpty(filterOpts.displayNodesWithAllMembersFilteredAsLeafs) ? true : filterOpts.displayNodesWithAllMembersFilteredAsLeafs);
        var filtFn = (Ext.isEmpty(filterOpts.filterFn) ? undefined : filterOpts.filterFn);

        if (level === 1 && hasTopRoot) {children = [list[0]];}  // Initial root
        else {children = this.getChildren(root, list, false);} //Fetch children

        var ln = children.length;

        for(i=0; i<ln;i++)
        {
            child = children[i];
            // Blank out categorized data above specified level as pre-specified in fldListArr
            // Example:  we may have 3 levels of cateogries.  Details sum to to the 3rd and perhaps 2nd level,
            //           but the 1st level should leave this column empty as not desired or applicable.
            for (var j=0; j< fldListArr.length; j++) {
                if (fldListArr[j][1] > 0 && fldListArr[j][1]>=level) {child[fldListArr[j][0]] = '';}
            }

            if(this.getChildren(child, list, true).length===0)
            {
                temptree = {LEVEL : level, ID : child.ID, PARENT_ID : child.PARENT_ID, leaf : true};
                this.assignMembers(fldListArr, temptree, child);

                // Push child to tree if filter not enabled or if passes filter condition
                if (!filtEnabled || filtFn(temptree)) {
                    childList.push(temptree);
                    tree["children"] = childList; // Add leaf to child array of the passed parent (also links arrays)
                    has_nonfiltered_child = true;
                }
            }
            else
            {
                thisExp = (level < expLevel ? true : false);
                temptree = {LEVEL : level, ID : child.ID, PARENT_ID : child.PARENT_ID, expanded : thisExp, leaf : false};
                this.assignMembers(fldListArr, temptree, child);

                // Push to children array now, but we will Pop it back later if this record and all children fail the filter condition
                childList.push(temptree);
                tree["children"] = childList;  // Add node to child array of passed parent (also links arrays)

                // Recursively create tree structure for the child since children exist.
                if (!this.createTreeStructure(temptree, child, list, level+1, expLevel, fldListArr, hasTopRoot, filterOpts).has_nonfiltered_child) {
                    // If child items are all fitlered, but node passes filter test then  load this node as leaf instead of node (unless specified otherwise)
                    if (!filtEnabled || filtFn(temptree)) {
                        tree.children[tree.children.length-1].leaf = filtNodesAsLeafs;
                        tree.children[tree.children.length-1].expanded = false;
                        tree.children[tree.children.length-1].expandable = false;  // disallow expand all children are filtered
                        has_nonfiltered_child = true;

                    } else {
                        tree.children.pop();    // If HAS_NONFILTERED_CHILD = false, then pop() per above
                    }
                } else {
                    has_nonfiltered_child = true;
                }

            }
        }

        result.push(tree);   // DON'T NEED TO DO THIS UNTIL DONE WITH FINAL ITERATION
        return {result: result, has_nonfiltered_child: has_nonfiltered_child};

    },

    assignMembers: function(fldListArr, treeObj, child) {
        for (var i=0; i< fldListArr.length; i++) {
            if (fldListArr[i][0]  !== 'ID' && fldListArr[i][0] !== 'PARENT_ID') {
                treeObj[fldListArr[i][0]] = child[fldListArr[i][0]];
            }
        }
    },

    getChildren: function(root, list, firstOnly) {
        var i=0, ln = list.length, result = [];
        for(i=0; i<ln;i++)
        {
            if(root.ID===list[i].PARENT_ID)
            {
                result.push(list[i]);
                if (firstOnly) {return result;} // Only checking if single child exists so abort upon first detection
            }
        }
        return result;
    }

});