
var DownloadEvt = null;

var defaults = {
    csvEnclosure:        '"',
    csvSeparator:        ',',
    csvUseBOM:           true,
    displayTableName:    false,
    escape:              false,
    exportHiddenCells:   false,       // true = speed up export of large tables with hidden cells (hidden cells will be exported !)
    fileName:            'tableExport',
    htmlContent:         false,
    ignoreColumn:        [],
    ignoreRow:           [],
    jsonScope:           'all',       // head, data, all
    jspdf: {                          // jsPDF / jsPDF-AutoTable related options
        orientation:       'p',
        unit:              'pt',
        format:            'a4',        // One of jsPDF page formats or 'bestfit' for autmatic paper format selection
        margins:           {left: 20, right: 10, top: 10, bottom: 10},
        onDocCreated:      null,
        autotable: {
            styles: {
                cellPadding:   2,
                rowHeight:     12,
                fontSize:      8,
                fillColor:     255,         // Color value or 'inherit' to use css background-color from html table
                textColor:     50,          // Color value or 'inherit' to use css color from html table
                fontStyle:     'normal',    // normal, bold, italic, bolditalic or 'inherit' to use css font-weight and fonst-style from html table
                overflow:      'ellipsize', // visible, hidden, ellipsize or linebreak
                halign:        'inherit',   // left, center, right or 'inherit' to use css horizontal cell alignment from html table
                valign:        'middle'     // top, middle, bottom
            },
            headerStyles: {
                fillColor:     [52, 73, 94],
                textColor:     255,
                fontStyle:     'bold',
                halign:        'inherit',   // left, center, right or 'inherit' to use css horizontal header cell alignment from html table
                valign:        'middle'     // top, middle, bottom
            },
            alternateRowStyles: {
                fillColor:     245
            },
            tableExport: {
                doc:               null,    // jsPDF doc object. If set, an already created doc will be used to export to
                onAfterAutotable:  null,
                onBeforeAutotable: null,
                onAutotableText:   null,
                onTable:           null,
                outputImages:      true
            }
        }
    },
    mso: {                            // MS Excel and MS Word related options
        fileFormat:        'xlshtml',   // xlshtml = Excel 2000 html format
                                        // xmlss = XML Spreadsheet 2003 file format (XMLSS)
                                        // xlsx = Excel 2007 Office Open XML format
        onMsoNumberFormat: null,        // Excel 2000 html format only. See readme.md for more information about msonumberformat
        pageFormat:        'a4',        // Page format used for page orientation
        pageOrientation:   'portrait',  // portrait, landscape (xlshtml format only)
        rtl:               false,       // true = Set worksheet option 'DisplayRightToLeft'
        styles:            [],          // E.g. ['border-bottom', 'border-top', 'border-left', 'border-right']
        worksheetName:     ''
    },
    numbers: {
        html: {
            decimalMark:        '.',
            thousandsSeparator: ','
        },
        output: {                       // Use 'output: false' to keep number format in exported output
            decimalMark:        '.',
            thousandsSeparator: ','
        }
    },
    onCellData:          null,
    onCellHtmlData:      null,
    onIgnoreRow:         null,        // onIgnoreRow($tr, rowIndex): function should return true to not export a row
    outputMode:          'file',      // 'file', 'string', 'base64' or 'window' (experimental)
    pdfmake: {
        enabled:           false,       // true: use pdfmake instead of jspdf and jspdf-autotable (experimental)
        docDefinition: {
            pageOrientation: 'portrait',  // 'portrait' or 'landscape'
            defaultStyle: {
                font:          'Roboto'     // Default is 'Roboto', for arabic font set this option to 'Mirza' and include mirza_fonts.js
            }
        },
        fonts: {}
    },
    preserve: {
        leadingWS:         false,       // preserve leading white spaces
        trailingWS:        false        // preserve trailing white spaces
    },
    preventInjection:    true,
    tbodySelector:       'tr',
    tfootSelector:       'tr',        // Set empty ('') to prevent export of tfoot rows
    theadSelector:       'tr',
    tableName:           'Table',
    type:                'csv'        // 'csv', 'tsv', 'txt', 'sql', 'json', 'xml', 'excel', 'doc', 'png' or 'pdf'
};

