Ext.ns('Aempower');
Ext.BLANK_IMAGE_URL = '/admin/lib/ext/resources/images/default/s.gif';
Ext.QuickTips.init();

// BEGIN Ext Bug Fixes

// END ext bug fixes

// BEGIN: 3rd Party Extensions

//http://www.extjs.com/forum/showthread.php?t=21331

Ext.ns('Ext.ux.grid');

Ext.ux.grid.GridSummary = function(config) {
        Ext.apply(this, config);
};

Ext.extend(Ext.ux.grid.GridSummary, Ext.util.Observable, {
    init : function(grid) {
        this.grid = grid;
        this.cm = grid.getColumnModel();
        this.view = grid.getView();

        var v = this.view;

        // override GridView's onLayout() method
        v.onLayout = this.onLayout;

        v.afterMethod('render', this.refreshSummary, this);
        v.afterMethod('refresh', this.refreshSummary, this);
        v.afterMethod('syncScroll', this.syncSummaryScroll, this);
        v.afterMethod('onColumnWidthUpdated', this.doWidth, this);
        v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);
        v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);

        // update summary row on store's add/remove/clear/update events
        grid.store.on({
            add: this.refreshSummary,
            remove: this.refreshSummary,
            clear: this.refreshSummary,
            update: this.refreshSummary,
            scope: this
        });

        if (!this.rowTpl) {
            this.rowTpl = new Ext.Template(
                '<div class="x-grid3-summary-row x-grid3-gridsummary-row-offset">',
                    '<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" {attr}>{value}</div>',
                "</td>"
            );
            this.cellTpl.disableFormats = true;
        }
        this.cellTpl.compile();
    },

    calculate : function(rs, cm) {
        var data = {}, cfg = cm.config;
        for (var i = 0, len = cfg.length; i < len; i++) { // loop through all columns in ColumnModel
            var cf = cfg[i], // get column's configuration
                cname = cf.dataIndex; // get column dataIndex

            // initialise grid summary row data for
            // the current column being worked on
            data[cname] = 0;

            if (cf.gridSummaryType) {
                for (var j = 0, jlen = rs.length; j < jlen; j++) {
                    var r = rs[j]; // get a single Record
                    data[cname] = Ext.ux.grid.GridSummary.Calculations[cf.gridSummaryType](r.get(cname), r, cname, data, j);
                }
            }
        }

        return data;
    },

    onLayout : function(vw, vh) {
        if (Ext.type(vh) != 'number') { // handles grid's height:'auto' config
            return;
        }
        // note: this method is scoped to the GridView
        if (!this.grid.getGridEl().hasClass('x-grid-hide-gridsummary')) {
            // readjust gridview's height only if grid summary row is visible
            this.scroller.setHeight(vh - this.summary.getHeight());
        }
    },

    syncSummaryScroll : function() {
        var mb = this.view.scroller.dom;

        this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft;
        this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)
    },

    doWidth : function(col, w, tw) {
        var s = this.view.summary.dom;

        s.firstChild.style.width = tw;
        s.firstChild.rows[0].childNodes[col].style.width = w;
    },

    doAllWidths : function(ws, tw) {
        var s = this.view.summary.dom, wlen = ws.length;

        s.firstChild.style.width = tw;

        var cells = s.firstChild.rows[0].childNodes;

        for (var j = 0; j < wlen; j++) {
            cells[j].style.width = ws[j];
        }
    },

    doHidden : function(col, hidden, tw) {
        var s = this.view.summary.dom,
            display = hidden ? 'none' : '';

        s.firstChild.style.width = tw;
        s.firstChild.rows[0].childNodes[col].style.display = display;
    },

    renderSummary : function(o, cs, cm) {
        cs = cs || this.view.getColumnData();
        var cfg = cm.config,
            buf = [],
            last = cs.length - 1;

        for (var i = 0, len = cs.length; i < len; i++) {
            var c = cs[i], cf = cfg[i], p = {};

            p.id = c.id;
            p.style = c.style;
            p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');

            if (cf.gridSummaryType || cf.gridSummaryRenderer) {
                p.value = (cf.gridSummaryRenderer || c.renderer)(o.data[c.name], p, o);
            } else {
                p.value = '';
            }
            if (p.value == undefined ) p.value = "*";
            buf[buf.length] = this.cellTpl.apply(p);
        }

        return this.rowTpl.apply({
            tstyle: 'width:' + this.view.getTotalWidth() + ';',
            cells: buf.join('')
        });
    },

    refreshSummary : function() {
        var g = this.grid, ds = g.store,
            cs = this.view.getColumnData(),
            cm = this.cm,
            rs = ds.getRange(),
            data = this.calculate(rs, cm),
            buf = this.renderSummary({data: data}, cs, cm);

        if (!this.view.summaryWrap) {
            this.view.summaryWrap = Ext.DomHelper.insertAfter(this.view.scroller, {
                tag: 'div',
                cls: 'x-grid3-gridsummary-row-inner'
            }, true);
        }
        this.view.summary = this.view.summaryWrap.update(buf).first();
    },

    toggleSummary : function(visible) { // true to display summary row
        var el = this.grid.getGridEl();

        if (el) {
            if (visible === undefined) {
                visible = el.hasClass('x-grid-hide-gridsummary');
            }
            el[visible ? 'removeClass' : 'addClass']('x-grid-hide-gridsummary');

            this.view.layout(); // readjust gridview height
        }
    },

    getSummaryNode : function() {
        return this.view.summary
    }
});
Ext.reg('gridsummary', Ext.ux.grid.GridSummary);

