"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var Utils_1 = __importDefault(require("../Utils"));
var Helpers_1 = __importDefault(require("../Helpers"));
var _ = __importStar(require("underscore"));
var PageContent = /** @class */ (function () {
    function PageContent(rawContent) {
        this.structured = false;
        this.canDoDelta = true;
        this.dirty = false;
        this._original = [[]];
        this._current = [[]];
        this._deltas = [];
        this._newRows = [];
        this._newCols = [];
        // private _defaultStyles: IPageCellStyle = {
        //   'background-color': 'FFFFFF',
        //   color: '000000',
        //   'font-family': 'sans-serif',
        //   'font-size': '11pt',
        //   'font-style': 'normal',
        //   'font-weight': 'normal',
        //   height: '20px',
        //   'number-format': '',
        //   'text-align': 'left',
        //   'text-wrap': 'normal',
        //   width: '64px',
        //   tbs: 'none',
        //   rbs: 'none',
        //   bbs: 'none',
        //   lbs: 'none',
        //   tbc: '000000',
        //   rbc: '000000',
        //   bbc: '000000',
        //   lbc: '000000',
        //   tbw: 'none',
        //   rbw: 'none',
        //   bbw: 'none',
        //   lbw: 'none',
        // };
        this.borders = {
            widths: {
                none: 0,
                thin: 1,
                medium: 2,
                thick: 3
            },
            styles: {
                none: 'solid',
                solid: 'solid',
                double: 'double'
            },
            names: {
                t: 'top',
                r: 'right',
                b: 'bottom',
                l: 'left'
            }
        };
        this.cellStyles = [
            'background-color',
            'color',
            'font-family',
            'font-size',
            'font-style',
            'font-weight',
            'height',
            'text-align',
            'text-wrap',
            'width',
            'vertical-align'
        ];
        if (!rawContent || rawContent.constructor !== Array || !rawContent.length || !rawContent[0].length) {
            rawContent = this.defaultContent();
        }
        this._utils = new Utils_1.default();
        this._helpers = new Helpers_1.default();
        // this._original = this._utils.clonePageContent(rawContent);
        // this._current = this.mergeStyles(rawContent);
        this.update(rawContent, true);
    }
    Object.defineProperty(PageContent.prototype, "deltas", {
        get: function () {
            return this._deltas;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PageContent.prototype, "current", {
        get: function () {
            return this._current;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PageContent.prototype, "original", {
        get: function () {
            return this._original;
        },
        enumerable: true,
        configurable: true
    });
    PageContent.prototype.update = function (rawContent, clean, replace) {
        if (clean === void 0) { clean = false; }
        if (replace === void 0) { replace = false; }
        // page history
        if (replace) {
            this.dirty = true;
            this._current = rawContent;
            this._deltas = [];
            return;
        }
        else {
            this._original = rawContent;
        }
        var style = __assign({}, this._utils.getDefaultCellStyle());
        this._current = this._utils.mergePageContent(this._original, clean ? null : this._deltas, style);
    };
    PageContent.prototype.updateDelta = function (content) {
        if (!content || !content.length)
            return;
        for (var rowIndex = 0; rowIndex < content.length; rowIndex++) {
            var row = content[rowIndex];
            if (!row)
                continue;
            for (var colIndex = 0; colIndex < row.length; colIndex++) {
                var col = row[colIndex];
                if (!col || !this._current[rowIndex] || !this._current[rowIndex][colIndex])
                    continue;
                this._original[rowIndex][colIndex] = col;
                this._current[rowIndex][colIndex] = col;
            }
        }
    };
    PageContent.prototype.reset = function (content) {
        // Remove new rows and columns
        for (var i = 0; i < this._newRows.length; i++) {
            this._current.splice(this._newRows[i], 1);
        }
        for (var i = 0; i < this._newCols.length; i++) {
            for (var j = 0; j < this._current.length; j++) {
                this._current[j].splice(this._newCols[i], 1);
            }
        }
        this._deltas = [];
        this.dirty = false;
        this.update(content || this._original, true);
    };
    Object.defineProperty(PageContent.prototype, "rowLen", {
        get: function () {
            return this.current.length;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PageContent.prototype, "colLen", {
        get: function () {
            return this.current.length ? this.current[0].length : 0;
        },
        enumerable: true,
        configurable: true
    });
    PageContent.prototype.getCellByRef = function (ref) {
        var rowCol = this._helpers.getRefIndex(ref);
        return this.getCell(rowCol[0], rowCol[1]);
    };
    PageContent.prototype.getCell = function (rowIndex, columnIndex) {
        if (!this._current[rowIndex]) {
            throw new Error('row out of bounds');
        }
        if (!this._current[rowIndex][columnIndex]) {
            throw new Error('column out of bounds');
        }
        return this._current[rowIndex][columnIndex];
    };
    PageContent.prototype.getCells = function (fromCell, toCell, valueOnly, noIndex) {
        var cells = [];
        var rowIndex = 0;
        var colIndex = 0;
        for (var row = fromCell.row; row <= toCell.row; row++) {
            colIndex = 0;
            if (noIndex)
                cells[rowIndex] = [];
            for (var col = fromCell.col; col <= toCell.col; col++) {
                if (!cells[row] && !noIndex)
                    cells[row] = [];
                cells[noIndex ? rowIndex : row][noIndex ? colIndex : col] = valueOnly ? this._current[row][col].value : this._current[row][col];
                colIndex++;
            }
            rowIndex++;
        }
        return cells;
    };
    PageContent.prototype.getCellsByRange = function (str, valueOnly, noIndex) {
        var range = this._helpers.cellRange(str, this._current.length, this._current[0].length);
        return this.getCells(range.from, range.to, valueOnly, noIndex);
    };
    PageContent.prototype.getRowCells = function (rowIndex) {
        if (!this._current[rowIndex]) {
            throw new Error('row out of bounds');
        }
        return this._current[rowIndex];
    };
    PageContent.prototype.getColCells = function (columnIndex) {
        if (!this._current[0][columnIndex]) {
            throw new Error('column out of bounds');
        }
        var cells = [];
        for (var row = 0; row < this._current.length - 1; row++) {
            cells.push(this._current[row][columnIndex]);
        }
        return cells;
    };
    PageContent.prototype.updateCellByRef = function (ref, data) {
        var rowCol = this._helpers.getRefIndex(ref);
        this.updateCell(rowCol[0], rowCol[1], data);
    };
    PageContent.prototype.updateCell = function (rowIndex, columnIndex, data, delta) {
        if (delta === void 0) { delta = true; }
        if (!this._current[rowIndex]) {
            throw new Error('row out of bounds');
        }
        if (!this._current[rowIndex][columnIndex]) {
            throw new Error('column out of bounds');
        }
        // Check if cell has been edited
        // data.dirty = true;
        // this.dirty = true;
        // @todo This will probably not work with styles
        var cell = __assign(__assign({}, this._current[rowIndex][columnIndex]), data);
        if (data.style) {
            // delete data.style.width;
            // delete data.style.height;
            cell.style = __assign(__assign({}, this._current[rowIndex][columnIndex].style), data.style);
            cell.originalStyle = __assign({}, this._current[rowIndex][columnIndex].style);
        }
        this._current[rowIndex][columnIndex] = cell;
        if (delta)
            this.addDelta(cell, rowIndex, columnIndex);
    };
    PageContent.prototype.updateCells = function (from, to, data) {
        for (var rowIndex = from.row; rowIndex <= to.row; rowIndex++) {
            for (var colIndex = from.col; colIndex <= to.col; colIndex++) {
                this.updateCell(rowIndex, colIndex, data);
            }
        }
    };
    // public insertRow (data: any): void {
    // }
    PageContent.prototype.addRow = function (index, direction) {
        if (!this._current[index]) {
            index = this._current.length - 1;
            direction = 'below';
        }
        var inc = direction === 'below' ? 1 : 0;
        var newRowData = [];
        // Clone row before
        if (this._current.length) {
            for (var i = 0; i < this._current[index].length; i++) {
                var clone = JSON.parse(JSON.stringify(this._current[index][i]));
                clone.value = '';
                clone.formatted_value = '';
                clone.dirty = true;
                if (clone.link)
                    delete clone.link;
                newRowData.push(clone);
            }
        }
        this._current.splice(index + inc, 0, newRowData);
        this._current = this._utils.mergePageContent(this._current);
    };
    PageContent.prototype.moveColumns = function (fromIndex, toIndex, newIndex) {
        if (!this._current[0]) {
            throw new Error('row out of bounds');
        }
        if (!this._current[0][fromIndex]) {
            throw new Error('column out of bounds');
        }
        if (!this._current[0][newIndex]) {
            throw new Error('column out of bounds');
        }
        // if (newIndex > fromIndex) {
        //     newIndex++;
        // }
        // let cells: IPageContentCell[] = [];
        // get columns cells
        for (var i = 0; i < this._current.length; i++) {
            var clone = void 0;
            var cells = [];
            for (var k = 0; k < this._current[i].length; k++) {
                if (k < fromIndex || k > toIndex) {
                    continue;
                }
                clone = JSON.parse(JSON.stringify(this._current[i][k]));
                clone.dirty = true;
                cells.push(clone);
            }
            var cellStr = [];
            for (var n = 0; n < cells.length; n++) {
                cellStr.push("cells[" + n + "]");
            }
            var evalStr = "this._current[i].splice(newIndex, 0, " + cellStr.join(',') + ");";
            eval(evalStr);
            if (newIndex > fromIndex) {
                this._current[i].splice(fromIndex, 1 + toIndex - fromIndex);
            }
            else {
                this._current[i].splice(fromIndex + 1 + toIndex - fromIndex, 1 + toIndex - fromIndex);
            }
        }
        this._current = this._utils.mergePageContent(this._current);
    };
    PageContent.prototype.addColumn = function (index, direction) {
        if (!this._current[0][index]) {
            index = this._current[0].length - 1;
            direction = 'right';
        }
        var inc = direction === 'right' ? 1 : 0;
        for (var i = 0; i < this._current.length; i++) {
            var clone = void 0;
            // for (let k: number = 0; k < this._current[i].length; k++) {
            //     if (k !== index) {
            //         continue;
            //     }
            clone = JSON.parse(JSON.stringify(this._current[i][index]));
            clone.dirty = true;
            clone.value = '';
            clone.formatted_value = '';
            if (clone.link)
                delete clone.link;
            // clone.index.col = index + inc;
            // }
            // this._current[i][index].index.col += direction === "right" ? 0 : 1;
            this._current[i].splice(index + inc, 0, clone);
        }
        this._current = this._utils.mergePageContent(this._current);
    };
    PageContent.prototype.removeRow = function (index) {
        if (!this._current[index] || this._current.length === 1) {
            return;
        }
        this._current.splice(index, 1);
        this._current = this._utils.mergePageContent(this._current);
        if (this._deltas[index]) {
            this._deltas[index] = [];
        }
    };
    PageContent.prototype.removeColumn = function (index) {
        if (!this._current[0][index] || this._current[0].length === 1) {
            return;
        }
        for (var i = 0; i < this._current.length; i++) {
            this._current[i].splice(index, 1);
            if (this._deltas[i] && this._deltas[i][index]) {
                delete this._deltas[i][index];
            }
        }
        this._current = this._utils.mergePageContent(this._current);
    };
    PageContent.prototype.setRowSize = function (row, value) {
        if (!this._current[row]) {
            return;
        }
        for (var colIndex = 0; colIndex < this._current[row].length; colIndex++) {
            var cell = this._current[row][colIndex];
            this.updateCell(row, colIndex, { value: cell.value, formatted_value: cell.formatted_value, style: { height: value + "px" } }, true);
            // if (!cell.style) cell.style = {};
            // cell.style.height = `${value}px`;
            // cell.dirty = true;
        }
    };
    PageContent.prototype.setColSize = function (col, value) {
        if (!this._current[0][col]) {
            return;
        }
        for (var rowIndex = 0; rowIndex < this._current.length; rowIndex++) {
            var cell = this._current[rowIndex][col];
            this.updateCell(rowIndex, col, { value: cell.value, formatted_value: cell.formatted_value, style: { width: value + "px" } }, true);
            // if (!cell.style) cell.style = {};
            // cell.style.width = `${value}px`;
            // cell.dirty = true;
        }
    };
    // @todo Would be better to supply the two contents rather than using "this"
    PageContent.prototype.getDelta = function () {
        // This is expensive, but will get proper styles
        var current = this._utils.clonePageContent(this._current);
        /**
         * Specs (Jira IPPWSTWO-195)
         * @type {{new_rows: Array, new_cols: Array, content_delta: *[]}}
         */
        var deltaStructure = {
            // First "commit" changes to the layout of page - add new cols and rows
            new_rows: [],
            new_cols: [],
            // @todo: Handle removed rows and cols
            // Second, process the data - Data will have right referencing already with added rows and cells
            content_delta: [
                {
                    row_index: 0,
                    cols: [
                        {
                            col_index: 0,
                            cell_content: {
                                value: '',
                                style: {}
                            }
                        }
                    ]
                }
            ]
        };
        /**
         *  --------------------------------------------
         */
        deltaStructure.content_delta = []; // just empty it
        deltaStructure.new_rows = this._newRows;
        deltaStructure.new_cols = this._newCols;
        var rowMovedBy = 0;
        var colMovedBy = 0;
        // @todo Every cell will get full styles basically braking inheritence model = adding more data to a page. We need to be able to work around this somehow
        for (var i = 0; i < current.length; i++) {
            var rowData = {};
            var newRow = this._newRows.indexOf(i) >= 0;
            colMovedBy = 0;
            if (newRow) {
                rowData = {
                    row_index: i,
                    cols: []
                };
                rowMovedBy++;
            }
            for (var j = 0; j < current[i].length; j++) {
                if (newRow) {
                    var cell = _.clone(current[i][j]);
                    delete cell.dirty;
                    // delete cell.formatting;
                    rowData.cols.push({
                        col_index: j,
                        cell_content: cell
                    });
                }
                else {
                    var newCol = this._newCols.indexOf(j) >= 0;
                    if (newCol) {
                        colMovedBy++;
                    }
                    if (newCol || current[i][j].dirty) {
                        if (!Object.keys(rowData).length) {
                            rowData = {
                                row_index: i,
                                cols: []
                            };
                        }
                        var cell = _.clone(current[i][j]);
                        delete cell.dirty;
                        delete cell.originalStyle;
                        delete cell.button;
                        rowData.cols.push({
                            col_index: j,
                            cell_content: cell
                        });
                    }
                }
            }
            if (Object.keys(rowData).length) {
                deltaStructure.content_delta.push(rowData);
            }
            // Sort new cols and rows
            // @todo uncomment this when deleting rows and columns is enabled
            /*deltaStructure.new_cols.sort(ipp.this._utils.sortByNumber);
                 deltaStructure.new_rows.sort(ipp.this._utils.sortByNumber);*/
        }
        // @todo Do something with styles
        return deltaStructure;
    };
    PageContent.prototype.getCellDeltas = function () {
        var deltaStructure = {
            new_rows: [],
            new_cols: [],
            content_delta: [
                {
                    row_index: 0,
                    cols: [
                        {
                            col_index: 0,
                            cell_content: {
                                value: '',
                                style: {}
                            }
                        }
                    ]
                }
            ]
        };
        deltaStructure.content_delta = [];
        var deltas = this._deltas.concat();
        this._deltas = [];
        for (var rowIndex = 0; rowIndex < deltas.length; rowIndex++) {
            var row = deltas[rowIndex];
            if (!row)
                continue;
            var cols = [];
            for (var colIndex = 0; colIndex < row.length; colIndex++) {
                var col = row[colIndex];
                if (!col)
                    continue;
                var cell = _.clone(this._current[rowIndex][colIndex]);
                delete cell.dirty;
                delete cell.originalStyle;
                delete cell.button;
                cols.push({
                    col_index: colIndex,
                    cell_content: cell
                });
            }
            // if (hasSchema && rowIndex - 1 < 0) continue;
            deltaStructure.content_delta.push({
                row_index: rowIndex,
                cols: cols
            });
        }
        return deltaStructure;
    };
    PageContent.prototype.getQuery = function () {
        var deltas = this._deltas.concat();
        this._deltas = [];
        // columns and pks
        var columns = [];
        var pks = [];
        this.current[0].forEach(function (cell, colIndex) {
            if (cell.pk)
                pks.push(colIndex);
            columns.push(cell.column_name);
        });
        if (!pks.length) {
            return {
                error: 'No primary keys found'
            };
        }
        var updates = [];
        for (var rowIndex = 0; rowIndex < deltas.length; rowIndex++) {
            var row = deltas[rowIndex];
            if (!row)
                continue;
            var update = {};
            var where = {};
            for (var colIndex = 0; colIndex < row.length; colIndex++) {
                var col = row[colIndex];
                var cell = this._current[rowIndex][colIndex];
                var ogCell = this._original[rowIndex][colIndex];
                if (pks.includes(colIndex)) {
                    where[columns[colIndex]] = ogCell.value;
                }
                if (!col)
                    continue;
                update[columns[colIndex]] = cell.value;
            }
            updates.push({
                update: update,
                where: where
            });
        }
        /*{
          "updates":[
             {
                "update":{
                   "bid":100.123,
                   "ask":100.125
                },
                "where":{
                   "isin":"JIMBO12345"
                }
             },
          ],
          "deletes":[
             {
                "where":{
                   "country":"France"
                }
             }
          ]
       }*/
        var query = {};
        if (updates.length)
            query.updates = updates;
        return query;
    };
    PageContent.prototype.getFull = function () {
        var content = this._utils.clonePageContent(this._current);
        // Remove dirty indicator
        for (var i = 0; i < content.length; i++) {
            for (var j = 0; j < content[i].length; j++) {
                delete content[i][j].dirty;
                delete content[i][j].originalStyle;
                // delete content[i][j].formatting;
            }
        }
        return content;
    };
    PageContent.prototype.getHtml = function (from, to) {
        var left = 0;
        var width = 0;
        var height = 0;
        var cells = [];
        var html = "<table style=\"border-collapse: collapse;\">";
        for (var rowIndex = 0; rowIndex < this._current.length; rowIndex++) {
            cells[rowIndex] = [];
            var row = this._current[rowIndex];
            html += "<tr>";
            left = 0;
            for (var colIndex = 0; colIndex < row.length; colIndex++) {
                var cell = row[colIndex];
                var styles = this.flattenStyles(cell.style);
                html += "<td style=\"" + styles + "\"><div>" + cell.formatted_value + "</div></td>";
                left += parseFloat(cell.style.width);
                if (!rowIndex) {
                    width += parseFloat(cell.style.width);
                }
                if (!colIndex) {
                    height += parseFloat(cell.style.height);
                }
                cells[rowIndex].push({
                    value: cell.formatted_value,
                    style: styles
                });
            }
            var colLast = row[row.length - 1];
            if (!rowIndex && colLast.style && colLast.style.rbw) {
                // width += parseFloat(colLast.style.rbw);
            }
            html += "</tr>";
        }
        var cellLast = this._current[this._current.length - 1][0];
        if (cellLast.style && cellLast.style.rbw && cellLast.style.rbw !== 'none') {
            // height += parseFloat(cellLast.style.rbw);
        }
        html += "</table>";
        return {
            width: width,
            height: height,
            html: html,
            cells: cells
        };
    };
    PageContent.prototype.flattenStyles = function (styles, only) {
        var htmlStyle = {};
        this.cellStyles.forEach(function (s) {
            htmlStyle[s] = styles[s];
        });
        for (var key in this.borders.names) {
            var name_1 = this.borders.names[key];
            var width = this.borders.widths[styles[key + "bw"]] + 'px';
            var style = styles[key + "bs"];
            var color = '#' + styles[key + "bc"].replace('#', '');
            htmlStyle["border-" + name_1] = width + " " + style + " " + color;
        }
        var str = '';
        for (var attr in htmlStyle) {
            var value = htmlStyle[attr];
            if ((attr === 'background-color' || attr === 'color') && value.indexOf('#') === -1) {
                value = "#" + value;
            }
            if (only && only.indexOf(attr) < 0)
                continue;
            str += attr + ":" + value + ";";
        }
        return str;
    };
    PageContent.prototype.addDelta = function (cell, row, col) {
        if (!this._deltas[row])
            this._deltas[row] = [];
        this._deltas[row][col] = cell;
    };
    PageContent.prototype.defaultContent = function () {
        return [
            [
                {
                    value: '',
                    formatted_value: ''
                }
            ]
        ];
    };
    return PageContent;
}());
exports.PageContent = PageContent;
//# sourceMappingURL=Content.js.map