/*
    Document   : DataGrid
    Created on : 10-Aug-2009, 14:55:26
    Author     : Andreas Hadjigeorgiou
    Description: DataGrid is a combination of Grid Extensions

    Used: Ext.ux.grid.MetaGrid Extension Class
          Extension of Ext.grid.EditorGridPanel to handle metaData.
          @author Michael LeComte

*/

Ext.namespace('Ext.ux.grid');

/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/

var Base64 = (function() {

    // private property
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    // private method for UTF-8 encoding
    function utf8Encode(string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        return utftext;
    }

    // public method for encoding
    return {
        encode : (typeof btoa == 'function') ? function(input) { return btoa(utf8Encode(input)); } : function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;
            input = utf8Encode(input);
            while (i < input.length) {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);
                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }
                output = output +
                keyStr.charAt(enc1) + keyStr.charAt(enc2) +
                keyStr.charAt(enc3) + keyStr.charAt(enc4);
            }
            return output;
        }
    };
})();

Ext.ux.grid.LinkButton = Ext.extend(Ext.Button, {
    template: new Ext.Template(
        '<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
        '<td class="x-btn-left"><i> </i></td><td class="x-btn-center"><a class="x-btn-text" href="{1}" target="{2}">{0}</a></td><td class="x-btn-right"><i> </i></td>',
        "</tr></tbody></table>"),

    onRender:   function(ct, position){
        var btn, targs = [this.text || ' ', this.href, this.target || "_self"];
        if(position){
            btn = this.template.insertBefore(position, targs, true);
        }else{
            btn = this.template.append(ct, targs, true);
        }
        var btnEl = btn.child("a:first");
        btnEl.on('focus', this.onFocus, this);
        btnEl.on('blur', this.onBlur, this);

        this.initButtonEl(btn, btnEl);
        Ext.ButtonToggleMgr.register(this);
    },

    onClick : function(e){
        if(e.button != 0){
            return;
        }
        if(!this.disabled){
            this.fireEvent("click", this, e);
            if(this.handler){
                this.handler.call(this.scope || this, this, e);
            }
        }
    }

});