var pageFormats = { // Size in pt of various paper formats. Adopted from jsPDF.
    'a0': [2383.94, 3370.39], 'a1': [1683.78, 2383.94], 'a2': [1190.55, 1683.78],
    'a3': [841.89, 1190.55],  'a4': [595.28, 841.89],   'a5': [419.53, 595.28],
    'a6': [297.64, 419.53],   'a7': [209.76, 297.64],   'a8': [147.40, 209.76],
    'a9': [104.88, 147.40],   'a10': [73.70, 104.88],
    'b0': [2834.65, 4008.19], 'b1': [2004.09, 2834.65], 'b2': [1417.32, 2004.09],
    'b3': [1000.63, 1417.32], 'b4': [708.66, 1000.63],  'b5': [498.90, 708.66],
    'b6': [354.33, 498.90],   'b7': [249.45, 354.33],   'b8': [175.75, 249.45],
    'b9': [124.72, 175.75],   'b10': [87.87, 124.72],
    'c0': [2599.37, 3676.54],
    'c1': [1836.85, 2599.37], 'c2': [1298.27, 1836.85], 'c3': [918.43, 1298.27],
    'c4': [649.13, 918.43],   'c5': [459.21, 649.13],   'c6': [323.15, 459.21],
    'c7': [229.61, 323.15],   'c8': [161.57, 229.61],   'c9': [113.39, 161.57],
    'c10': [79.37, 113.39],
    'dl': [311.81, 623.62],
    'letter': [612, 792], 'government-letter': [576, 756], 'legal': [612, 1008],
    'junior-legal': [576, 360], 'ledger': [1224, 792], 'tabloid': [792, 1224],
    'credit-card': [153, 243]
};
var FONT_ROW_RATIO = 1.15;
var el             = this;
var DownloadEvt    = null;
var $hrows         = [];
var $rows          = [];
var rowIndex       = 0;
var trData         = '';
var colNames       = [];
var ranges         = [];
var blob;
var $hiddenTableElements = [];
var checkCellVisibilty = false;


function GetColumnNames (tableColumns) {
    var result = [];
    $.each(tableColumns,function (i,o) {
        if(i>0){
            result[i-1] = o.field;
        }
    });
    return result;
}