/*
 * all Calculation methods are called on each Record in the Store
 * with the following 5 parameters:
 *
 * v - cell value
 * record - reference to the current Record
 * colName - column name (i.e. the ColumnModel's dataIndex)
 * data - the cumulative data for the current column + summaryType up to the current Record
 * rowIdx - current row index
 */
Ext.ux.grid.GridSummary.Calculations = {
    sum : function(v, record, colName, data, rowIdx) {
        return data[colName] + Ext.num(v, 0);
    },

    count : function(v, record, colName, data, rowIdx) {
        return rowIdx + 1;
    },

    max : function(v, record, colName, data, rowIdx) {
        return Math.max(Ext.num(v, 0), data[colName]);
    },

    min : function(v, record, colName, data, rowIdx) {
        return Math.min(Ext.num(v, 0), data[colName]);
    },

    average : function(v, record, colName, data, rowIdx) {
        var t = data[colName] + Ext.num(v, 0), count = record.store.getCount();
        return rowIdx == count - 1 ? (t / count) : t;
    },
    
    remote : function(v, record, colName, data, rowIdx) {
        var jsonData = record.store.reader.jsonData;
        return eval("jsonData." + colName + "Total");
    }
}

// END: 3rd Party Extensions

// BEGIN Ext Extensions

Ext.ux.FieldHelp = Ext.extend(Object, (function(){

    function afterFieldRender() {
			if (this.helpText) {
				if (this.getEl().up('div.x-form-item')) {
					// NOTE: This shouldn't be necessary, but for some reason using the style attribute of
					//       the image doesn't work right in IE8. It is ignored initially but then applied
					//       apparently on focus/blur.
					var spacerImage = this.getEl().up('div.x-form-item').child('div.x-form-element').createChild({
						tag: 'span', html:'&nbsp;'
					});
					var helpImage = this.getEl().up('div.x-form-item').child('div.x-form-element').createChild({
						tag: 'img',
						src: '/admin/resources/help.png'
					});
					Ext.QuickTips.register({
						target: helpImage,
						title: '',
						text: this.helpText,
						enabled: true,
						dismissDelay: 30000
					});
				}
			}
    }

    return {
        constructor: function(t) {
            this.helpText = t;
        },
        init: function(f) {
            f.helpText = this.helpText;
            f.afterRender = f.afterRender.createSequence(afterFieldRender);
        }
    };

})());

//http://www.extjs.com/forum/showthread.php?p=385087#post385087