Ext.ux.grid.DataGrid = Ext.extend(Ext.grid.EditorGridPanel, {

    /**
     * Default Configuration Options
     */
    initPreview: true,
    loadMask: {
        msg: 'Loading ...'
    },
    maskEmpty: false,
    newKey: -1,
    perPage: 30,
    primaryKey: 'id',
    stripeRows: true,
    trackMouseOver: true,
    border: true,
    rowNumberer: true,
    columnLines:true,
    checkboxSelModel: false,
    //dataform: this.dataform,
    forceFit: false,
    //recordWnd: this.recordWnd,
    //store: this.store,
    type: "grid",
    displayOnly: false,
    //related: {},

    initComponent: function(){
        Ext.applyIf(this, {
            plugins: [],
            pagingPlugins: [],
            // customize view config
            viewConfig: {
                emptyText: 'No Data',
                forceFit: this.forceFit
            }
        });

        if (this.filters) {
            this.filters = new Ext.grid.GridFilters({
        	    filters:[]
            });
            this.plugins.push(this.filters);
            this.pagingPlugins.push(this.filters);
        }

        if(this.store==null) {
            this.store = new Ext.data.Store({
                url: this.url,
                // create reader (reader will be further configured through metaData sent by server)
                reader: new Ext.data.JsonReader(),
                //writer: new Ext.data.JsonWriter(),
                baseParams: this.baseParams,
                proxy: new Ext.data.HttpProxy({
                    url: this.url, method: 'post'
                }),
                remoteSort: true,
                listeners: {
                    // register to the store's metachange event
                    metachange: {
                        fn: this.onMetaChange,
                        scope: this
                    },
                    exception : function(proxy, type, action, options, res, arg) {
                        //console.warn(arguments);
                        if (type === 'remote') {
                            Ext.Msg.show({
                                title: 'REMOTE EXCEPTION',
                                msg: res.message,
                                icon: Ext.MessageBox.ERROR
                            });
                        }
                    },
                    load: {
                        fn: this.onLoad,
                        scope: this
                    },
                    scope: this
                }
            });
                
            this.store.sort = this.store.sort.createInterceptor(this._new_storeSort);
        }

        this.sm = new Ext.grid.RowSelectionModel({
            singleSelect: true,
            listeners: {
                /*rowselect: function(smObj, rowIndex, record) {
                    this.selectedIndex = rowIndex;
                },*/
                selectionchange: function(sm) {
                    if (sm.getCount()) {
                        if(!this.grid.displayOnly) {
                            this.grid.removeButton.enable();
                            // Copy
                            this.grid.copyButton.enable();
                        }
                    } else {
                        if(!this.grid.displayOnly) {
                            this.grid.removeButton.disable();
                            // Copy
                            this.grid.copyButton.disable();
                            //this.selectedIndex = -1;
                        }
                    }
                }
            }
        });

        //Create top bar
        this.toolbar = new Ext.Toolbar({
            items: [
                {
                    text: 'Add Record',
                    iconCls: 'grid_add',
                    tooltip:'Add new record',
                    ref: '../addButton',
                    listeners:{
                        click:{scope:this, buffer:200, fn:this.addRecord}
                    }
                },
                {
                    text: 'Delete Record',
                    iconCls: 'grid_delete',
                    tooltip:'Remove the selected item',
                    // Place a reference in the GridPanel
                    ref: '../removeButton',
                    disabled: true,
                    listeners:{
                        click:{scope:this, buffer:200, fn:this.removeRecord}
                    }
                },
                {
                    text: 'Copy Record',
                    iconCls: 'icon-copy',
                    tooltip:'Copy selected item',
                    // Place a reference in the GridPanel
                    ref: '../copyButton',
                    disabled: true,
                    listeners:{
                        click:{scope:this, buffer:200, fn:this.copyRecord}
                    }
                }/*,
                {
                    id: 'grid-excel-button',
                    text: 'Excel',
                    scope:this,
                    handler: function(){
                        document.location='data:application/vnd.ms-excel;base64,' +Base64.encode(this.getExcelXml());
                    }

                }*/
            ]
        });

        if(!this.displayOnly)
            this.tbar = this.toolbar;

        //Create Paging Toolbar
        this.pagingToolbar = new Ext.PagingToolbar({
            id: this.id + 'pager',
            store: this.store,
            //pageSize: this.options.pageSize,//makes this global for all who need it
            pageFit: true,
            pageSize: this.perPage || 30, //default is 20
            plugins: this.pagingPlugins,
            displayInfo: true,//default is false (to not show displayMsg)
            displayMsg: 'Displaying {0} - {1} of {2}',
            emptyMsg: "No data to display"//display message when no records found
        });

        //Add a bottom bar
        if(this.type !== 'mtm' && this.type !== 'lookup'){
            this.bbar = this.pagingToolbar;
        }
        
        if (this.columns && (this.columns instanceof Array)) {
            this.colModel = new Ext.grid.ColumnModel(this.columns);
            delete this.columns;
        }

        // Create a empty colModel if none given
        if (!this.colModel) {
            this.colModel = new Ext.grid.ColumnModel([]);
        }

        this.colModel.defaultSortable = true;

        Ext.ux.grid.DataGrid.superclass.initComponent.call(this);


        /*if(this.dataform === undefined) {
            this.dataform = new Ext.ux.form.DataForm({
               title: 'test'
            });
        }*/
        
        /**
         * Grid Popup Window
         */
        this.recordWnd = new Ext.Window({
            id: this.id + 'DataForm',
            closable: true,
            layout: 'fit',
            //autoHide: true,
            modal: true,
            closeAction: 'hide',
            resizable: true,
            plain: true,
            border: false,
            constrain: true,
            forceLayout: true,
            hidden: true,
            //autoHeight: true,
            //autoWidth: true,
            //width:100,
            buttons: [{
                        text: 'Save',
                        scope:this,
                        formBind: true,
                        handler: this.onSaveForm
                    },{
                        text: 'Cancel',
                        scope:this,
                        handler: this.onCancelForm
                    }]
        });

        /**
         * n-n Relation lookup
         *
         */
        if(this.type == 'mtm') {
            this.lookupWnd = new Ext.Window({
                id: this.id + 'DataForm',
                closable: true,
                //layout: 'fit',
                autoHide: true,
                modal: true,
                closeAction: 'hide',
                resizable: true,
                plain: true,
                border: false,
                constrain: true,
                forceLayout: true,
                //autoHeight: true,
                //autoWidth: true,
                width:600,
                height:400,
                buttons: [{
                            text: 'Select',
                            scope:this,
                            formBind: true,
                            handler: this.onSelectLookup
                        },{
                            text: 'Cancel',
                            scope:this,
                            handler: this.onCancelLookup
                        }]
            });

            this.lookupWnd.on('show', function() {
               var lugrid = this.items.get(0);

               if(lugrid.rendered) {
                   lugrid.loadLookup();
               }
            });
        }
        else {
            /**
             * Must be in MetaChange Event
             * Get Relations Property and build the tab panel
             * with the related entities grid
             */
            //alert(this.relations);
            if(this.dataform !== undefined && this.dataform.relations !== undefined && this.dataform.relations.length > 0) {

                var tabPanel = new Ext.TabPanel({
                    id: this.dataform.id + '_relationsPanel',
                    activeTab: 0,
                    anchor: "100%",
                    plain:true,
                    height: 200
                });

                tabPanel.on('beforetabchange', function(tPanel, newTab, curTab) {
                    //newTab.loadData();
                });

                Ext.each(this.dataform.relations, function(rel, index) {

                   var panelItem =  new Ext.ux.grid.DataGrid({
                        id: rel.id,
                        type: rel.type,
                        displayOnly: rel.displayOnly !== undefined ? rel.displayOnly : false,
                        title: rel.title,
                        url: rel.url,
                        baseParams: rel.baseParams,
                        perPage: 20,
                        primaryKey: rel.primaryKey,
                        related: rel.related,
                        postFields: rel.postFields,
                        renderers: this.renderers
                    });

                    panelItem.on('afterrender',function() {
                        //alert('test');
                        //var lgrid = tabspanel.get(i);
                        //this.store.baseParams.filter = this.store.baseParams.table + '.' + this.primaryKey + '=' + rec.get(this.primaryKey);
                        this.loadGrid();
                    });

                    /*panelItem.on('show',function() {
                        //alert('test');
                        //if(this.rendered)
                        //    panelItem.loadData();
                    });

                    panelItem.on('beforehide', function() {
                        //this.destroy();
                    });*/

                    tabPanel.add(panelItem);
                }, this);

                this.dataform.add(tabPanel);
                this.dataform.doLayout();
            }

            this.recordWnd.on({
                show: {scope: this, fn: function(h) {
                   //alert('testr');
                   if(this.dataform !== undefined) {
                       var tabspanel = Ext.getCmp(this.dataform.id + '_relationsPanel');

                       if(tabspanel !== undefined) {
                           for(var i=0; i<tabspanel.items.length;i++){
                               var lgrid = tabspanel.get(i);
                               //alert(lgrid.title);
                               if(lgrid.rendered) {
                                    lgrid.loadData();
                               }
                           }
                       }
                   }
               }}
            });
        }

    },
    
    onRender: function() {
        Ext.ux.grid.DataGrid.superclass.onRender.apply(this, arguments);

        if(!this.displayOnly && this.dataform !== undefined) {
            //this.dataform.url = this.url;
            //this.dataform.doLayout();
            this.recordWnd.title = this.dataform.title;
            this.recordWnd.add(this.dataform);
            this.recordWnd.width = this.dataform.width;
            this.recordWnd.height = this.dataform.height;

            this.on('rowdblclick', function(grid, rowIndex, e) {
               if(!this.allowedit) {
                   Ext.Msg.alert("Security Info", "Restricted Priority");
                   return;
               }

               var rec = this.store.getAt(rowIndex);

               var tabspanel = Ext.getCmp(this.dataform.id + '_relationsPanel');

               if(tabspanel !== undefined) {
                   for(var i=0; i<tabspanel.items.length;i++){
                       var lgrid = tabspanel.get(i);

                       lgrid.store.baseParams.filter = lgrid.store.baseParams.table + '.' + this.primaryKey + '=' + rec.get(this.primaryKey);
                       //lgrid.loadGrid();
                       //alert('test');
                   }
               }

               this.recordWnd.show(/*grid.getView().getRow(rowIndex)*/);
               this.dataform.getForm().loadRecord(this.getSelectionModel().getSelected());

            });
        }
        else {
            if(this.type == 'mtm') { // n-n relation
                this.lookupWnd.title = this.related.title;
                var lookupGrid = new Ext.ux.grid.DataGrid({
                    id: this.id + '_lookup',
                    type: 'lookup',
                    displayOnly: true,
                    url: this.related.url,
                    baseParams: this.related.baseParams,
                    perPage: 20,
                    viewConfig:{forceFit:true},
                    loadMask: true,
                    width: 500,
                    height: 400,
                    renderers: this.renderers
                });

                /*lookupGrid.on('afterrender',function() {
                    this.loadGrid();
                });*/

                lookupGrid.on({
                    rowdblclick : {
                        scope: this,
                        fn: function(grid, rowIndex, e) {
                            this.onSelectLookup();
                        }
                    }
                });

                /*lookupGrid.on('show', function() {
                    alert('test');
                    //if(this.rendered)
                        this.loadData();
                });*/

                this.lookupWnd.add(lookupGrid);
            }
        }

    },
    onMetaChange: function(store, meta){
        // avoid loading meta on store reload
        delete (store.lastOptions.params.meta);

        var columns = [], editor, plugins, storeCfg, l, convert;

        // set primary Key
        this.primaryKey = meta.id;

        // action restrictions
        this.allowadd = meta.allowadd == undefined ? true : meta.allowadd;
        this.allowedit = meta.allowedit == undefined ? true : meta.allowedit;
        this.allowdelete = meta.allowdelete == undefined ? true : meta.allowdelete;

        // Row Numberer PlugIn
        if(this.rowNumberer) { columns.push(new Ext.grid.RowNumberer()); }
        // Row Checkbox Plugin
        if(this.checkboxSelModel) { columns.push(new Ext.grid.CheckboxSelectionModel()); }

        // the metaData.fields property in the returned data packet will be used to:
        // 1. internally create a Record constructor using the array of field definitions:
        // this.recordType = Ext.data.Record.create(o.metaData.fields);
        // both the reader and the store will have a recordType property
        // 2. reconfigure the column model:
        Ext.each(meta.fields, function(col){

            // if plugin specified
            if (col.plugin !== undefined) {
                columns.push(eval(col.plugin));
                return;
            }

            // if header property is not specified do not add to column model
            //-- NOT NEDDED --///
            if (col.header == undefined) {
                return;
            }

            // if not specified assign dataIndex = name
            if (typeof col.dataIndex == "undefined") {
                col.dataIndex = col.name;
            }

            //if using gridFilters extension
            if (this.filters) {
                if (col.filter !== undefined) {
                    if ((col.filter.type !== undefined)) {
                        col.filter.dataIndex = col.dataIndex;
                        this.filters.addFilter(col.filter);
                    }
                }
                delete col.filter;
            }

            // if renderer specified in meta data
            if (typeof col.renderer == "string") {

                // if specified Ext.util or a function will eval to get that function
                if (col.renderer.indexOf("Ext") < 0 && col.renderer.indexOf("function") < 0) {
                    //                    col.renderer = this.setRenderer(col.renderer);
                    //col.renderer = this.setRenderer(col.renderer);
                    if(this[col.renderer] != undefined)
                        col.renderer = this[col.renderer].createDelegate(this);
                    else {
                        //for(var i=0; i<this.renderers.length; i++) {
                        //    if(col.renderer == this.renderers[i])
                                col.renderer = this.renderers[col.renderer].createDelegate(this);
                        //}
                    }
                }
                else {
                    //col.renderer = eval(col.renderer);
                    col.renderer = this[col.renderer].createDelegate(this);
                }
            }

            
             // if want to modify default column id
             //if(typeof col.id == "undefined"){
             //col.id = 'c' + i;
             //}
             
            // if listeners specified in meta data
            l = col.listeners;
            if (typeof l == "object") {
                for (var e in l) {
                    if (typeof e == "string") {
                        for (var c in l[e]) {
                            if (typeof c == "string") {
                                l[e][c] = eval(l[e][c]);
                            }
                        }
                    }
                }
            }

            // if convert specified assume it's a function and eval it
            if (col.convert) {
                col.convert = eval(col.convert);
            }

            editor = col.editor;

            if (editor) {

                switch (editor.xtype) {
                    case 'checkbox':
                        delete (col.editor);
                        delete (col.renderer);
                        col = new Ext.grid.CheckColumn(col);
                        col.editor = Ext.ComponentMgr.create(editor, 'textfield');
                        col.init(this);
                        break;
                    case 'combo':
                        if (col.editor.store) {
                            storeCfg = col.editor.store;
                            col.editor.store = new Ext.data[storeCfg.storeType](storeCfg.config);
                        }
                        col.editor = Ext.ComponentMgr.create(editor, 'textfield');
                        break;
                    case 'datefield':
                        col.editor = Ext.ComponentMgr.create(editor, 'textfield');
                        break;
                    default:
                        col.editor = Ext.ComponentMgr.create(editor, 'textfield');
                        break;
                }

                plugins = editor.plugins;
                delete (editor.plugins);

                //configure any listeners specified for this column's editor
                l = editor.listeners;
                if (typeof l == "object") {
                    for (var e in l) {
                        if (typeof e == "string") {
                            for (var c in l[e]) {
                                if (typeof c == "string") {
                                    l[e][c] = eval(l[e][c]);
                                }
                            }
                        }
                    }
                }
            }

            if (plugins instanceof Array) {
                editor.plugins = [];
                Ext.each(plugins, function(plugin){
                    plugin.name = plugin.name || col.dataIndex;
                    editor.plugins.push(Ext.ComponentMgr.create(plugin));
                });
            }

            if(col.sortable == undefined)
                col.sortable = true;
            // add column to colModel config array
            columns.push(col);

        }, this); // end of columns loop

        var cm = new Ext.grid.ColumnModel(columns);

        if (meta.defaultSortable != undefined) {
            cm.defaultSortable = meta.defaultSortable;
        }

        // can change the store if we need to also, perhaps if we detect a groupField
        // config for example
        // meta.groupField or meta.storeCfg.groupField;
        var store = this.store;

        // Reconfigure the grid to use a different Store and Column Model. The View
        // will be bound to the new objects and refreshed.
        this.reconfigure(store, cm);

        // to add a record, just get a reference to the recordType:
        // this.store.recordType
        // and then use it to create a new record:
        // var r = new s.recordType({
        //     value:4,
        //     displayField:"Last Week",
        //     total: 23
        // });
        // and then insert it into the store (updates the grid visually also):
        // this.store.insert(0, r);

        //update the store for the pagingtoolbar also
        this.pagingToolbar.bind(store);

        if (this.stateful) {
            this.initState();
        }

        if (!this.view.hmenu.items.containsKey('reset')) {
            this.view.hmenu.add({
                id: "reset",
                text: "Reset Columns",
                cls: "xg-hmenu-reset-columns"
            });
        }

        /*var tabspanel = Ext.getCmp(this.dataform.id + '_relationsPanel');

        for(var i=0; i<tabspanel.items.length;i++){
           var lgrid = tabspanel.get(i);
           alert(lgrid.title);
           lgrid.loadData();
        }*/
        

    },
    
    onLoad: function() {
        if (this.maskEmpty) {
            var el = this.getGridEl();
            if (this.store.getTotalCount() == 0) {
                    el.mask('No Data', 'x-mask');
            }
            else {
                el.unmask(true);
            }
        }
        
    },
    _new_storeSort: function (fieldName, dir){
        if (this.lastOptions.params) this.lastOptions.params.action = "read";
        return true;
    },

    /**
     * Grid Actions
     *
     */
    addRecord:function() {
        if(!this.allowadd) {
            Ext.Msg.alert("Security Info", "Restricted Priority");
            return;
        }

        if(this.type !== "mtm") {
            var store = this.store;
            if(store.recordType) {
                this.rec = new store.recordType({newRecord:true});

                
                if(this.dataform !== undefined) {
                    this.dataform.doLayout();
                    //this.dataform.getForm().loadRecord(this.rec);

                    var tabspanel = Ext.getCmp(this.dataform.id + '_relationsPanel');

                    if(tabspanel !== undefined) {
                       for(var i=0; i<tabspanel.items.length;i++){
                           var lgrid = tabspanel.get(i);

                           if(this.rec.get(this.primaryKey) != undefined)
                               lgrid.store.baseParams.filter = lgrid.store.baseParams.table + '.' + this.primaryKey + '=' + this.rec.get(this.primaryKey);
                           else 
                               lgrid.store.baseParams.filter = lgrid.store.baseParams.table + '.' + this.primaryKey + '=0';

                           //alert(lgrid.store.baseParams.filter);
                           //lgrid.loadGrid();
                       }
                    }

                    this.recordWnd.show();

                    /*Ext.each(this.rec.fields.items, function(f) {
                        var field = this.dataform.getForm().findField(f.name);
                        if(field)
                            field.defaultValue = f.defaultValue || null;
                    }, this);

                    this.dataform.getForm().items.each(function(item) {
                        item.setValue(item.defaultValue);
                    });*/
                    Ext.each(this.rec.fields.items, function(f) {
                        this.rec.data[f.name] = f.defaultValue || null;
                    }, this);
                    this.rec.markDirty();
                    
                    this.dataform.getForm().loadRecord(this.rec);

                    this.dataform.doLayout();
                }
                
            }
        }
        else {
            this.lookupWnd.show();
        }
        return false;
    }, // eo function addRecord
    removeRecord: function() {

        if(!this.allowdelete) {
            Ext.Msg.alert("Security Info", "Restricted Priority");
            return;
        }
        
        var sel = this.getSelectionModel().getSelected();
        var store = this.store;

        if(this.type == "mtm") {
            if(sel !== undefined)
            {
                Ext.MessageBox.confirm('Message', 'Do you really want to delete record?', function(btn){
                    if (btn == 'yes'){
                        // process text value and close...
                        store.remove(sel);
                    }
                });
            }
            else
            {
                Ext.MessageBox.alert('Message', 'Please select at least one record to delete');
            }
        }
        else {
            var start = store.baseParams.start;
            var limit = store.baseParams.limit;
            var idname = store.reader.meta.id;
            var idval = sel.get(idname);

            if(sel !== undefined)
            {
                Ext.MessageBox.confirm('Message', 'Do you really want to delete record?', function(btn){
                    if (btn == 'yes'){
                        // process text value and close...
                        store.remove(sel);
                        store.load({params:{action:'delete', key: idname, id:idval, start:start, limit:limit }});
                    }
                });
            }
            else
            {
                Ext.MessageBox.alert('Message', 'Please select at least one record to delete');
            }
        }

    },
    copyRecord: function() {

        if(this.type !== "mtm") {
            var store = this.store;
            if(store.recordType) {
                this.rec = this.getSelectionModel().getSelected().copy(null);//new store.recordType({newRecord:true});


                if(this.dataform !== undefined) {
                    this.dataform.doLayout();
                    //this.dataform.getForm().loadRecord(this.getSelectionModel().getSelected());
                    //this.dataform.getForm().loadRecord(this.rec);

                    var tabspanel = Ext.getCmp(this.dataform.id + '_relationsPanel');

                    if(tabspanel !== undefined) {
                       for(var i=0; i<tabspanel.items.length;i++){
                           var lgrid = tabspanel.get(i);

                           if(this.rec.get(this.primaryKey) != undefined)
                               lgrid.store.baseParams.filter = lgrid.store.baseParams.table + '.' + this.primaryKey + '=' + this.rec.get(this.primaryKey);
                           else
                               lgrid.store.baseParams.filter = lgrid.store.baseParams.table + '.' + this.primaryKey + '=0';

                           //alert(lgrid.store.baseParams.filter);
                           //lgrid.loadGrid();
                       }
                    }

                    this.recordWnd.show();

                    /*Ext.each(this.rec.fields.items, function(f) {
                        var field = this.dataform.getForm().findField(f.name);
                        if(field)
                            field.defaultValue = f.defaultValue || null;
                    }, this);

                    this.dataform.getForm().items.each(function(item) {
                        item.setValue(item.defaultValue);
                    });*/

                    /*
                    Ext.each(this.rec.fields.items, function(f) {
                        this.rec.data[f.name] = f.defaultValue || null;
                    }, this);*/
                    this.rec.data[this.primaryKey] = null;

                    this.rec.markDirty();

                    this.dataform.getForm().loadRecord(this.rec);

                    this.dataform.doLayout();
                }

            }
        }
        else {
            //this.lookupWnd.show();
        }
    },

    /**
     * Load Grid with meta data so onMetaChange get called
     * and create the column model
     */
    loadGrid: function() {
        if(this.type == 'mtm' || this.type == 'lookup'){
            var params = { //this is only parameters for the FIRST page load,
                action: "init",
                filter: this.store.baseParams.filter
            };
        }
        else {
            var params = { //this is only parameters for the FIRST page load,
                action: "init",
                start: 0, //pass start/limit parameters for paging
                limit: this.perPage,
                pageid: this.id,
                filter: this.store.baseParams.filter
            };
        }
        this.store.load({params: params});
        
        //this.loadData();
    },
    
    /**
     *
     * Load onlu grid's data
     *
     */
    loadData: function() {
        if(this.type == 'mtm' || this.type == 'lookup'){
            var params = { //this is only parameters for the FIRST page load,
                action: "read",
                filter: this.store.baseParams.filter
            };
        }
        else {
            var params = { //this is only parameters for the FIRST page load,
                action: "read",
                start: 0, //pass start/limit parameters for paging
                limit: this.perPage,
                filter: this.store.baseParams.filter
            };
        }

        this.store.load({params: params});
    },

    loadLookup: function() {
        var params = { //this is only parameters for the FIRST page load,
                action: "init",
                filter: this.store.baseParams.filter
        };
        this.store.load({params: params});
    },

    /**
     * Form Actions
     *
     */
    onSaveForm: function() {
        if(this.dataform.getForm().isValid()) {

            // See if form record is new
            var id = this.dataform.getForm().findField(this.primaryKey).getValue();
            
            // If yes submit form first to get new id
            // If no submit related data

            this.dataform.getForm().submit({
                params: {
                    action: 'save'
                },
                method:'POST',
                waitTitle:'Please wait.......',
                waitMsg:'Saving data...',
                scope:this,
                success:function(form, action) {
                    obj = Ext.util.JSON.decode(action.response.responseText);

                    // If response has newid and dataform has relations
                    // Submit related data with newid
                    if(obj.newid !== undefined) {
                        //Ext.Msg.alert("Error", obj.newid);
                        id = obj.newid;
                    }

                    // Submit one by one relations
                    var tabspanel = Ext.getCmp(this.dataform.id + '_relationsPanel');

                    if( tabspanel !== undefined ) {
                        for(var i=0; i<tabspanel.items.length;i++){
                           var lgrid = tabspanel.get(i);

                           if(lgrid.displayOnly) continue;

                           var relids = '';
                           var postVars = {};
                           var fields = new Array();
                           var postFls = new Array();
                           var j = 0;

                           if(lgrid.postFields!==undefined) {
                               for(var pf=0; pf<lgrid.postFields.length; pf++) {
                                    fields[j++] = lgrid.postFields[pf].fieldName;
                               }
                           }

                           var row=0;

                           lgrid.store.each(function(rec) {
                               var js = {};
                               js['relid'] = rec.data[lgrid.related.primaryKey];
                               for(var k=0; k<fields.length; k++) {
                                    js[fields[k]] = rec.data[fields[k]];
                               }

                               postFls[row] = js;

                               row++;
                           }, this);

                           postVars['postVars'] = postFls;

                           var o = {
                                url: lgrid.url
                                ,method:'post'
                                //,callback:this.requestCallback
                                ,scope:this
                                ,params:{
                                        action:'save'
                                        ,parentid: id
                                        ,relids: relids
                                        ,postFields: Ext.util.JSON.encode(postVars)
                                }
                            };
                            Ext.Ajax.request(o);

                        }
                    }
                    // If everything went ok COMMIT
                    this.loadData();
                    this.recordWnd.hide();
                },
                failure:function(form, action){
                    // If start ntransaction
                    // ROLLBACK

                    //alert('Failed');
                    //if(action.failureType == 'server'){
                        obj = Ext.util.JSON.decode(action.response.responseText);
                        Ext.Msg.alert("Error", obj.error);
                    //}else{
                    //    Ext.Msg.alert('Warning!', 'Authentication server is unreachable : ' + action.response.responseText);
                    //}
                }
            });


        }
    },

    onCancelForm: function() {
        //if(this.store.getModifiedRecords().length > 0) alert("DSF");
        /*Ext.Msg.show({
           title:'Cancel?',
           msg: 'Are you sure you want to cancel changes?',
           buttons: Ext.Msg.YESNO,
           fn: function(buttonid) {
               if(buttonid == 'yes' ) {
                   this.store.rejectChanges();
                   //this.loadData();
                   this.recordWnd.hide();
               }
           },
           icon: Ext.MessageBox.QUESTION
        });*/
        
        this.store.rejectChanges();
        //this.loadData();
        this.recordWnd.hide();

        
    },

    /**
     * Lookup Function
     *
     */
    onSelectLookup: function() {
        //
        var lugrid = this.lookupWnd.items.get(0);
        var sel = lugrid.getSelectionModel().getSelected();

        if(sel == undefined) {
            Ext.Msg.alert("Error", "Select an entry first.");
            return;
        }
        
        if(this.store.findExact(lugrid.primaryKey, sel.data[lugrid.primaryKey]) == -1) {
            this.store.add(sel);
            this.lookupWnd.hide();
        }
        else {
            Ext.Msg.alert("Error", "Entry already added.");
        }

        
    },

    onCancelLookup: function() {
        this.lookupWnd.hide();
    },

    getExcelXml: function(includeHidden) {
        var worksheet = this.createWorksheet(includeHidden);
        var totalWidth = this.getColumnModel().getTotalWidth(includeHidden);
        return '<?xml version="1.0" encoding="utf-8"?>' +
            '<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:o="urn:schemas-microsoft-com:office:office">' +
            '<o:DocumentProperties><o:Title>' + this.title + '</o:Title></o:DocumentProperties>' +
            '<ss:ExcelWorkbook>' +
                '<ss:WindowHeight>' + worksheet.height + '</ss:WindowHeight>' +
                '<ss:WindowWidth>' + worksheet.width + '</ss:WindowWidth>' +
                '<ss:ProtectStructure>False</ss:ProtectStructure>' +
                '<ss:ProtectWindows>False</ss:ProtectWindows>' +
            '</ss:ExcelWorkbook>' +
            '<ss:Styles>' +
                '<ss:Style ss:ID="Default">' +
                    '<ss:Alignment ss:Vertical="Top" ss:WrapText="1" />' +
                    '<ss:Font ss:FontName="arial" ss:Size="10" />' +
                    '<ss:Borders>' +
                        '<ss:Border ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous" ss:Position="Top" />' +
                        '<ss:Border ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous" ss:Position="Bottom" />' +
                        '<ss:Border ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous" ss:Position="Left" />' +
                        '<ss:Border ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous" ss:Position="Right" />' +
                    '</ss:Borders>' +
                    '<ss:Interior />' +
                    '<ss:NumberFormat />' +
                    '<ss:Protection />' +
                '</ss:Style>' +
                '<ss:Style ss:ID="title">' +
                    '<ss:Borders />' +
                    '<ss:Font />' +
                    '<ss:Alignment ss:WrapText="1" ss:Vertical="Center" ss:Horizontal="Center" />' +
                    '<ss:NumberFormat ss:Format="@" />' +
                '</ss:Style>' +
                '<ss:Style ss:ID="headercell">' +
                    '<ss:Font ss:Bold="1" ss:Size="10" />' +
                    '<ss:Alignment ss:WrapText="1" ss:Horizontal="Center" />' +
                    '<ss:Interior ss:Pattern="Solid" ss:Color="#A3C9F1" />' +
                '</ss:Style>' +
                '<ss:Style ss:ID="even">' +
                    '<ss:Interior ss:Pattern="Solid" ss:Color="#CCFFFF" />' +
                '</ss:Style>' +
                '<ss:Style ss:Parent="even" ss:ID="evendate">' +
                    '<ss:NumberFormat ss:Format="[ENG][$-409]dd\-mmm\-yyyy;@" />' +
                '</ss:Style>' +
                '<ss:Style ss:Parent="even" ss:ID="evenint">' +
                    '<ss:NumberFormat ss:Format="0" />' +
                '</ss:Style>' +
                '<ss:Style ss:Parent="even" ss:ID="evenfloat">' +
                    '<ss:NumberFormat ss:Format="0.00" />' +
                '</ss:Style>' +
                '<ss:Style ss:ID="odd">' +
                    '<ss:Interior ss:Pattern="Solid" ss:Color="#CCCCFF" />' +
                '</ss:Style>' +
                '<ss:Style ss:Parent="odd" ss:ID="odddate">' +
                    '<ss:NumberFormat ss:Format="[ENG][$-409]dd\-mmm\-yyyy;@" />' +
                '</ss:Style>' +
                '<ss:Style ss:Parent="odd" ss:ID="oddint">' +
                    '<ss:NumberFormat ss:Format="0" />' +
                '</ss:Style>' +
                '<ss:Style ss:Parent="odd" ss:ID="oddfloat">' +
                    '<ss:NumberFormat ss:Format="0.00" />' +
                '</ss:Style>' +
            '</ss:Styles>' +
            worksheet.xml +
            '</ss:Workbook>';
    },

    createWorksheet: function(includeHidden) {

//      Calculate cell data types and extra class names which affect formatting
        var cellType = [];
        var cellTypeClass = [];
        var cm = this.getColumnModel();
        var totalWidthInPixels = 0;
        var colXml = '';
        var headerXml = '';
        for (var i = 1; i < cm.getColumnCount(); i++) {
            if (includeHidden || !cm.isHidden(i)) {
                var w = cm.getColumnWidth(i)
                totalWidthInPixels += w;
                colXml += '<ss:Column ss:AutoFitWidth="1" ss:Width="' + w + '" />';
                headerXml += '<ss:Cell ss:StyleID="headercell">' +
                    '<ss:Data ss:Type="String">' + cm.getColumnHeader(i) + '</ss:Data>' +
                    '<ss:NamedCell ss:Name="Print_Titles" /></ss:Cell>';
                var fld = this.store.recordType.prototype.fields.get(cm.getDataIndex(i));

                if(fld != undefined) {

                    switch(fld.type) {
                        case "int":
                            cellType.push("Number");
                            cellTypeClass.push("int");
                            break;
                        case "float":
                            cellType.push("Number");
                            cellTypeClass.push("float");
                            break;
                        case "bool":
                        case "boolean":
                            cellType.push("String");
                            cellTypeClass.push("");
                            break;
                        case "date":
                            cellType.push("DateTime");
                            cellTypeClass.push("date");
                            break;
                        default:
                            cellType.push("String");
                            cellTypeClass.push("");
                            break;
                    }
                }
                else {
                    cellType.push("String");
                    cellTypeClass.push("");
                }
            }
        }
        var visibleColumnCount = cellType.length;

        var result = {
            height: 9000,
            width: Math.floor(totalWidthInPixels * 30) + 50
        };

//      Generate worksheet header details.
        var t = '<ss:Worksheet ss:Name="' + this.title + '">' +
            '<ss:Names>' +
                '<ss:NamedRange ss:Name="Print_Titles" ss:RefersTo="=\'' + this.title + '\'!R1:R2" />' +
            '</ss:Names>' +
            '<ss:Table x:FullRows="1" x:FullColumns="1"' +
                ' ss:ExpandedColumnCount="' + visibleColumnCount +
                '" ss:ExpandedRowCount="' + (this.store.getCount() + 2) + '">' +
                colXml +
                '<ss:Row ss:Height="38">' +
                    '<ss:Cell ss:StyleID="title" ss:MergeAcross="' + (visibleColumnCount - 1) + '">' +
                      '<ss:Data xmlns:html="http://www.w3.org/TR/REC-html40" ss:Type="String">' +
                        '<html:B><html:U><html:Font html:Size="15">' + this.title +
                        '</html:Font></html:U></html:B>Generated by ExtJs</ss:Data><ss:NamedCell ss:Name="Print_Titles" />' +
                    '</ss:Cell>' +
                '</ss:Row>' +
                '<ss:Row ss:AutoFitHeight="1">' +
                headerXml +
                '</ss:Row>';

//      Generate the data rows from the data in the Store
        for (var i = 0, it = this.store.data.items, l = it.length; i < l; i++) {
            t += '<ss:Row>';
            var cellClass = (i & 1) ? 'odd' : 'even';
            r = it[i].data;
            var k = 0;
            for (var j = 1; j < cm.getColumnCount(); j++) {
                if (includeHidden || !cm.isHidden(j)) {
                    var v = r[cm.getDataIndex(j)];
                    t += '<ss:Cell ss:StyleID="' + cellClass + cellTypeClass[k] + '"><ss:Data ss:Type="' + cellType[k] + '">';
                        if (cellType[k] == 'DateTime') {
                            t += v.format('Y-m-d');
                        } else {
                            t += v;
                        }
                    t +='</ss:Data></ss:Cell>';
                    k++;
                }
            }
            t += '</ss:Row>';
        }

        result.xml = t + '</ss:Table>' +
            '<x:WorksheetOptions>' +
                '<x:PageSetup>' +
                    '<x:Layout x:CenterHorizontal="1" x:Orientation="Landscape" />' +
                    '<x:Footer x:Data="Page &amp;P of &amp;N" x:Margin="0.5" />' +
                    '<x:PageMargins x:Top="0.5" x:Right="0.5" x:Left="0.5" x:Bottom="0.8" />' +
                '</x:PageSetup>' +
                '<x:FitToPage />' +
                '<x:Print>' +
                    '<x:PrintErrors>Blank</x:PrintErrors>' +
                    '<x:FitWidth>1</x:FitWidth>' +
                    '<x:FitHeight>32767</x:FitHeight>' +
                    '<x:ValidPrinterInfo />' +
                    '<x:VerticalResolution>600</x:VerticalResolution>' +
                '</x:Print>' +
                '<x:Selected />' +
                '<x:DoNotDisplayGridlines />' +
                '<x:ProtectObjects>False</x:ProtectObjects>' +
                '<x:ProtectScenarios>False</x:ProtectScenarios>' +
            '</x:WorksheetOptions>' +
        '</ss:Worksheet>';
        return result;
    },

    /**
     * Render Functions
     */
    renderDateTime: function(date){
        if (!date) {
            return '';
        }

        return date.dateFormat('d/m/Y h:m a');
    },
    renderDate: function(date){
        return date ? date.dateFormat('M d, Y') : '';
    },
    renderIcon: function(val) {
        return val ? '<img src="' + val + '" style="max-width: 100px; max-height: 100px;" />' : '';
    }
});

Ext.reg('dataGrid', Ext.ux.grid.DataGrid);

