var jsep = require("../vendors/jsep.js");

export function ExpParser() {
    var self = this;
    self.phrase = "";
    self.parts = [];
    self.addCol = function (phrase, col) {
        phrase = phrase.replace("=", "");
        self.phrase = _h.replaceAll(phrase, " ", "");
        var temp = self.phrase.replace(/[\])}[{(=]/g, '');
        temp = _h.replaceAll(temp, ' ', '');
        var splits = _h.splitMulti(temp, ['+', '-', '*', '/']);
        splits = _h.cleanArray(splits);
        var repArray = [];
        for (var b = 0; b < splits.length; b++) {
            var number = splits[b].replace(/^\D+/g, '');
            var letter = splits[b].replace(number, '');
            if (letter) {
                var t = Number(_h.alphabetToNumber(letter));
                if (t >= col) {
                    repArray.push({ old: splits[b], new: _h.numberToAlphabet(t + 1) + Number(number) });

                }
            }
        }
        self.phrase = self.replaceParts(self.phrase, repArray);
        return "=" + self.phrase;
    };
    self.addNodeCol = function (phrase, col) {
        self.phrase = _h.replaceAll(phrase, " ", "");
        var splits = _h.multiSplit(self.phrase, ['+', '-', '/', '*']);
        var repArray = [];
        if (_h.any(splits))
            for (var i = 0; i < splits.length; i++) {
                if (!splits[i].startsWith("{")) {
                    var number = splits[i].replace(/^\D+/g, '');
                    var letter = splits[i].replace(number, '');
                    var t = Number(_h.alphabetToNumber(letter));
                    if (t >= col) {
                        repArray.push({ old: splits[i], new: _h.numberToAlphabet(t + 1) + Number(number) });
                    }
                }
            }
        self.phrase = self.replaceParts(self.phrase, repArray);
        return self.phrase;
    }
    self.removeCol = function (phrase, col) {
        phrase = phrase.replace("=", "");
        self.phrase = _h.replaceAll(phrase, " ", "");
        var parse = jsep(self.phrase);
        var res = self.removeColToString(parse, _h.numberToAlphabet(col));
        var temp = res.replace(/[\])}[{(=]/g, '');
        temp = _h.replaceAll(temp, ' ', '');
        var splits = _h.splitMulti(temp, ['+', '-', '*', '/']);
        splits = _h.cleanArray(splits);
        for (var b = 0; b < splits.length; b++) {
            var number = splits[b].replace(/^\D+/g, '');
            var letter = splits[b].replace(number, '');
            var t = Number(_h.alphabetToNumber(letter));
            if (letter) {
                if (t > col) {
                    res = _h.replaceAll(res,
                        splits[b],
                        _h.numberToAlphabet(t - 1) + number);
                }
            }
        }
        return "=" + res;
    };
    self.removeNodeCol = function (phrase, col) {
        self.phrase = _h.replaceAll(phrase, " ", "");
        var splits = _h.multiSplit(self.phrase, ['+', '-', '/', '*']);
        if (_h.any(splits))
            for (var i = 0; i < splits.length; i++) {
                if (!splits[i].startsWith("{")) {
                    var number = splits[i].replace(/^\D+/g, '');
                    var letter = splits[i].replace(number, '');
                    var t = Number(_h.alphabetToNumber(letter));
                    if (t > col) {
                        self.phrase = _h.replaceAll(self.phrase,
                            splits[i],
                            _h.numberToAlphabet(t - 1) + number);
                    }
                    if (t === col) {
                        if (splits.length === i + 1) {
                            self.phrase = _h.replaceAll(self.phrase,
                                splits[i], "");
                            self.phrase = self.phrase.substring(0, self.phrase.length - 1);
                        } else {
                            var part1 = self.phrase.substring(0, self.phrase.indexOf(splits[i]) - 1);
                            var part2 = self.phrase.substring(self.phrase.indexOf(splits[i]) + splits[i].length);
                            self.phrase = part1 + part2;
                        }
                    }
                }
            }
        return self.phrase;

    }
    self.removeColToString = function (obj, col) {
        var left, right;
        if (obj.type === "BinaryExpression") {
            if (obj.left.type === "Identifier") {
                left = obj.left.name;
            }
            if (obj.right.type === "Identifier") {
                right = obj.right.name;
            }
            if (obj.left.type === "Literal") {
                left = obj.left.value;
            }
            if (obj.right.type === "Literal") {
                right = obj.right.value;
            }
            if (obj.left.type === "BinaryExpression") {
                left = self.removeColToString(obj.left, col);
            }
            if (obj.right.type === "BinaryExpression") {
                right = self.removeColToString(obj.right, col);
            }
            if (obj.right.type === "UnaryExpression") {
                right = obj.right.operator + obj.right.argument.value;
            }
            if (obj.type === "Identifier") {
                return obj.name;
            }
            var numberLeft, letterLeft, numberRight, letterRight;
            try {
                numberLeft = left.replace(/^\D+/g, '');
                letterLeft = left.replace(numberLeft, '');
            } catch (e) {
                //
            }
            try {
                numberRight = right.replace(/^\D+/g, '');
                letterRight = right.replace(numberRight, '');
            } catch (e) {
                //
            }
            if (letterLeft && letterRight && (letterLeft === col || letterRight === col)) {
                if (letterLeft === col && letterRight === col) {
                    return "";
                }
                if (letterRight === col) {
                    return left;
                }
                if (letterLeft === col) {
                    return right;
                }
            } else {
                var exp = left + obj.operator + right;
                if (self.phrase.indexOf("(" + exp + ")") !== -1) {
                    return "(" + exp + ")";
                } else {
                    return exp;
                }
            }

        }
    };
    self.addRow = function (phrase, rowNumber) {
        phrase = phrase.replace("=", "");
        self.phrase = _h.replaceAll(phrase, " ", "");
        var res = self.phrase;
        var temp = self.phrase.replace(/[\])}[{(=]/g, '');
        temp = _h.replaceAll(temp, ' ', '');
        var splits = _h.splitMulti(temp, ['+', '-', '*', '/']);
        splits = _h.cleanArray(splits);
        var repArray = [];
        for (var j = 0; j < splits.length; j++) {
            var number = splits[j].replace(/^\D+/g, '');
            var letter = splits[j].replace(number, '');
            if (letter) {
                if (Number(number) >= rowNumber)
                    repArray.push({ old: splits[j], new: letter + (Number(number) + 1) });
            } else {
                repArray.push({ old: splits[j], new: Number(number) });
            }
        }
        res = self.replaceParts(res, repArray);
        return "=" + res;
    };
    self.addNodeRow = function (phrase, rowNumber) {
        self.phrase = _h.replaceAll(phrase, " ", "");
        var splits = _h.multiSplit(self.phrase, ['+', '-', '/', '*']);
        var repArray = [];
        if (_h.any(splits))
            for (var i = 0; i < splits.length; i++) {
                if (!splits[i].startsWith("{")) {
                    var number = splits[i].replace(/^\D+/g, '');
                    var letter = splits[i].replace(number, '');
                    if (Number(number) >= rowNumber) {
                        repArray.push({ old: splits[i], new: letter + (Number(number) + 1) });
                    }
                }
            }
        self.phrase = self.replaceParts(self.phrase, repArray);
        return self.phrase;
    };
    self.replaceParts = function (phrase, array) {
        if (array.length === 0 || _h.isNullOrEmpty(phrase) || phrase === "")
            return phrase;
        array.sort((a, b) =>
            a.new < b.new ? 1 : -1);
        for (var i = 0; i < array.length; i++) {
            phrase = _h.replaceAll(phrase,
                array[i].old,
                array[i].new);
        }
        return phrase;
    };
    self.removeRow = function (phrase, rowNumber) {
        phrase = phrase.replace("=", "");
        self.phrase = _h.replaceAll(phrase, " ", "");
        var parse = jsep(self.phrase);
        var res = self.removeRowToString(parse, rowNumber);
        var temp = res.replace(/[\])}[{(=]/g, '');
        temp = _h.replaceAll(temp, ' ', '');
        var splits = _h.splitMulti(temp, ['+', '-', '*', '/']);
        splits = _h.cleanArray(splits);
        for (var j = 0; j < splits.length; j++) {
            var number = splits[j].replace(/^\D+/g, '');
            var letter = splits[j].replace(number, '');
            if (letter) {
                if (Number(number) > rowNumber) {
                    res = _h.replaceAll(res,
                        splits[j],
                        letter + (number - 1));
                }
            }
        }
        return "=" + res;
    };
    self.removeNodeRow = function (phrase, rowNumber) {
        self.phrase = _h.replaceAll(phrase, " ", "");
        var splits = _h.multiSplit(self.phrase, ['+', '-', '/', '*']);
        if (_h.any(splits))
            for (var i = 0; i < splits.length; i++) {
                if (!splits[i].startsWith("{")) {
                    var number = splits[i].replace(/^\D+/g, '');
                    var letter = splits[i].replace(number, '');
                    if (Number(number) > rowNumber) {
                        self.phrase = _h.replaceAll(self.phrase,
                            splits[i],
                            letter + (number - 1));
                    }
                    if (Number(number) === rowNumber) {
                        if (splits.length === i + 1) {
                            self.phrase = _h.replaceAll(self.phrase,
                                splits[i], "");
                            self.phrase = self.phrase.substring(0, self.phrase.length - 1);
                        } else {
                            var part1 = self.phrase.substring(0, self.phrase.indexOf(splits[i]) - 1);
                            var part2 = self.phrase.substring(self.phrase.indexOf(splits[i]) + splits[i].length);
                            self.phrase = part1 + part2;
                        }
                    }
                }
            }
        return self.phrase;
    }
    self.removeRowToString = function (obj, rowNumber) {
        var left, right, res;
        if (obj.type === "BinaryExpression") {
            if (obj.left.type === "Identifier") {
                left = obj.left.name;
            }
            if (obj.right.type === "Identifier") {
                right = obj.right.name;
            }
            if (obj.left.type === "Literal") {
                left = obj.left.value;
            }
            if (obj.right.type === "Literal") {
                right = obj.right.value;
            }
            if (obj.left.type === "BinaryExpression") {
                left = self.removeRowToString(obj.left, rowNumber);
            }
            if (obj.right.type === "BinaryExpression") {
                right = self.removeRowToString(obj.right, rowNumber);
            }
            if (obj.right.type === "UnaryExpression") {
                right = obj.right.operator + obj.right.argument.value;
            }
            if (obj.type === "Identifier") {
                return obj.name;
            }
            var numberLeft, letterLeft, numberRight, letterRight;
            try {
                numberLeft = left.replace(/^\D+/g, '');
                letterLeft = left.replace(numberLeft, '');
            } catch (e) {
                //
            }
            try {
                numberRight = right.replace(/^\D+/g, '');
                letterRight = right.replace(numberRight, '');
            } catch (e) {
                //
            }
            if (letterLeft && letterRight && (Number(numberLeft) === rowNumber || Number(numberRight) === rowNumber)) {
                if (Number(numberLeft) === rowNumber && Number(numberRight) === rowNumber) {
                    return "";
                }
                if (Number(numberLeft) === rowNumber) {
                    return right;
                }
                if (Number(numberRight) === rowNumber) {
                    return left;
                }
            } else {
                var exp = left + obj.operator + right;
                if (self.phrase.indexOf("(" + exp + ")") !== -1) {
                    return "(" + exp + ")";
                } else {
                    return exp;
                }
            }

        }
    };
    self.expToString = function (obj) {
        var left, right, res;
        if (obj.type === "BinaryExpression") {
            if (obj.left.type === "Identifier") {
                left = obj.left.name;
            }
            if (obj.right.type === "Identifier") {
                right = obj.right.name;
            }
            if (obj.left.type === "Literal") {
                left = obj.left.value;
            }
            if (obj.right.type === "Literal") {
                right = obj.right.value;
            }
            if (obj.left.type === "BinaryExpression") {
                left = self.expToString(obj.left);
            }
            if (obj.right.type === "BinaryExpression") {
                right = self.expToString(obj.right);
            }

            var exp = left + obj.operator + right;
            if (self.phrase.indexOf("(" + exp + ")") !== -1) {
                return "(" + exp + ")";
            } else {
                return exp;
            }
        }
        if (obj.type === "Identifier") {
            return obj.name;
        }
    };
    self.afterColCopy = function (phrase, maxCol, maxRow, cellRow, lastNumber) {
        self.phrase = phrase.replace(/[\])}[{(=]/g, '');
        self.phrase = _h.replaceAll(self.phrase, ' ', '');
        var parse = jsep(self.phrase);
        self.phrase = self.changeParts(parse, cellRow, lastNumber);
        var splits = _h.splitMulti(self.phrase, ['+', '-', '*', '/']);
        splits = _h.cleanArray(splits);
        var inValidItems = [], validItems = [];
        if (_h.any(splits))
            for (var i = 0; i < splits.length; i++) {
                if (/^\d+$/.test(splits[i])) {
                    validItems.push(splits[i]);
                } else {
                    var number = splits[i].replace(/^\D+/g, '');
                    var letter = splits[i].replace(number, '');
                    var letterNumber = _h.alphabetToNumber(letter);
                    if (letterNumber > maxCol || Number(number) > maxRow)
                        inValidItems.push(splits[i]);
                    else
                        validItems.push(splits[i]);
                }
            }
        if (validItems.length >= 2) {
            if (inValidItems.length > 0) {
                parse = jsep(self.phrase);
                var res = self.removeInValidPart(parse, inValidItems);
                return "=" + res;
            }
            else {
                return "=" + self.phrase;
            }
        }
        else {
            return "";
        }
    };
    self.minMaxControl = function (phrase, maxCol, maxRow) {
        self.phrase = phrase.replace(/[\])}[{(=]/g, '');
        self.phrase = _h.replaceAll(self.phrase, ' ', '');
        var splits = _h.splitMulti(self.phrase, ['+', '-', '*', '/']);
        splits = _h.cleanArray(splits);
        var inValidItems = [], validItems = [];
        if (_h.any(splits))
            for (var i = 0; i < splits.length; i++) {
                if (/^\d+$/.test(splits[i])) {
                    validItems.push(splits[i]);
                } else {
                    var number = splits[i].replace(/^\D+/g, '');
                    var letter = splits[i].replace(number, '');
                    var letterNumber = _h.alphabetToNumber(letter);
                    if (letterNumber > maxCol || Number(number) > maxRow)
                        inValidItems.push(splits[i]);
                    else
                        validItems.push(splits[i]);
                }
            }
        if (validItems.length >= 2) {
            if (inValidItems.length > 0) {
                var parse = jsep(phrase);
                var res = self.removeInValidPart(parse, inValidItems);
                return "=" + res;
            } else {
                return phrase;
            }
        } else {
            return "";
        }
    };
    self.removeInValidPart = function (obj, parts) {
        var left, right, res;
        if (obj.type === "BinaryExpression") {
            if (obj.left.type === "Identifier") {
                left = obj.left.name;
            }
            if (obj.right.type === "Identifier") {
                right = obj.right.name;
            }
            if (obj.left.type === "Literal") {
                left = obj.left.value;
            }
            if (obj.right.type === "Literal") {
                right = obj.right.value;
            }
            if (obj.left.type === "BinaryExpression") {
                left = self.removeInValidPart(obj.left, parts);
            }
            if (obj.right.type === "BinaryExpression") {
                right = self.removeInValidPart(obj.right, parts);
            }
            if (obj.right.type === "UnaryExpression") {
                right = obj.right.operator + obj.right.argument.value;
            }
            if (obj.type === "Identifier") {
                return obj.name;
            }
            if (parts.indexOf(left) === -1 && parts.indexOf(right) === -1) {
                var exp = left + obj.operator + right;
                if (self.phrase.indexOf("(" + exp + ")") !== -1) {
                    return "(" + exp + ")";
                } else {
                    return exp;
                }
            }
            if (parts.indexOf(left) === -1 && parts.indexOf(right) !== -1) {
                return left;
            }
            if (parts.indexOf(right) === -1 && parts.indexOf(left) !== -1) {
                return right;
            }
            if (parts.indexOf(right) !== -1 && parts.indexOf(left) !== -1) {
                return "";
            }
        }
    };
    self.changeParts = function (obj, cellRow, lastNumber) {
        var left, right;
        if (obj.type === "BinaryExpression") {
            if (obj.left.type === "Identifier") {
                left = obj.left.name;
            }
            if (obj.right.type === "Identifier") {
                right = obj.right.name;
            }
            if (obj.left.type === "Literal") {
                left = obj.left.value;
            }
            if (obj.right.type === "Literal") {
                right = obj.right.value;
            }
            if (obj.left.type === "BinaryExpression") {
                left = self.changeParts(obj.left, cellRow, lastNumber);
            }
            if (obj.right.type === "BinaryExpression") {
                right = self.changeParts(obj.right, cellRow, lastNumber);
            }
            if (obj.right.type === "UnaryExpression") {
                right = obj.right.operator + obj.right.argument.value;
            }
            if (obj.type === "Identifier") {
                return obj.name;
            }
            var newLeft, newRight, number, letter;
            var exp = left + obj.operator + right;
            if (/^\d+$/.test(left) || self.anyOprator(left)) {
                newLeft = left;
            }
            if (/^\d+$/.test(right) || self.anyOprator(right)) {
                newRight = right;
            }
            if (/^\d+$/.test(left) === false && self.anyOprator(left) === false) {
                number = left.replace(/^\D+/g, '');
                letter = left.replace(number, "");
                newLeft = letter + ((cellRow - lastNumber) + Number(number));
            }

            if (/^\d+$/.test(right) === false && self.anyOprator(right) === false) {
                number = right.replace(/^\D+/g, '');
                letter = right.replace(number, "");
                newRight = letter + ((cellRow - lastNumber) + Number(number));
            }
            var newExp = newLeft + obj.operator + newRight;
            if (self.phrase.indexOf("(" + exp + ")") !== -1) {

                return "(" + newExp + ")";
            } else {
                return newExp;
            }
        }
    };
    self.anyOprator = function (phrase) {
        if (phrase.indexOf("+") !== -1 ||
            phrase.indexOf("-") !== -1 ||
            phrase.indexOf("*") !== -1 ||
            phrase.indexOf("/") !== -1) {
            return true;
        }
        return false;
    };
}