function exportExcel(){
    var trData = '';
    var queryResult = $("#queryResult").val();

    var result = new JSONFormat(queryResult, 4);

    var MSDocType   =  'excel';
    var MSDocExt    =  'xls';
    var MSDocSchema = 'xmlns:x="urn:schemas-microsoft-com:office:' + MSDocType + '"';
    var docData     = '';
    var docName     = 'dataTable';
        var $table = $("table");
        var rowIndex = 0;
        var ranges   = [];
        var colNames = GetColumnNames(result.data.data.tableColumns);
        // Header
        docData += '<table><thead>';
        $.each(colNames,function (i,o) {
            trData += '<th>'+o+'</th>';
        });

        if ( trData.length > 0 ){
            docData += '<tr>' + trData + '</tr>';
        }
        docData += '</thead><tbody>';

        var dataRows = result.data.data.tableData;
        trData = '';
        $.each(dataRows,function (i,dataRow) {
            $.each(colNames,function (i,o) {
                trData += '<td>'+dataRow[o]+'</td>';
            });
            docData += '<tr>' + trData + '</tr>';
        });
        docData += '</tbody></table>';

    //noinspection XmlUnusedNamespaceDeclaration
    var docFile = '<html xmlns:o="urn:schemas-microsoft-com:office:office" ' + MSDocSchema + ' xmlns="http://www.w3.org/TR/REC-html40">';
    docFile += '<meta http-equiv="content-type" content="application/vnd.ms-' + MSDocType + '; charset=UTF-8">';
    docFile += "<head>";
    if (MSDocType === 'excel') {
        docFile += "<!--[if gte mso 9]>";
        docFile += "<xml>";
        docFile += "<x:ExcelWorkbook>";
        docFile += "<x:ExcelWorksheets>";
        docFile += "<x:ExcelWorksheet>";
        docFile += "<x:Name>";
        docFile += docName;
        docFile += "</x:Name>";
        docFile += "<x:WorksheetOptions>";
        docFile += "<x:DisplayGridlines/>";
        docFile += "</x:WorksheetOptions>";
        docFile += "</x:ExcelWorksheet>";
        docFile += "</x:ExcelWorksheets>";
        docFile += "</x:ExcelWorkbook>";
        docFile += "</xml>";
        docFile += "<![endif]-->";
    }
    docFile += "<style>";

    docFile += "@page { size:" + defaults.mso.pageOrientation + "; mso-page-orientation:" + defaults.mso.pageOrientation + "; }";
    docFile += "@page Section1 {size:" + pageFormats[defaults.mso.pageFormat][0] + "pt " + pageFormats[defaults.mso.pageFormat][1] + "pt";
    docFile += "; margin:1.0in 1.25in 1.0in 1.25in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";
    docFile += "div.Section1 {page:Section1;}";
    docFile += "@page Section2 {size:" + pageFormats[defaults.mso.pageFormat][1] + "pt " + pageFormats[defaults.mso.pageFormat][0] + "pt";
    docFile += ";mso-page-orientation:" + defaults.mso.pageOrientation + ";margin:1.25in 1.0in 1.25in 1.0in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";
    docFile += "div.Section2 {page:Section2;}";

    docFile += "br {mso-data-placement:same-cell;}";
    docFile += "</style>";
    docFile += "</head>";
    docFile += "<body>";
    docFile += "<div class=\"Section" + ((defaults.mso.pageOrientation === 'landscape') ? "2" : "1") + "\">";
    docFile += docData;
    docFile += "</div>";
    docFile += "</body>";
    docFile += "</html>";

    if ( defaults.outputMode === 'string' )
        return docFile;

    if ( defaults.outputMode === 'base64' )
        return base64encode(docFile);

    try {
        blob = new Blob([docFile], {type: 'application/vnd.ms-' + defaults.type});
        saveAs(blob, defaults.fileName + '.' + MSDocExt);
    }
    catch (e) {
        downloadFile(defaults.fileName + '.' + MSDocExt,
            'data:application/vnd.ms-' + MSDocType + ';base64,',
            docFile);
    }


}
function exportInsert(){
    try {
        var tdData = "INSERT INTO `tableName` (";
        var queryResult = $("#queryResult").val();

        var result = new JSONFormat(queryResult, 4);
        $.each(result.data.data.tableColumns,function (i,o) {
            if(i>0){
                tdData += "'" + o.field + "',";
            }
        });
        tdData = $.trim(tdData).substring(0, tdData.length - 1);
        tdData += ") \r\nVALUES ";

        $.each(result.data.data.tableData,function (i,tableData) {
            tdData += "(";
            $.each(result.data.data.tableColumns,function (i,o) {
                if(i>0) {
                    if (tableData[o.field]) {
                        tdData += "'" + tableData[o.field] + "',";
                    } else {
                        tdData += "null,";
                    }
                }
            });
            tdData += "),\r\n";
        });
        tdData = $.trim(tdData).substring(0, tdData.length - 1);
        tdData += ";";

        blob = new Blob([tdData], {type: "text/plain;charset=utf-8"});
        saveAs(blob, 'insert.sql');
    }
    catch (e) {
        downloadFile('insert.sql',
            'data:application/sql;charset=utf-8,',
            tdData);
    }
}
function exportUpdate(){

    try {
        var tdData = "";
        var queryResult = $("#queryResult").val();

        var result = new JSONFormat(queryResult, 4);

        var columnName = $("#columnName").val();
        $.each(result.data.data.tableData,function (i,tableData) {
            tdData += "update `tableName` set ";
            $.each(result.data.data.tableColumns,function (i,o) {
                if(i>0) {
                    if(columnName != o.field){
                        tdData += o.field + "=";
                        if (tableData[o.field]) {
                            tdData += "'" + tableData[o.field] + "',";
                        } else {
                            tdData += "null,";
                        }
                    }
                }
            });
            tdData = $.trim(tdData).substring(0, tdData.length - 1);
            tdData += " where "+columnName+"='"+tableData[columnName]+"';\r\n";
        });

        blob = new Blob([tdData], {type: "text/plain;charset=utf-8"});
        saveAs(blob, 'update.sql');
    }
    catch (e) {
        downloadFile('update.sql',
            'data:application/sql;charset=utf-8,',
            tdData);
    }
}