Ext.ux.Report = Ext.extend(Ext.Component, {
    autoEl: {tag: 'iframe', cls: 'x-hidden', src: Ext.SSL_SECURE_URL},
    load: function(config){
        this.getEl().dom.src = config.url + (config.params ? '?' + Ext.urlEncode(config.params) : '');
    }
});
Ext.reg('ux.report', Ext.ux.Report);

// http://www.sencha.com/forum/showthread.php?37923-Too-much-data-for-cookies-what-else&highlight=stateprovider

Ext.namespace('Ext.ux','Ext.ux.state');

Ext.ux.state.PersistStateProvider = function(config) {
	
	Ext.ux.state.PersistStateProvider.superclass.constructor.call(this);
	this.store = new Persist.Store('pstore');
	Ext.apply(this, config);
};

Ext.extend(Ext.ux.state.PersistStateProvider, Ext.state.Provider, {

	set: function(name, value) {

		if (typeof value == "undefined" || value === null) {
			this.clear(name);
			return;
		}
		
		var val = this.encodeValue(value);
		this.store.set(name, val);
		this.fireEvent("statechange", this, name, value);
    },
	
	get: function(name, defaultValue) {
		
		var val = null;
		this.store.get(name, function(k, v) {
			if (k) {
				val = v;
			}
		});

		return this.decodeValue(val);
	},

    clear: function(name) {
		this.store.remove(name);
		this.fireEvent("statechange", this, name, null);
	}
});

//http://www.yannlaviolette.com/2010/04/extjs-show-hide-textfield-in-formpanel.html
/**
 * Overrides the Ext.form.Field to add some functionalities 
 * @author Yann Laviolette
 *
 */
Ext.override(Ext.form.Field, {
    /**
     * Show the container including the label
     */
    showContainer: function() {
        this.enable();
        this.show();
 
        if (!Ext.isEmpty(this.getEl())) {
            this.getEl().up('.x-form-item').setDisplayed(true); // show entire container and children (including label if applicable)
        }
 
 
    },
 
    /**
     * Hide the container including the label
     */
    hideContainer: function() {
        this.disable(); // for validation
        this.hide();
 
        if (!Ext.isEmpty(this.getEl())) {
            this.getEl().up('.x-form-item').setDisplayed(false); // hide container and children (including label if applicable)
        }
    },
 
    /**
     * Hide / Show the container including the label
     * @param visible
     */
    setContainerVisible: function(visible) {
        if (this.rendered) {
            if (visible) {
                this.showContainer();
            } else {
                this.hideContainer();
            }
        }
 
        return this;
    }
 
}); 

// END Ext Extensions


// BEGIN VTYPES

// END VTYPES


// BEGIN Aeris Extensions

//
// ---------------- Aempower.ErrorHandler ------------------
//
// Generic functions to handle the various forms of ext errors

