import { h } from '../webmapgl.core.js';

class TableExportButton {
    constructor() {
        this.format = 'csv';
    }
    async clickHandler() {
        this.exportCtrl.create(this);
    }
    render() {
        return (h("ion-button", { "ion-button": true, onClick: () => this.clickHandler() },
            h("slot", null, this.format.toUpperCase())));
    }
    static get is() { return "gl-table-export-button"; }
    static get properties() { return {
        "author": {
            "type": String,
            "attr": "author"
        },
        "exportCtrl": {
            "connect": "gl-table-export-controller"
        },
        "filename": {
            "type": String,
            "attr": "filename"
        },
        "format": {
            "type": String,
            "attr": "format"
        },
        "pageOrientation": {
            "type": String,
            "attr": "page-orientation"
        },
        "pageSubtitle": {
            "type": String,
            "attr": "page-subtitle"
        },
        "pageTitle": {
            "type": String,
            "attr": "page-title"
        },
        "tableId": {
            "type": String,
            "attr": "table-id"
        }
    }; }
}

var fileDownload = function(data, filename, mime, bom) {
    var blobData = (typeof bom !== 'undefined') ? [bom, data] : [data];
    var blob = new Blob(blobData, {type: mime || 'application/octet-stream'});
    if (typeof window.navigator.msSaveBlob !== 'undefined') {
        // IE workaround for "HTML7007: One or more blob URLs were 
        // revoked by closing the blob for which they were created. 
        // These URLs will no longer resolve as the data backing 
        // the URL has been freed."
        window.navigator.msSaveBlob(blob, filename);
    }
    else {
        var blobURL = window.URL.createObjectURL(blob);
        var tempLink = document.createElement('a');
        tempLink.style.display = 'none';
        tempLink.href = blobURL;
        tempLink.setAttribute('download', filename); 
        
        // Safari thinks _blank anchor are pop ups. We only want to set _blank
        // target if the browser does not support the HTML5 download attribute.
        // This allows you to download files in desktop safari if pop up blocking 
        // is enabled.
        if (typeof tempLink.download === 'undefined') {
            tempLink.setAttribute('target', '_blank');
        }
        
        document.body.appendChild(tempLink);
        tempLink.click();
        document.body.removeChild(tempLink);
        window.URL.revokeObjectURL(blobURL);
    }
};

function csvQuote(value) {
    if (!value)
        return '';
    return (value.indexOf(',') !== -1) ?
        `"${value.replace(/"/g, '""')}"` : value;
}
class TableExportController {
    async create(options) {
        let tableSelector = 'gl-table' +
            ((options.tableId) ? `#${options.tableId}` : '');
        let table = (options.table) ? options.table :
            document.querySelector(tableSelector);
        let features = (options.features) ? options.features :
            await table.getSortedFeatures();
        let columns = (options.columns) ? options.columns :
            Array.from(table.querySelectorAll('gl-table-column'));
        if (options.format === 'csv')
            this.exportCsv(table, features, columns, options);
        if (options.format === 'pdf')
            this.exportPdf(table, features, columns, options);
    }
    async exportCsv(table, features, columns, options) {
        let csv = await this.createCsvDoc(table, features, columns);
        fileDownload(csv, this.getFilename(options), 'text/csv');
    }
    async exportPdf(table, features, columns, options) {
        pdfMake.createPdf(await this.createDocDef(table, features, columns, options)).download(this.getFilename(options));
    }
    getFilename(options) {
        if (options.filename)
            return options.filename;
        if (!options.pageTitle)
            return `table.${options.format}`;
        return `${options.pageTitle.toLowerCase()
            .replace(/[^a-z0-9]+/g, '_')}.${options.format}`;
    }
    zebraFill(i) {
        if (i === 0)
            return 'black';
        return (i % 2 === 0) ? '#ECEBEB' : null;
    }
    async createCsvDoc(table, features, columns) {
        let filteredColumns = columns.filter(col => col.visible);
        let headerRow = filteredColumns.map((col) => csvQuote(col.label));
        let featureRows = (await Promise.all(features.map((feature) => this.getTableRow(table, feature, filteredColumns, 'text'))))
            .map((row) => row.map((cell) => csvQuote(cell)));
        return [headerRow, ...featureRows]
            .map((row) => row.join(','))
            .join('\n');
    }
    getTableRow(table, feature, columns, type = 'pdf') {
        return Promise.all(columns.map((column) => table.getCellContents(feature, column, type)));
    }
    async createDocDef(table, features, columns, options) {
        let filteredColumns = columns.filter((col) => col.visible);
        let header = filteredColumns.map((col) => {
            return { text: col.label, style: 'tableHeader' };
        });
        let featureRows = await Promise.all(features.map((feature) => this.getTableRow(table, feature, filteredColumns)));
        let docDef = {
            info: {},
            pageOrientation: options.pageOrientation,
            content: [
                {
                    table: {
                        headerRows: 1,
                        body: [header, ...featureRows]
                    },
                    style: 'table',
                    layout: {
                        fillColor: this.zebraFill
                    }
                },
            ],
            styles: {
                tableHeader: {
                    color: 'white'
                },
                header: {
                    fontSize: 15,
                    bold: true,
                    margin: [0, 0, 0, 5]
                },
                subHeader: {
                    margin: [0, 5, 0, 15]
                }
            },
        };
        if (options.pageSubtitle)
            docDef['content'].unshift({ text: options.pageSubtitle, style: 'subHeader', alignment: 'center' });
        if (options.pageTitle) {
            docDef['info']['title'] = options.pageTitle;
            docDef['content'].unshift({ text: options.pageTitle, style: 'header', alignment: 'center' });
        }
        if (options.author)
            docDef['info']['author'] = options.author;
        return docDef;
    }
    static get is() { return "gl-table-export-controller"; }
    static get properties() { return {
        "create": {
            "method": true
        }
    }; }
}

export { TableExportButton as GlTableExportButton, TableExportController as GlTableExportController };