function downloadFile (filename, header, data) {
    var ua = window.navigator.userAgent;
    if ( filename !== false && window.navigator.msSaveOrOpenBlob ) {
        //noinspection JSUnresolvedFunction
        window.navigator.msSaveOrOpenBlob(new Blob([data]), filename);
    }
    else if ( filename !== false && (ua.indexOf("MSIE ") > 0 || !!ua.match(/Trident.*rv\:11\./)) ) {
        // Internet Explorer (<= 9) workaround by Darryl (https://github.com/dawiong/tableExport.jquery.plugin)
        // based on sampopes answer on http://stackoverflow.com/questions/22317951
        // ! Not working for json and pdf format !
        var frame = document.createElement("iframe");

        if ( frame ) {
            document.body.appendChild(frame);
            frame.setAttribute("style", "display:none");
            frame.contentDocument.open("txt/plain", "replace");
            frame.contentDocument.write(data);
            frame.contentDocument.close();
            frame.contentDocument.focus();

            var extension = filename.substr((filename.lastIndexOf('.') +1));
            switch(extension) {
                case 'doc': case 'json': case 'png': case 'pdf': case 'xls': case 'xlsx':
                    filename += ".txt";
                    break;
            }
            frame.contentDocument.execCommand("SaveAs", true, filename);
            document.body.removeChild(frame);
        }
    }
    else {
        var DownloadLink = document.createElement('a');

        if ( DownloadLink ) {
            var blobUrl = null;

            DownloadLink.style.display = 'none';
            if ( filename !== false )
                DownloadLink.download = filename;
            else
                DownloadLink.target = '_blank';

            if ( typeof data === 'object' ) {
                window.URL = window.URL || window.webkitURL;
                var binaryData = [];
                binaryData.push(data);
                blobUrl = window.URL.createObjectURL(new Blob(binaryData, {type: header}));
                DownloadLink.href = blobUrl;
            }
            else if ( header.toLowerCase().indexOf("base64,") >= 0 )
                DownloadLink.href = header + base64encode(data);
            else
                DownloadLink.href = header + encodeURIComponent(data);

            document.body.appendChild(DownloadLink);
            if ( document.createEvent ) {
                if ( DownloadEvt === null )
                    DownloadEvt = document.createEvent('MouseEvents');

                DownloadEvt.initEvent('click', true, false);
                DownloadLink.dispatchEvent(DownloadEvt);
            }
            else if ( document.createEventObject )
                DownloadLink.fireEvent('onclick');
            else if ( typeof DownloadLink.onclick === 'function' )
                DownloadLink.onclick();

            setTimeout(function(){
                if ( blobUrl )
                    window.URL.revokeObjectURL(blobUrl);
                document.body.removeChild(DownloadLink);
            }, 100);
        }
    }
}


function base64encode (input) {
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    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;
}


function utf8Encode (text) {
    if (typeof text === 'string') {
        text = text.replace(/\x0d\x0a/g, "\x0a");
        var utftext = "";
        for ( var n = 0; n < text.length; n++ ) {
            var c = text.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;
    }
    return text;
}