Aempower.ErrorHandler = {
   // This is used for 'action' errors (e.g., form posts)
   actionFailureHandler: function(action) {
     switch (action.failureType) {
         case Ext.form.Action.CONNECT_FAILURE:
            this.showError("Received invalid response from server");
            break;
         case Ext.form.Action.SERVER_INVALID:
            this.showError("One or more fields contained invalid values");
            break;
         default:
            Aempower.ErrorHandler.showException(action.result.message, action.result.stacktrace);
      }
   },
   // This is used to handle loadexceptions (e.g., Stores)
   loadExceptionHandler: function(proxy, options, response, e) {
	   if (response.isTimeout) {
	         Aempower.ErrorHandler.showError("Timeout while waiting for response. Try the Excel download option for larger results.");		   
	   }
	   else {
         var responseObj =  eval('(' + response.responseText + ')');
         Aempower.ErrorHandler.showException(responseObj.message, responseObj.stacktrace);
	   }
   },
   // helper function
   showError: function(msg) {
      Ext.Msg.show({
         title:'Error Occurred', 
         width:850,
         minWidth:850,
         maxWidth:1000,
         msg: msg,
         icon:Ext.Msg.ERROR,
         buttons:Ext.Msg.OK
     });
      
   },
   // helper function
   showException: function(message, stacktrace) {
         if (!message) message = 'No additional information available';
         if (!stacktrace) stacktrace = 'No additional details avaialable';
         var msg = 'Action failed with the following message: ' + message +
         '<br><br><a href="#" onclick="javascript:document.getElementById(\'stacktrace\').className=\'ext-mb-text\'">Show Debugging Information</a>' +
         '<div id="stacktrace" class="invisible"><br><PRE>' + stacktrace + '</PRE></div>';
         Aempower.ErrorHandler.showError(msg);
   }
};
//
// ------------- END ErrorHandler ----------------------------------
//

	// BEGIN: BasicCombo
	// Intended to be used for combo boxes that are most like the old HTML SELECTs
	
	Aempower.BasicCombo = Ext.extend(Ext.form.ComboBox, {
		 
	    // PATTERN: default configuration (can be changed when instantiated)
		forceSelection: true,
		selectOnFocus: true,
		triggerAction: 'all',
	    
	    // PATTERN: constructor if you need it, e.g. if you need listeners
	    constructor:function(config) {
		
	        // PATTERN: parent constructor call pre-processing - configure listeners here
	        config = config || {};
	        config.listeners = config.listeners || {};
	        Ext.applyIf(config.listeners, {
	            // PATTERN: add listeners config here
	        });

	        // PATTERN: call parent constructor
	        Aempower.BasicCombo.superclass.constructor.call(this, config);

	        // PATTERN: parent constructor call post-processing

	    }, // eo function constructor
	
	    initComponent:function() {
	 
	        // PATTERN: hard coded config (it cannot be changed while instantiating)
	        // {{{
	        var config = {
	        }; // eo config object
	 
	        // PATTERN: apply config
	        Ext.apply(this, Ext.apply(this.initialConfig, config));
	        // }}}
	 
	        // PATTERN: call parent
	        Aempower.BasicCombo.superclass.initComponent.apply(this, arguments);
	 
	        // PATTERN: parent call post-processing, e.g. install event handlers
	 
	    } // eo function initComponent

	    ,onRender:function() {
	 
	        // PATTERN: parent call pre-processing
	 
	        // PATTERN: call parent
	        Aempower.BasicCombo.superclass.onRender.apply(this, arguments);
	 
	        // PATTERN: parent call post-processing, e.g. install event handlers on rendered components
	 
	    } // eo function onRender
	 
	    // PATTERN: any other added/overriden methods
	    
	}); // eo extend
	 
	// PATTERN: register xtype
	Ext.reg('basicCombo', Aempower.BasicCombo); 
	 
	// END: BasicCombo
	
	
	// BEGIN: AerisDisplayField
	// Replaces regular form.DisplayField which has some quirks; could this be done with overrides instead?
	
	Aempower.AerisDisplayField = Ext.extend(Ext.form.DisplayField, {
		 
	    // PATTERN: default configuration (can be changed when instantiated)
		style: {padding:'4px'}, 	// Fixes a label alignment issue
	    
	    // PATTERN: constructor if you need it, e.g. if you need listeners
	    constructor:function(config) {
		
	        // PATTERN: parent constructor call pre-processing - configure listeners here
	        config = config || {};
	        config.listeners = config.listeners || {};
	        Ext.applyIf(config.listeners, {
	            // PATTERN: add listeners config here
	        });

	        // PATTERN: call parent constructor
	        Aempower.AerisDisplayField.superclass.constructor.call(this, config);

	        // PATTERN: parent constructor call post-processing

	    }, // eo function constructor
	
	    initComponent:function() {
	 
	        // PATTERN: hard coded config (it cannot be changed while instantiating)
	        // {{{
	        var config = {
	        	// Fix label hide issue
	        	onHide: function(){this.getEl().up('.x-form-item').setDisplayed(false);}, 
		        onShow: function(){this.getEl().up('.x-form-item').setDisplayed(true);}
	        }; // eo config object
	 
	        // PATTERN: apply config
	        Ext.apply(this, Ext.apply(this.initialConfig, config));
	        // }}}
	 
	        // PATTERN: call parent
	        Aempower.AerisDisplayField.superclass.initComponent.apply(this, arguments);
	 
	        // PATTERN: parent call post-processing, e.g. install event handlers
	 
	    } // eo function initComponent

	    ,onRender:function() {
	 
	        // PATTERN: parent call pre-processing
	 
	        // PATTERN: call parent
	        Aempower.AerisDisplayField.superclass.onRender.apply(this, arguments);
	 
	        // PATTERN: parent call post-processing, e.g. install event handlers on rendered components

	 
	    } // eo function onRender
	 
	    // PATTERN: any other added/overriden methods
	    
	}); // eo extend
	 
	// PATTERN: register xtype
	Ext.reg('aerisDisplayField', Aempower.AerisDisplayField); 
	 
	// END: AerisDisplayField
	
