"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// declare var moment: any;
var moment_timezone_1 = __importDefault(require("moment-timezone"));
// declare module 'hot-formula-parser' {
//   function Parser(): any;
//   export = Parser;
// }
var Emitter_1 = __importDefault(require("./Emitter"));
var Helpers_1 = __importDefault(require("./Helpers"));
var hot_formula_parser_1 = require("hot-formula-parser");
var Functions = /** @class */ (function (_super) {
    __extends(Functions, _super);
    function Functions(content, vars) {
        if (content === void 0) { content = []; }
        if (vars === void 0) { vars = {}; }
        var _this = _super.call(this) || this;
        _this.content = content;
        _this.vars = vars;
        _this.selectedRows = [];
        _this.helpers = new Helpers_1.default();
        _this.parser = new hot_formula_parser_1.Parser();
        _this.parser.on('callCellValue', function (cellCoord, done) {
            if (_this.content[cellCoord.row.index] && _this.content[cellCoord.row.index][cellCoord.column.index]) {
                done(_this.content[cellCoord.row.index][cellCoord.column.index]);
            }
            else {
                done('#ERROR!');
            }
        });
        _this.parser.on('callRangeValue', function (startCellCoord, endCellCoord, done) {
            var fragment = [];
            for (var row = startCellCoord.row.index; row <= endCellCoord.row.index; row++) {
                var rowData = _this.content[row];
                if (!rowData)
                    continue;
                var colFragment = [];
                for (var col = startCellCoord.column.index; col <= endCellCoord.column.index; col++) {
                    if (!rowData[col])
                        continue;
                    colFragment.push(_this.getCellValue(rowData[col]));
                }
                if (colFragment.length)
                    fragment.push(colFragment);
            }
            if (fragment.length) {
                done(fragment);
            }
            else {
                done('#ERROR!');
            }
        });
        _this.parser.setFunction('IPPVAR', function (params) {
            if (!params[0]) {
                return '#ERROR!';
            }
            var p = ("" + params[0]).toLowerCase();
            if (!_this.vars[p]) {
                return '#ERROR!';
            }
            return _this.vars[p];
        });
        _this.parser.setFunction('MAX', function (params) {
            if (params[0] === '#ERROR!' || !params[0].length || !params[0][0].length) {
                return '#ERROR!';
            }
            var max = params[0].flat().filter(function (n) { return ("" + n !== '' && n !== null); }).reduce(function (x, y) { return y > x ? y : x; });
            var nums = !isNaN(params[0][0]);
            var cellValue = _this.getCellValue(_this.cell, true);
            if (nums)
                cellValue = _this.helpers.convertToNumber(cellValue);
            if ("" + cellValue === '' || typeof cellValue !== typeof max)
                return false;
            return (cellValue >= max);
        });
        _this.parser.setFunction('MIN', function (params) {
            if (params[0] === '#ERROR!' || !params[0].length || !params[0][0].length) {
                return '#ERROR!';
            }
            var max = params[0].flat().filter(function (n) { return ("" + n !== '' && n !== null); }).reduce(function (x, y) { return y < x ? y : x; });
            var nums = !isNaN(params[0][0]);
            var cellValue = _this.getCellValue(_this.cell, true);
            if (nums)
                cellValue = _this.helpers.convertToNumber(cellValue);
            if ("" + cellValue === '' || typeof cellValue !== typeof max)
                return false;
            return (cellValue <= max);
        });
        _this.parser.setFunction('NUMBERVALUE', function (params) {
            if (params[0] === '#ERROR!') {
                return '#ERROR!';
            }
            // check if multiple values
            if (typeof params[0] === 'object') {
                return params[0].map(function (row) {
                    return row.map(function (n) { return _this.helpers.convertToNumber(n); });
                });
            }
            else {
                // let cellValue = this.getCellValue(this.cell, true);
                return _this.helpers.convertToNumber(params[0]) || '#VALUE!';
            }
        });
        _this.parser.setFunction('CHECKED', function (params) {
            if (params[0] === '#ERROR!') {
                return '#ERROR!';
            }
            if (!_this.cell.index)
                return false;
            return _this.selectedRows.includes(_this.cell.index.row);
        });
        _this.parser.setFunction('MOD', function (params) {
            if (!_this.cell || params[0] === undefined || params[1] === undefined || isNaN(params[0]) || isNaN(params[1])) {
                return '#ERROR!';
            }
            var num = parseFloat(params[0]);
            var div = parseFloat(params[1]);
            return num % div;
        });
        _this.parser.setFunction('ROW', function (params) {
            if (params[0] === '#ERROR!') {
                return '#ERROR!';
            }
            if (!_this.cell.index)
                return -1;
            return _this.cell.index.row;
        });
        _this.parser.setFunction('VALUE', function (params) {
            if (params[0] === '#ERROR!') {
                return '#ERROR!';
            }
            if (!params[0]) {
                return _this.cell ? _this.getCellValue(_this.cell) : '#ERROR!';
            }
            return _this.getCellValue(params[0]);
        });
        _this.parser.setFunction('RAWVALUE', function (params) {
            if (params[0] === '#ERROR!') {
                return '#ERROR!';
            }
            if (!params[0]) {
                return _this.cell ? _this.getCellValue(_this.cell, true) : '#ERROR!';
            }
            return _this.getCellValue(params[0], true);
        });
        _this.parser.setFunction('OFFSET', function (params) {
            if (!_this.cell || params[0] === undefined || params[1] === undefined || isNaN(params[0]) || isNaN(params[1])) {
                return '#ERROR!';
            }
            var row = parseFloat(params[0]);
            var col = parseFloat(params[1]);
            if (_this.content[_this.cell.index.row + row] && _this.content[_this.cell.index.row + row][_this.cell.index.col + col]) {
                return _this.content[_this.cell.index.row + row][_this.cell.index.col + col];
            }
            return '#ERROR!';
        });
        _this.parser.setFunction('DATETIME', function (params) {
            var time = moment_timezone_1.default
                .tz(params[1] || 'UTC')
                .add(params[2] || 0, params[3] || 'minutes')
                .format(params[0]);
            return time;
        });
        _this.parser.setFunction('SYTAG', function (params) {
            if (params[0] === undefined) {
                return '#ERROR!';
            }
            var message = '';
            var arg = params[1];
            switch (params[0]) {
                case 'mention':
                    // arg = arg.replace(/[^a-z0-9]/gi, '');
                    if (_this.helpers.isValidEmail(arg)) {
                        message = "<mention email=\"" + arg + "\" strict=\"false\"/>";
                    }
                    else {
                        message = '#ERROR!';
                    }
                    break;
                case 'cash':
                    if (!arg) {
                        // arg = `ipp.${this.content.data.domain_name}.${this.content.data.name}`;
                    }
                    message = "<cash tag=\"" + _this.helpers.safeTitle(arg) + "\" />";
                    break;
                case 'hash':
                    message = "<hash tag=\"" + _this.helpers.safeTitle(arg) + "\" />";
                    break;
                case 'chime':
                    message = "<chime />";
                    break;
                case 'emoji':
                    message = "<emoji shortcode=\"" + _this.helpers.safeTitle(arg) + "\" />";
                    break;
                default:
                    message = '#ERROR!';
                    break;
            }
            return message;
        });
        _this.parser.setFunction('TABLE', function (params) {
            if (!_this.cell || params[0] === undefined || !(params[0] instanceof Array)) {
                return '#ERROR!';
            }
            var headerRow = 0;
            if (_this.helpers.isNumber(params[1]) && _this.content[params[1] - 1]) {
                headerRow = params[1] - 1;
            }
            var columns = params[0];
            var arr = [];
            var row = [];
            columns.forEach(function (col) {
                var cell = _this.content[headerRow][col];
                row.push(_this.getCellValue(cell));
            });
            arr.push(row);
            row = [];
            columns.forEach(function (col) {
                var cell = _this.content[_this.cell.index.row][col];
                row.push(_this.getCellValue(cell));
            });
            arr.push(row);
            return _this.helpers.tableFromArray(arr);
            // TABLE([3,4,5])
            // header row
            // columns
        });
        return _this;
    }
    Functions.prototype.updateVars = function (vars) {
        this.vars = vars;
    };
    Functions.prototype.updateContentDelta = function (content) {
        if (content === void 0) { 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.content[rowIndex] || !this.content[rowIndex][colIndex])
                    continue;
                this.content[rowIndex][colIndex] = col;
            }
        }
    };
    Functions.prototype.parse = function (str, joinWith) {
        var _this = this;
        if (joinWith === void 0) { joinWith = '\n'; }
        var results = [];
        var lines = ("" + str).split(/\n/);
        lines.forEach(function (line) {
            line = line.trim();
            if (!line || line[0] !== '=') {
                results.push(line);
                return;
            }
            var result = _this.parser.parse(_this.toUppercaseFunctions(line.replace('=', '')));
            results.push(result.result || result.error);
        });
        return results.join(joinWith);
    };
    Functions.prototype.getCellReference = function (str) {
        var result = this.parser.parse(str.trim());
        return result.result || null;
    };
    Functions.prototype.setCellReference = function (cell) {
        this.cell = cell;
    };
    Functions.prototype.isButtonWithinTaskRange = function (buttonCell, taskGroup) {
        if (buttonCell.button && buttonCell.button.name !== taskGroup.ref) {
            return false;
        }
        else if (!buttonCell.button && !taskGroup.range) {
            return false;
        }
        try {
            var range = taskGroup.ref ? buttonCell.button.range : taskGroup.range;
            var cellRange = this.helpers.cellRange(range, this.content.length, this.content[0].length);
            // const [taskFrom, taskTo] = this.helpers.getRefIndex(range); // range.split(':').map(str => this.helpers.getRefIndex(str));
            // let endRow: number = taskTo[0] < 0 ? this.page.Content.current.length : taskTo[0];
            //   const [buttonsFrom, buttonsTo] = buttonRange.split(':').map(str => this.helpers.getRefIndex(str));
            var endRow = cellRange.to.row < 0 ? this.content.length : cellRange.to.row;
            if (buttonCell.position.row < cellRange.from.row || buttonCell.position.row > endRow)
                return false;
            if (buttonCell.position.col < cellRange.from.col || buttonCell.position.col > cellRange.to.col)
                return false;
            return true;
        }
        catch (e) {
            return false;
        }
    };
    Functions.prototype.isTaskValid = function (task) {
        if (!task.condition)
            return true;
        try {
            return this.parse(task.condition) === 'true';
        }
        catch (e) {
            return false;
        }
    };
    Functions.prototype.getCellUpdate = function (action) {
        return this.updateCell(action);
    };
    Functions.prototype.updateCell = function (action) {
        try {
            if (!action.cell)
                return null;
            var cell = this.getCellReference(action.cell.replace('=', '').toUpperCase());
            if (!cell)
                return null;
            var formatted_value = this.parse(action.data.formatted_value);
            var value = this.parse(action.data.value);
            if (this.helpers.isNumber(formatted_value)) {
                formatted_value = parseFloat(formatted_value);
            }
            if (this.helpers.isNumber(value)) {
                value = parseFloat(value);
            }
            var update = {
                row: cell.index.row,
                col: cell.index.col,
                data: {
                    formatted_value: formatted_value,
                    value: value,
                    style: {},
                },
            };
            // this.content.Content.updateCell(update.row, update.col, update.data);
            return update;
        }
        catch (e) {
            return null;
        }
    };
    Functions.prototype.getCellFormatting = function (styles, buttons, contentDiff) {
        if (buttons === void 0) { buttons = []; }
        return this.setCellFormatting(styles, buttons, contentDiff);
    };
    Functions.prototype.setCellFormatting = function (styles, buttons, contentDiff) {
        var _this = this;
        if (buttons === void 0) { buttons = []; }
        if (!styles || !styles.length) {
            return [];
        }
        // let dirty: boolean = false;
        var cellStyles = [];
        styles.forEach(function (style) {
            // check for a button ref
            var range = style.range || '';
            if (!style.range) {
                buttons.forEach(function (button) {
                    if (button.name === style.ref) {
                        range = button.range;
                    }
                });
            }
            if (!range) {
                return;
            }
            // let content: IPageContentProvider = contentDiff || this.page.Content.current;
            var cellRange = _this.helpers.cellRange(range, _this.content.length, _this.content[0].length);
            // const from = cellRange.from;
            // const to = cellRange.to;
            // const [from, to] = range.split(':').map(str => this.helpers.getRefIndex(str));
            var endRow = cellRange.to.row < 0 ? _this.content.length : cellRange.to.row;
            var _loop_1 = function (colIndex) {
                var _loop_2 = function (rowIndex) {
                    if (rowIndex < cellRange.from.row || rowIndex > endRow)
                        return "continue";
                    var cell = contentDiff && contentDiff[rowIndex] && contentDiff[rowIndex][colIndex] ? contentDiff[rowIndex][colIndex] : _this.content[rowIndex][colIndex];
                    // cell.formatting = {};
                    _this.setCellReference(cell);
                    style.conditions.forEach(function (condition) {
                        if (_this.parse(condition.exp) !== 'true')
                            return;
                        // cell.formatting = condition.style;
                        if (condition.columns.indexOf(-1) > -1) {
                            for (var colConditionIndex = 0; colConditionIndex < _this.content[rowIndex].length; colConditionIndex++) {
                                if (!cellStyles[rowIndex]) {
                                    cellStyles[rowIndex] = [];
                                }
                                cellStyles[rowIndex][colConditionIndex] = condition.style;
                            }
                        }
                        else {
                            if (!cellStyles[rowIndex]) {
                                cellStyles[rowIndex] = [];
                            }
                            cellStyles[rowIndex][colIndex] = condition.style;
                        }
                    });
                };
                for (var rowIndex = 0; rowIndex < _this.content.length; rowIndex++) {
                    _loop_2(rowIndex);
                }
            };
            for (var colIndex = cellRange.from.col; colIndex <= cellRange.to.col; colIndex++) {
                _loop_1(colIndex);
            }
        });
        return cellStyles;
    };
    Functions.prototype.getTable = function (config) {
        var _this = this;
        // config.headers
        // config.values
        var arr = [];
        arr.push(config.headers);
        config.values.forEach(function (row) {
            var cells = [];
            row.forEach(function (index) {
                if (typeof index === 'string') {
                    cells.push(index);
                    return;
                }
                var cell = _this.content[_this.cell.index.row + index[0]][_this.cell.index.col + index[1]];
                cells.push(_this.getCellValue(cell));
            });
            arr.push(cells);
        });
        return this.helpers.tableFromArray(arr);
    };
    Functions.prototype.toUppercaseFunctions = function (expression) {
        // =value()="three" -> =VALUE()="three"
        var regex = /("(.*?)")/gm;
        var m;
        var replace = [];
        while ((m = regex.exec(expression)) !== null) {
            if (m.index === regex.lastIndex) {
                regex.lastIndex++;
            }
            replace.push(m[1]);
        }
        replace.forEach(function (str, i) {
            expression = expression.replace(str, "[" + i + "]");
        });
        expression = expression.toUpperCase();
        replace.forEach(function (str, i) {
            expression = expression.replace("[" + i + "]", str);
        });
        return expression;
    };
    Functions.prototype.getCellValue = function (cell, raw) {
        if (raw === void 0) { raw = false; }
        var value;
        if (raw) {
            value = cell.value;
        }
        else {
            value = cell.formatted_value || cell.value;
        }
        return this.helpers.isNumber(value) ? parseFloat("" + value) : value;
    };
    return Functions;
}(Emitter_1.default));
exports.Functions = Functions;
//# sourceMappingURL=Functions.js.map