/**
 * @class Ext.ux.grid.Printer
 * @author Ed Spencer (edward@domine.co.uk)
 * Helper class to easily print the contents of a grid. Will open a new window with a table where the first row
 * contains the headings from your column model, and with a row for each item in your grid's store. When formatted
 * with appropriate CSS it should look very similar to a default grid. If renderers are specified in your column
 * model, they will be used in creating the table. Override headerTpl and bodyTpl to change how the markup is generated
 * 
 * Usage:
 * 
 * 1 - Add Ext.Require Before the Grid code
 * Ext.require([
 *   'Ext.ux.grid.GridPrinter',
 * ]);
 * 
 * 2 - Declare the Grid 
 * var grid = Ext.create('Ext.grid.Panel', {
 *   columns: //some column model,
 *   store   : //some store
 * });
 * 
 * 3 - Print!
 * Ext.ux.grid.Printer.mainTitle = 'Your Title here'; //optional
 * Ext.ux.grid.Printer.print(grid);
 * 
 * Original url: http://edspencer.net/2009/07/printing-grids-with-ext-js.html
 * 
 * Modified by Loiane Groner (me@loiane.com) - September 2011 - Ported to Ext JS 4
 * http://loianegroner.com (English)
 * http://loiane.com (Portuguese)
 * 
 * Modified by Bruno Sales - August 2012
 * 
 * Modified by Paulo Goncalves - March 2012
 * 
 * Modified by Beto Lima - March 2012
 * 
 * Modified by Beto Lima - April 2012
 *
 * Modified by Paulo Goncalves - May 2012
 * 
 * Modified by Nielsen Teixeira - 2012-05-02
 *
 * Modified by Joshua Bradley - 2012-06-01
 * 
 * Modified by Loiane Groner - 2012-09-08
 * 
 * Modified by Loiane Groner - 2012-09-24
 *
 * Modified by Loiane Groner - 2012-10-17
 * FelipeBR contribution: Fixed: support for column name that cotains numbers
 * Fixed: added support for template columns
 *
 * Modified by Loiane Groner - 2013-Feb-26
 * Fixed: added support for row expander plugin
 * Tested using Ext JS 4.1.2
 *
 */