// END: Aeris Extensions

	
// BEGIN: Aeris Common Functions

	// Boolean renderer
	function formatYesNo(value) {  
	    return value ? 'Yes': 'No';  
	}
	
	function isEmpty( inputStr ) { if ( null == inputStr || "" == inputStr ) { return true; } return false; }
	
	// Render quicktip for full description
	function tipRenderer(v, params) {
        params.attr = 'ext:qtip="' + v + '"';
        return v;
    }
	
	function wrapRenderer(v, params) {
        params.attr = 'style="white-space: normal;"';
        return v;
    }
	
	function combineJSON() {
		var a = arguments, b = [], i, f, g, c = {};
		for (i in (new Array(a.length+1)).join(1).split("")) b.push(a[i]);
		for (f in b) for (g in b[f]) c[g] = b[f][g];
		return c;
		};
		
	function startReport(form, description, reportFormat, filename) {
  		
		// First get a new user report ID (via StartReport)	  
  		var conn = new Ext.data.Connection();
  		conn.request({
	    	    url: '/admin/report/StartReport.aep2',
	    	    method: 'POST',
	    	    params: {
  					"description": description, 
  			        "reportFormat": reportFormat,
  			        "filename": filename
  			    },
	    	    success: function(response, options) {
  			    
  			    	// AFTER the start succeeds and we have a user report ID, start the status loop
  			    	var responseData = Ext.util.JSON.decode(response.responseText);
  			    	form.submit({
						params: {
  			    			userReportId: responseData.userReportId,
  			    			mode: "download"
  			    		} 			    	   
	    	        });
					window.open('/admin/report/CheckReportStatus.aep2?userReportId=' + responseData.userReportId, '_blank', 
				    'status=0,toolbar=0,location=0,menubar=0,directories=0,resizable=1,scrollbars=1,height=250,width=400');
	    	        
	    	    },
	    	    failure: function(form, action) {
	    	    	Ext.Msg.alert('Error', 'Error: failed to start report');
	    	    }
  		});
  		   		
		
	}
	
	function downloadGridToExcel(formName, gridName, description, format, filename, addlValues) {
		
		var form = Ext.getCmp(formName).getForm();
		var formValues = {}; 
		
		// Get a list of all the visible columns
		var grid = Ext.getCmp(gridName);
	    var visibleCols = grid.getColumnModel().getColumnsBy(
	     function (columnConfig, index)
	     {
	       if (columnConfig.hidden || columnConfig.alwaysDownload)
	          return false;
	       else
	          return true;
	     }
	    );
	    
	    var col;
	    var visibleColNames = "";
	    var visibleColFields = "";
	    for (col = 0; col< visibleCols.length; col++)
	    {
	    	visibleColNames += visibleCols[col].header + ",";
	    	visibleColFields += visibleCols[col].dataIndex + ",";
	    }
	    formValues.columnNames = visibleColNames;
	    formValues.columnFields = visibleColFields;
	    
	    var sortState = grid.store.getSortState();
	    if (typeof sortState != "undefined") {
		    formValues.sort = sortState.field;
		    formValues.dir = sortState.direction;
	    }
	    
	    if (typeof addlValues != "undefined") {
	    	formValues = combineJSON(formValues, addlValues);
	    }
	    form.baseParams = formValues;
	    	    
	    startReport(form, description, format, filename);
	    
	}
	// END: Aeris Common Functions