Ext.define("Ext.ux.grid.Printer", {
    
    requires: 'Ext.XTemplate',

    statics: {
        /**
         * Prints the passed grid. Reflects on the grid's column model to build a table, and fills it using the store
         * @param {Ext.grid.Panel} grid The grid to print
         */
        printInvoice: function(grid, featureId, CompanyName, CompanyAddress, CompanyPhone, CompanyFax, CompanyEmail, ABN) {
            // We generate an XTemplate here by using 2 intermediary
            // XTemplates - one to create the header, the other
            // to create the body (see the escaped {} below)
            var columns = [];
            var isGrouped = grid.store.isGrouped();
            if ( isGrouped ) {
                var feature = this.getFeature( grid, featureId );
                var groupField = feature.getGroupField();
            }
            //account for grouped columns
            Ext.each(grid.columns, function(c) {
                if(c.items.length > 0) {
                    columns = columns.concat(c.items.items);
                } else {
                    columns.push(c);
                }
            });

            //build a usable array of store data for the XTemplate
            var data = [];
            grid.store.data.each(function(item, row) {
                var convertedData = {};

                //apply renderers from column model
                for (var key in item.data) {
                    var value = item.data[key];
                    var found = false;

                    Ext.each(columns, function(column, col) {
                        
                        if (column && column.dataIndex == key) {

                            /*
                             * TODO: add the meta to template
                             */
                            var meta = {item: '', tdAttr: '', style: ''};
                            value = column.renderer ? column.renderer.call(grid, value, meta, item, row, col, grid.store, grid.view) : value;
                            var varName = column.dataIndex.replace(/(^[^a-z]*|[^\w])/gi, '');
                            convertedData[varName] = value;
                            found = true;
                            
                        } else if (column && column.xtype === 'rownumberer'){
                        	var varName = column.id.replace(/(^[^a-z]*|[^\w])/gi, '');
                            convertedData[varName] = (row + 1);
                            found = true;
                            
                        } else if (column && column.xtype === 'templatecolumn'){
                            
                            value = column.tpl ? column.tpl.apply(item.data) : value;
                            
                            var varName = column.id.replace(/(^[^a-z]*|[^\w])/gi, '');
                            convertedData[varName] = value;
                            found = true;
                            
                        } 
                    }, this);

                    if (!found) { // model field not used on Grid Column, can be used on RowExpander
                        var varName = key.replace(/(^[^a-z]*|[^\w])/gi, '');
                        convertedData[varName] = value;
                    }
                }

                data.push(convertedData);
            });
            
            // remove columns that do not contain dataIndex
            // or dataIndex is empty.
            // for example: columns filter or columns button
            var clearColumns = [];
            Ext.each(
                columns,
                function (column) {
                    if ( column ) {
                        if ( !Ext.isEmpty(column.dataIndex) &&
                             !column.hidden                 &&
                             !isGrouped )
                        {
                            clearColumns.push(column);
                        } else if ( column.xtype === 'rownumberer'){
                            column.text = 'Row';
                            clearColumns.push(column);
                        } else if ( column.xtype === 'templatecolumn'){
                            clearColumns.push(column);
                        } else if ( isGrouped && column.dataIndex !== groupField ){
                            clearColumns.push(column);
                        }
                    }
                }
            );
            columns = clearColumns;
            
            //get Styles file relative location, if not supplied
            if (this.stylesheetPath === null) {
                var scriptPath = Ext.Loader.getPath('Ext.ux.grid.Printer');
                this.stylesheetPath = scriptPath.substring(0, scriptPath.indexOf('Printer.js')) + 'gridPrinterCss/print.css';
            }

            //use the headerTpl and bodyTpl markups to create the main XTemplate below
            var headings = Ext.create('Ext.XTemplate', this.headerTpl).apply(columns);
            var body     = this.generateBody( grid, columns, feature );
            var pluginsBody = '',
                pluginsBodyMarkup = [];
            
            //add relevant plugins
            Ext.each(grid.plugins, function(p) {
                if (p.ptype == 'rowexpander') {
                    pluginsBody += p.rowBodyTpl.html;
                }
            });
            
            if (pluginsBody != '') {
                pluginsBodyMarkup = [
                    '<tr class="{[xindex % 2 === 0 ? "even" : "odd"]}"><td colspan="' + columns.length + '">',
                      pluginsBody,
                    '</td></tr>'
                ];
            }
            
            var title = grid.title || this.defaultGridTitle;
            
            var date = Ext.util.Format.date(Ext.getStore('DrillDownInfo').data.items[0].data.deliveryDate, 'd-m-Y');
	        var invoiceDate = Ext.util.Format.date(Ext.getStore('DrillDownInfo').data.items[0].data.invoiceDate, 'd-m-Y');
            var transactionType = Ext.getStore('DrillDownInfo').data.items[0].data.transactionType;

            	if (transactionType == "Invoice") {
                  transactionType = "Copy of Tax Invoice";
              }

            //Here because inline styles using CSS, the browser did not show the correct formatting of the data the first time that loaded
            var htmlMarkup = [
                '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
                '<html class="' + Ext.baseCSSPrefix + 'ux-grid-printer">',
                  '<head>',
                    '<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />',
                    '<link href="' + this.stylesheetPath + '" rel="stylesheet" type="text/css" />',
                    '<link href="config/css.css" rel="stylesheet" type="text/css" />',
                    '<title>' + title + '</title>',
                  '</head>',
                  '<body class="' + Ext.baseCSSPrefix + 'ux-grid-printer-body">',
                  '<div class="' + Ext.baseCSSPrefix + 'ux-grid-printer-noprint ' + Ext.baseCSSPrefix + 'ux-grid-printer-links">',
                      '<a class="' + Ext.baseCSSPrefix + 'ux-grid-printer-linkprint" href="javascript:void(0);" onclick="window.print();">' + this.printLinkText + '</a>',
                      '<a class="' + Ext.baseCSSPrefix + 'ux-grid-printer-linkclose" href="javascript:void(0);" onclick="window.close();">' + this.closeLinkText + '</a>',
                  '</div>',
                  '<div class="printcustomer"><img src="resources/themes/images/custom/logo_small_new.png" width="233px" height="67px"><br /><br /><br /><br />',
				 '<b>Customer</b><br />',
				  Ext.getStore('DrillDownInfo').data.items[0].data.nameCharge + '<br />',
  				Ext.getStore('DrillDownInfo').data.items[0].data.chargeAddress1 + '<br />',
  				Ext.getStore('DrillDownInfo').data.items[0].data.chargeAddress2 + '<br />',
  				Ext.getStore('DrillDownInfo').data.items[0].data.chargeAddress3,
				'</div><span class="printbalance">',
				'<h1 class="bigtext">' + transactionType + '</h1>',
              'Transaction #: '+Ext.getStore('DrillDownInfo').data.items[0].data.transactionNumber+'/'+Ext.getStore('DrillDownInfo').data.items[0].data.transactionSuffix+'<br />',
	            'Invoice Date: '+ invoiceDate + '<br />',
              'Delivery Date: '+ date + '<br />',
              'Order #: '+Ext.getStore('DrillDownInfo').data.items[0].data.customerOrderNumber + '<br />',
              'Customer #: '+Ext.getStore('DrillDownInfo').data.items[0].data.customerID + '<br /><br /></span>',
				'<span class="printdeliver">',
				'<b>Deliver To</b><br />',
				Ext.getStore('DrillDownInfo').data.items[0].data.nameShip + '<br />',
				Ext.getStore('DrillDownInfo').data.items[0].data.shipAddress1 + '<br />',
				Ext.getStore('DrillDownInfo').data.items[0].data.shipAddress2 + '<br />',
				Ext.getStore('DrillDownInfo').data.items[0].data.shipAddress3,
				'</span>',
                  '<span class="printdiv">',
				CompanyName + '<br />',
                CompanyAddress + '<br />',
                CompanyPhone + '<br />',
                CompanyFax + '<br />',
                CompanyEmail+ '<br />',
                ABN,	
                  '</span></div>',
                  '<br />',
                    '<table>',
                      '<tr>',
                        headings,
                      '</tr>',
                        '<tpl for=".">',
                           '<tr class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
                              body,
                           '</tr>',
                        '</tpl>',
                    '</table>',
                    '<span class="printtotals">',
                'Total (GST Ex): ' + Ext.util.Format.currency(Ext.getStore('DrillDownInfo').data.items[0].data.transactionTotalAmountExcGST) + '<br />',
  				'Total GST: ' + Ext.util.Format.currency(Ext.getStore('DrillDownInfo').data.items[0].data.transactionTotalGST) + '<br />',
  				'Total (GST Inc): ' + Ext.util.Format.currency(Ext.getStore('DrillDownInfo').data.items[0].data.transactionTotalAmountIncGST),
                  '</span>',
                  '</body>',
                '</html>'
            ];

            var html = Ext.create('Ext.XTemplate', htmlMarkup).apply(data); 

            //open up a new printing window, write to it, print it and close
            var win = window.open('', 'printgrid');
            
            //document must be open and closed
            win.document.open();
            win.document.write(html);
            win.document.close();
            
            if (this.printAutomatically){
                win.print();
            }
            
            //Another way to set the closing of the main
            if (this.closeAutomaticallyAfterPrint){
                if(Ext.isIE){
                    window.close();
                } else {
                    win.close();
                }                
            }
        },
        
        printStatement: function(grid, featureId, CompanyName, CompanyAddress, CompanyPhone, CompanyFax, CompanyEmail, ABN, TradingTerms) {
            // We generate an XTemplate here by using 2 intermediary
            // XTemplates - one to create the header, the other
            // to create the body (see the escaped {} below)
            var columns = [];
            var isGrouped = grid.store.isGrouped();
            if ( isGrouped ) {
                var feature = this.getFeature( grid, featureId );
                var groupField = feature.getGroupField();
            }
            //account for grouped columns
            Ext.each(grid.columns, function(c) {
                if(c.items.length > 0) {
                    columns = columns.concat(c.items.items);
                } else {
                    columns.push(c);
                }
            });

            //build a usable array of store data for the XTemplate
            var data = [];
            grid.store.data.each(function(item, row) {
                var convertedData = {};

                //apply renderers from column model
                for (var key in item.data) {
                    var value = item.data[key];
                    var found = false;

                    Ext.each(columns, function(column, col) {
                        
                        if (column && column.dataIndex == key) {

                            /*
                             * TODO: add the meta to template
                             */
                            var meta = {item: '', tdAttr: '', style: ''};
                            value = column.renderer ? column.renderer.call(grid, value, meta, item, row, col, grid.store, grid.view) : value;
                            var varName = column.dataIndex.replace(/(^[^a-z]*|[^\w])/gi, '');
                            convertedData[varName] = value;
                            found = true;
                            
                        } else if (column && column.xtype === 'rownumberer'){
                        	var varName = column.id.replace(/(^[^a-z]*|[^\w])/gi, '');
                            convertedData[varName] = (row + 1);
                            found = true;
                            
                        } else if (column && column.xtype === 'templatecolumn'){
                            
                            value = column.tpl ? column.tpl.apply(item.data) : value;
                            
                            var varName = column.id.replace(/(^[^a-z]*|[^\w])/gi, '');
                            convertedData[varName] = value;
                            found = true;
                            
                        } 
                    }, this);

                    if (!found) { // model field not used on Grid Column, can be used on RowExpander
                        var varName = key.replace(/(^[^a-z]*|[^\w])/gi, '');
                        convertedData[varName] = value;
                    }
                }

                data.push(convertedData);
            });
            
            // remove columns that do not contain dataIndex
            // or dataIndex is empty.
            // for example: columns filter or columns button
            var clearColumns = [];
            Ext.each(
                columns,
                function (column) {
                    if ( column ) {
                        if ( !Ext.isEmpty(column.dataIndex) &&
                             !column.hidden                 &&
                             !isGrouped )
                        {
                            clearColumns.push(column);
                        } else if ( column.xtype === 'rownumberer'){
                            column.text = 'Row';
                            clearColumns.push(column);
                        } else if ( column.xtype === 'templatecolumn'){
                            clearColumns.push(column);
                        } else if ( isGrouped && column.dataIndex !== groupField ){
                            clearColumns.push(column);
                        }
                    }
                }
            );
            columns = clearColumns;
            
            //get Styles file relative location, if not supplied
            if (this.stylesheetPath === null) {
                var scriptPath = Ext.Loader.getPath('Ext.ux.grid.Printer');
                this.stylesheetPath = scriptPath.substring(0, scriptPath.indexOf('Printer.js')) + 'gridPrinterCss/print.css';
            }

            //use the headerTpl and bodyTpl markups to create the main XTemplate below
            var headings = Ext.create('Ext.XTemplate', this.headerTpl).apply(columns);
            var body     = this.generateBody( grid, columns, feature );
            var pluginsBody = '',
                pluginsBodyMarkup = [];
            
            //add relevant plugins
            Ext.each(grid.plugins, function(p) {
                if (p.ptype == 'rowexpander') {
                    pluginsBody += p.rowBodyTpl.html;
                }
            });
            
            if (pluginsBody != '') {
                pluginsBodyMarkup = [
                    '<tr class="{[xindex % 2 === 0 ? "even" : "odd"]}"><td colspan="' + columns.length + '">',
                      pluginsBody,
                    '</td></tr>'
                ];
            }
            
            var title = grid.title || this.defaultGridTitle;

            //Here because inline styles using CSS, the browser did not show the correct formatting of the data the first time that loaded
            var htmlMarkup = [
                '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
                '<html class="' + Ext.baseCSSPrefix + 'ux-grid-printer">',
                  '<head>',
                    '<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />',
                    '<link href="' + this.stylesheetPath + '" rel="stylesheet" type="text/css" />',
                    '<link href="config/css.css" rel="stylesheet" type="text/css" />',
                    '<title>' + title + '</title>',
                  '</head>',
                  '<body class="' + Ext.baseCSSPrefix + 'ux-grid-printer-body">',
                  '<div class="' + Ext.baseCSSPrefix + 'ux-grid-printer-noprint ' + Ext.baseCSSPrefix + 'ux-grid-printer-links">',
                      '<a class="' + Ext.baseCSSPrefix + 'ux-grid-printer-linkprint" href="javascript:void(0);" onclick="window.print();">' + this.printLinkText + '</a>',
                      '<a class="' + Ext.baseCSSPrefix + 'ux-grid-printer-linkclose" href="javascript:void(0);" onclick="window.close();">' + this.closeLinkText + '</a>',
                  '</div>',
                  '<h1>' + this.mainTitle + '</h1>',
                  '<div style="height: 170px;"><img src="resources/themes/images/custom/logo_small_new.png" width="233px" height="67px"><br />',
				Ext.getStore('CustomerDetails').data.items[0].data.customerName + '<br />',
                Ext.getStore('CustomerDetails').data.items[0].data.streetAddress + '<br />',
                Ext.getStore('CustomerDetails').data.items[0].data.streetSuburb + '<br />',
                Ext.getStore('CustomerDetails').data.items[0].data.streetState + '<br />',
                Ext.getStore('CustomerDetails').data.items[0].data.streetPostCode,
				'<span class="printbalance">',
				Ext.get('statements_drilldownbalances').dom.innerHTML,
				'</span>',
                  '<span class="printdiv">',
                CompanyName + '<br />',
                CompanyAddress + '<br />',
                CompanyPhone + '<br />',
                CompanyFax + '<br />',
                CompanyEmail+ '<br />',
                ABN,
                  '</span></div>',
                  '<br />',
                    '<table>',
                      '<tr>',
                        headings,
                      '</tr>',
                        '<tpl for=".">',
                           '<tr class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
                              body,
                           '</tr>',
                        '</tpl>',
                    '</table>',
                    TradingTerms,
                  '</body>',
                '</html>'
            ];

            var html = Ext.create('Ext.XTemplate', htmlMarkup).apply(data); 

            //open up a new printing window, write to it, print it and close
            var win = window.open('', 'printgrid');
            
            //document must be open and closed
            win.document.open();
            win.document.write(html);
            win.document.close();
            
            if (this.printAutomatically){
                win.print();
            }
            
            //Another way to set the closing of the main
            if (this.closeAutomaticallyAfterPrint){
                if(Ext.isIE){
                    window.close();
                } else {
                    win.close();
                }                
            }
        },

        getFeature : function( grid, featureId ) {
            var feature;
            var view     = grid.getView();
            if ( featureId ) {
                feature = view.getFeature( featureId );
            }
            else {
                var features = view.features;
                if ( features.length > 1 ) {
                    alert( "More than one feature requires to pass " +
                           "featureId as parameter to 'print'." );
                    return;
                }
                else {
                    feature = features[0];
                }
            }
            return feature;
        },

        generateBody : function( grid, columns, feature ) {

            var groups   = grid.store.getGroups();
            var groupers = grid.store.groupers;
            var fields   = grid.store.getProxy().getModel().prototype.fields.items;
            var hideGroupField = true;
            var groupField;
            var body;

            if ( grid.store.isGrouped() ) {
            	console.log("test");
                hideGroupField = feature.hideGroupedHeader;  // bool
                groupField = feature.getGroupField();

                if ( !feature || !fields || !groupField ) {
                    return;
                }
                
                if ( hideGroupField ) {
                    var removeGroupField = function( item ) {
                        return ( item.name != groupField );
                    };
                    // Remove group field from fields array.
                    // This could be done later in the template,
                    // but it is easier to do it here.
                    fields = fields.filter( removeGroupField );
                }

                var bodyTpl = [
                    '<tpl for=".">',
                        '<tr class="group-header">',
                            '<td colspan="{[this.colSpan]}"> {[this.headerPrefix]}{name} &nbsp; {[this.postfixWithParens ? "(" : ""]} {[this.childCount(values.children)]}  {[this.childCount(values.children) > 1 ? this.headerPostfixPlural : this.headerPostfixSingular ]}  {[this.postfixWithParens ? ")" : ""]} </td>',
                        ' </tr>', 
                        '<tpl for="children">',
                            '<tr>',
                                '<tpl for="this.fields">',
                                    '{% if (values.name==="id") continue; %}',
                                    '<td>',
                                      '{[ parent.get(values.name) ]}',
                                    '</td>',
                                '</tpl>',
                            '</tr>',
                        '</tpl>',
                    '</tpl>',
                    {
                        // XTemplate configuration:
                        hideGroupField        : hideGroupField,
                        headerPrefix          : this.groupHeaderPrefix,
                        headerPostfixSingular : this.groupHeaderPostfixSingular,
                        headerPostfixPlural   : this.groupHeaderPostfixPlural,
                        postfixWithParens     : false,
                        fields                : fields,
                        colSpan               : fields.length - 1,
                        // XTemplate member functions:
                        childCount : function(c) {
                            return c.length;
                        }
                    }
                ];
                body = Ext.create('Ext.XTemplate', bodyTpl).apply(groups);
            }
            else {          	
                body = Ext.create('Ext.XTemplate', this.bodyTpl).apply(columns);
            }
            return body;
        },

        /**
         * @property stylesheetPath
         * @type String
         * The path at which the print stylesheet can be found (defaults to 'ux/grid/gridPrinterCss/print.css')
         */
        stylesheetPath: 'resources/css/print.css',
        
        /**
         * @property printAutomatically
         * @type Boolean
         * True to open the print dialog automatically and close the window after printing. False to simply open the print version
         * of the grid (defaults to false)
         */
        printAutomatically: false,
        
        /**
         * @property closeAutomaticallyAfterPrint
         * @type Boolean
         * True to close the window automatically after printing.
         * (defaults to false)
         */
        closeAutomaticallyAfterPrint: false,        
        
        /**
         * @property mainTitle
         * @type String
         * Title to be used on top of the table
         * (defaults to empty)
         */
        mainTitle: '',
        
        /**
         * @property defaultGridTitle
         * @type String
         * Title to be used if grid to be printed
         * has no title attribute set.
         */
        defaultGridTitle: '',
        
        /**
         * Text show on print link
         * @type String
         */
        printLinkText: 'Print',
        
        /**
         * Text show on close link
         * @type String
         */
        closeLinkText: 'Close',
        
        /**
         * Text shown as prefix to group header text.
         * @type String
         */
        groupHeaderPrefix : '',

        /**
         * Text shown as postfix to group header text,
         * if there is only one child element for this group.
         * @type String
         */
        groupHeaderPostfixSingular : '',

        /**
         * Text shown as postfix to group header text,
         * if there are multiple child elements for this group.
         * @type String
         */
        groupHeaderPostfixPlural : '',

        /**
         * @property headerTpl
         * @type {Object/Array} values
         * The markup used to create the headings row. By default this just uses <th> elements, override to provide your own
         */
        headerTpl: [ 
            '<tpl for=".">',
                '<th>{text}</th>',
            '</tpl>'
        ],

        /**
         * @property bodyTpl
         * @type {Object/Array} values
         * The XTemplate used to create each row. This is used inside the 'print' function to build another XTemplate, to which the data
         * are then applied (see the escaped dataIndex attribute here - this ends up as "{dataIndex}")
         */
        bodyTpl: [
            '<tpl for=".">',
                '<tpl>',
                    '<td>\{{[values.dataIndex]}\}</td>',
                '</tpl>',   
            '</tpl>'
        ]
    }
});