
import { CompanySelectItem, TreeFormulaMakerSelectItem, TipItem } from '../pages/master/model';
import { ApiService } from "../util/apiService.js";

ko.components.register('ko-formulamaker', {
    viewModel: function (params) {
        var self = this;
        self.parentForm = params.parent;
        self.name = params.name;
        self.loc = params.loc;
        self.branchSelectable = params.branchSelectable || true;
        var context = _h.kocnx();
        self.isGroup = context.currentCompany().ct === 0;
        self.loginCompanyId = context.loginCompanyId();
        self.inputId = "formula-" + _h.createRandomNumber();
        self.element = null;
        self.controllerName = params.controllerName;
        self.companies = ko.observableArray();
        self.trees = ko.observableArray();
        self.columns = ko.observableArray();
        self.nodes = [];
        self.consolidateCompany = ko.observable();
        self.tips = ko.observableArray();
        self.input = ko.observable();
        self.closeMenu = function () {
            self.showMenu(false);
        }
        self.input.subscribe(function (newValue, oldValue) {
            if (_h.isNullOrEmpty(newValue))
                return;
            self.setCaretPosition(self.inputId, newValue.length);
            if (params.value() !== newValue)
                self.parentForm.onChangeFormula(newValue, self.name);
        });
        self.companyId = ko.observable();
        self.companyId.subscribe(function (newValue, oldValue) {
            if (_h.isNullOrEmpty(newValue))
                return;

            if (newValue === self.loginCompanyId) {
                for (var j = 0; j < self.trees().length; j++) {
                    self.trees()[j].disabled(false);
                }
            } else {
                for (var i = 0; i < self.trees().length; i++) {
                    var target = self.trees()[i];
                    if (_h.contains([0, 2, 3], target.treeType))
                        target.disabled(false);
                    else
                        target.disabled(true);
                }
            }
            self.treeId(undefined);
            self.getConsolidateCompanies();
            self.toggleTabs();
        });
        self.treeId = ko.observable();
        self.showFormulaValueType = ko.observable(false);
        self.treeId.subscribe(function (newValue, oldValue) {
            if (_h.isNullOrEmpty(newValue))
                return;
            self.formulaValueType("F");
            self.showFormulaValueType(false);
            if (self.trees() && self.trees().length)
                for (var i = 0; i < self.trees().length; i++) {
                    var target = self.trees()[i];
                    if (target.value === newValue && target.treeType ===
                        0 && _h.kocnx().loginCompanyType() === 0) {
                        self.showFormulaValueType(true);
                        break;
                    }
                }
            self.toggleTabs();
            setTimeout(function () {
                $('a[href="#nodes-t"]').trigger('click');

            }, 200);
            self.getNodes();
        });
        self.companySearch = ko.observable();
        self.treeSearch = ko.observable();
        self.columnSearch = ko.observable();
        self.companySearch.subscribe(function (newValue) {
            if (self.companies().length)
                for (var i = 0; i < self.companies().length; i++) {
                    if (_h.isEmpty(newValue) || (self.companies()[i].text() &&
                        self.companies()[i].text().indexOf(newValue) !== -1))
                        self.companies()[i].hide(false);
                    else
                        self.companies()[i].hide(true);
                }
            self.companyId(undefined);
            self.treeId(undefined);
        });
        self.treeSearch.subscribe(function (newValue) {
            if (self.trees().length)
                for (var i = 0; i < self.trees().length; i++) {
                    if (_h.isEmpty(newValue))
                        self.trees()[i].hide(false);
                    else if (self.trees()[i].text.indexOf(newValue) !== -1 ||
                        self.trees()[i].type.indexOf(newValue) !== -1 ||
                        self.trees()[i].valueTypeText.indexOf(newValue) !== -1)
                        self.trees()[i].hide(false);
                    else
                        self.trees()[i].hide(true);
                }
        });
        self.columnSearch.subscribe(function (newValue) {
            if (self.columns().length)
                for (var i = 0; i < self.columns().length; i++) {
                    if (_h.isEmpty(newValue))
                        self.trees()[i].hide(false);
                    if (self.columns()[i].text().indexOf(newValue) !== -1)
                        self.columns()[i].hide(false);
                    else
                        self.companies()[i].hide(true);
                }
        });
        self.nodeSearchKey = ko.observable();
        self.onEnterNodeSearchKey = function (d, e) {
            if (e.keyCode === 13) {
                self.getNodes(self.nodeSearchKey());
            }
            return true;
        };
        self.showMenu = ko.observable(false);
        self.showColumn = false;
        self.showPercentage = true;
        self.lastPhrase = ko.observable();
        self.lastOperator = ko.observable();
        self.formulaValueType = ko.observable("F");
        self.operators = {
            undefined: { name: "", type: -3, after: [-1, 0, 4, 6], enabled: ko.observable(false) },
            "": { name: "", type: -3, after: [-1, 0, 4, 6], enabled: ko.observable(false) },
            "000": { type: -2, after: [-2, -1, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "0": { type: -1, after: [-2, -1, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "1": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "2": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "3": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "4": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "5": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "6": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "7": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "8": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            "9": { type: 0, after: [-3, -1, -2, 0, 1, 2, 3, 5], enabled: ko.observable(false) },
            ".": { type: 1, after: [-1, 0], enabled: ko.observable(false) },
            "+": { type: 2, after: [-1, 0, 4, 6], enabled: ko.observable(false) },
            "-": { type: 2, after: [-1, 0, 4, 6], enabled: ko.observable(false) },
            "*": { type: 2, after: [-1, 0, 4, 6], enabled: ko.observable(false) },
            "/": { type: 2, after: [-1, 0, 4, 6], enabled: ko.observable(false) },
            "%": { type: 3, after: [2], enabled: ko.observable(false) },
            "(": { type: 4, after: [-1, 0, 4, 6], enabled: ko.observable(false) },
            ")": { type: 5, after: [2], enabled: ko.observable(false) }, // if has open p
            "[": { type: 6, after: [], enabled: ko.observable(false) },
            "]": { type: 7, after: [2, 5], enabled: ko.observable(false) }, // if has open bracket
            "C": { type: 10, after: [], enabled: ko.observable(false) },
            "CE": { type: 11, after: [], enabled: ko.observable(false) }
        };
        self.tabs = {
            Info: ko.observable(true),
            Oprators: ko.observable(true),
            Nodes: ko.observable(false),
            Consolidates: ko.observable(false),
            Companies: ko.observable(false),
            Trees: ko.observable(false),
            Columns: ko.observable(false)
        };
        self.inBracket = ko.observable(false);
        self.getLastOperator = function () {
            var lastOperator = self.lastOperator();
            if (!lastOperator)
                lastOperator = "";
            return lastOperator;
        };
        self.toggleTabs = function () {
            var lastOperator = self.operators[self.lastOperator()];
            var inBracket = self.inBracket();
            if (self.isGroup) {
                switch (lastOperator.type) {
                    case 6:
                        if (self.companyId() === self.loginCompanyId)
                            self.tabs.Consolidates(false);
                        else {
                            self.tabs.Consolidates(inBracket);
                        }
                        if (self.loc) {
                            self.tabs.Companies(inBracket);
                            self.tabs.Trees(inBracket);
                            self.tabs.Nodes(inBracket && self.treeId() > 0);
                            self.tabs.Columns(inBracket && self.showColumn);
                        } else {
                            self.tabs.Companies(inBracket);
                            self.tabs.Trees(inBracket && self.companyId() > 0);
                            self.tabs.Nodes(inBracket && self.companyId() > 0 && self.treeId() > 0);
                            self.tabs.Columns(inBracket && self.showColumn);
                        }                      
                        break;
                    case 7:
                        self.tabs.Nodes(inBracket);
                        self.tabs.Companies(inBracket);
                        self.tabs.Trees(inBracket);
                        self.tabs.Consolidates(inBracket);
                        self.tabs.Columns(inBracket && self.showColumn);
                        break;
                    case -3:
                        self.tabs.Nodes(inBracket);
                        self.tabs.Companies(inBracket);
                        self.tabs.Trees(inBracket);
                        self.tabs.Consolidates(inBracket);
                        self.tabs.Columns(inBracket && self.showColumn);
                        break;
                }

                if (!self.tabs.Nodes())
                    $('a[href="#oprators-t"]').trigger('click');
                if (!self.tabs.Consolidates())
                    $('a[href="#oprators-t"]').trigger('click');

                if (!self.tabs.Trees())
                    $('a[href="#info-t"]').trigger('click');
                if (!self.tabs.Companies())
                    $('a[href="#info-t"]').trigger('click');
            } else {
                self.tabs.Nodes(inBracket);
                self.tabs.Trees(inBracket);
                self.tabs.Columns(inBracket && self.showColumn);
                if (!self.tabs.Nodes())
                    $('a[href="#oprators-t"]').trigger('click');
                if (!self.tabs.Trees())
                    $('a[href="#info-t"]').trigger('click');
            }
        };
        self.toggleOperators = function () {
            var lastOperator = self.getLastOperator();
            var last = self.operators[lastOperator];
            for (var operatorName in self.operators) {
                if (self.operators.hasOwnProperty(operatorName)) {
                    var operator = self.operators[operatorName];
                    if (operator.type === 5)
                        operator.enabled(self.ifHasOpenParentheses() && last.type !== 4);
                    else if (operator.type === 10 || operator.type === 11)
                        operator.enabled(true);
                    else if (last.after.length === 0)
                        operator.enabled(false);
                    else if (last.after.indexOf(operator.type) === -1)
                        operator.enabled(false);
                    else
                        operator.enabled(true);
                }
            }
        };
        self.eraseText = function (type) {
            switch (type) {
                case 10:
                    self.input("");
                    self.lastOperator(undefined);
                    break;
                case 11:
                    var text = self.input();
                    if (text && text.length === 1) {
                        self.input("");
                        self.lastOperator(undefined);
                    } else if (text && text.length > 1) {
                        var sub = text.substring(text.length - 1);
                        var operator = self.operators[sub];
                        if (_h.isNullOrEmpty(operator))
                            return;
                        if (operator.type === 7) {
                            var index = 0;
                            var length = self.input().length;
                            var array = self.input().split('').reverse();
                            for (var i = 0; i < array.length; i++) {
                                var current = array[length - i];
                                if (current === "[")
                                    index = length - i;
                            }
                            var res = self.input().substring(0, length - index);
                            self.input(res);
                            self.lastOperator("[");
                        } else {
                            var rest = text.substring(0, text.length - 1);
                            self.input(rest);
                            sub = self.input().substring(self.input().length - 1);

                            self.lastOperator(sub);
                        }
                    }
                    break;
            }
            self.ifInBracket();
            self.toggleOperators();
            self.toggleTabs();
        };
        self.onTreeItemsClick = function (item) {
            if (self.treeId() === item.value) {
                self.treeId(undefined);
            } else {
                self.treeId(item.value);
            }
        };
        self.onCompanyItemsClick = function (item) {
            if (self.companyId() === item.value()) {
                self.companyId(undefined);
            } else {
                self.companyId(item.value());
            }
        };
        self.onColumnItemsClick = function (item) {
            if (_h.isNullOrEmpty(item))
                return;
            var p = "";
            if (self.input() !== null && self.input() !== undefined)
                p = self.input();
            self.input(p + "col:" + item.value() + "]");
            self.lastOperator("]");
            self.inBracket(false);
            self.toggleOperators();
            self.toggleTabs();
        };
        self.setCaretPosition = function (elemId, caretPos) {
            var elem = document.getElementById(elemId);
            if (elem !== null) {
                if (elem.createTextRange) {
                    var range = elem.createTextRange();
                    range.move('character', caretPos);
                    range.select();
                } else {
                    if (elem.selectionStart) {
                        elem.focus();
                        elem.setSelectionRange(caretPos, caretPos);
                    } else
                        elem.focus();
                }
            }
        };
        self.getCaretPosition = function () {
            var el = document.getElementById(self.inputId);
            var iCaretPos = el.selectionStart;
            return iCaretPos;
        };
        self.onClick = function (model, e) {
            var visList = $(".drp-menu:visible");
            if (visList && visList.length > 0) {
                for (var i = 0; i < visList.length; i++) {
                    var target = ko.contextFor(visList[i]);
                    if (target && target.$data && target.$data["showMenu"])
                        target.$data.showMenu(false);
                }
            }
            self.showMenu(true);
            if (self.input()) {
                self.setCaretPosition(self.inputId, self.input().length);
                var char = self.input().charAt(self.input().length - 1);
                if (char !== self.lastOperator()) {
                    self.lastOperator(char);
                }
            } else {
                self.setCaretPosition(self.inputId, 0);
                self.lastOperator(undefined);
            }
            self.ifInBracket();
            self.toggleOperators();
            self.toggleTabs();
            self.calculateOpenListLoc();
        };
        self.onKeydown = function (model, event) {
            if (!self.showMenu())
                return true;
            if (!_h.isEnglishKeyboard(event.key)) {
                var text = _h.getApiMessage("FormulaMakerEnglishOnly");
                _h.failToast(text);
                return false;
            }

            switch (event.keyCode) {
                case 8:
                    self.eraseText(11);
                    break;
                case 46:
                    self.eraseText(10);
                    break;
                default:
                    var key = event.key;
                    var operator = self.operators[key];
                    if (!operator || !operator.enabled())
                        return false;

                    if (self.canWrite(operator)) {
                        self.write(key, operator);
                        self.lastOperator(key);
                        self.ifInBracket();
                        self.toggleOperators();
                        self.toggleTabs();
                    }
                    break;
            }


        };
        self.onKeyClick = function (model, e) {
            var lastOperator = self.operators[self.getLastOperator()];
            var newOperator = self.operators[e.currentTarget.innerText];
            if (!newOperator.enabled())
                return;
            switch (newOperator.type) {
                case 10:
                    self.eraseText(10);
                    break;
                case 11:
                    self.eraseText(11);
                    break;
                default:
                    if (lastOperator.after.indexOf(newOperator.type) !== -1) {
                        var el = document.getElementById(self.inputId);
                        el.focus();
                        self.lastOperator(e.currentTarget.innerText);
                        self.write(e.currentTarget.innerText, newOperator);
                    }
                    break;
            }
            self.ifInBracket();
            self.toggleTabs();
            self.toggleOperators();
        };
        self.ifInBracket = function () {
            if (!self.input()) {
                self.inBracket(false);
                return;
            }
            var array = self.input().split('').reverse();
            for (var i = 0; i < array.length; i++) {
                if (array[i] === "[") {
                    self.inBracket(true);
                    break;
                }
                if (array[i] === "]") {
                    self.inBracket(false);
                    break;
                }
            }
        };
        self.ifHasOpenParentheses = function () {
            if (!self.input())
                return false;
            var lPCount = self.input().replace(/[^(]/g, "").length;
            var rPCount = self.input().replace(/[^)]/g, "").length;
            if (lPCount === 0)
                return false;
            if (lPCount === rPCount)
                return false;
            if (lPCount > rPCount)
                return true;
            return false;
        };
        self.write = function (key, operator) {
            var text = self.input();
            var pos = self.getCaretPosition();
            if (!text) {
                self.input(key);
            } else if (text.length === pos) {
                self.input(self.input() + key);
            } else {
                var part1 = self.input().substring(0, pos);
                var part2 = self.input().substring(pos);
                self.input(part1 + key + part2);
            }


        };
        self.canWrite = function (operator) {
            if (!self.lastOperator() ||
                operator.after.indexOf(-3) !== -1)
                return true;
            var last = self.operators[self.lastOperator()];

            if (last.after.indexOf(operator.type) !== -1)
                return true;


            return false;
        };
        self.getTreeSelectList = function () {
            ApiService.request(
                {
                    url: "/api/common/getgeneraltreelist",
                    data: { controllerName: 4 },
                    success: function (data) {
                        self.trees.removeAll();
                        if (!_h.isNullOrEmpty(data)) {
                            for (var j = 0; j < data.length; j++) {
                                var item = new TreeFormulaMakerSelectItem(data[j]);
                                self.trees.push(item);
                            }
                        }
                        self.treeId(undefined);
                    },
                    error: function (data) {
                        var text = _h.getApiMessage("ErrorLoadTree");
                        _h.failToast(text);
                    }
                });
        };
        self.getCompanyList = function () {
            ApiService.request(
                {
                    url: "/api/common/getcompanylist",
                    data: { controllerName: self.controllerName },
                    success: function (data) {
                        self.companies.removeAll();
                        if (_h.any(data))
                            for (var j = 0; j < data.length; j++) {
                                var target = data[j];
                                self.companies.push(new CompanySelectItem(target));
                            }
                        self.companyId(undefined);
                    },
                    error: function (data) {
                        toast.error("Company", 'getSelectList');
                    }
                });
        };
        self.getConsolidateCompanies = function () {
            ApiService.request(
                {
                    url: "getCompanyOwnership",
                    data: { id: self.companyId() },
                    success: function (data) {
                        self.consolidateCompany(data);
                    },
                    error: function (data) {
                        toast.error("Company", 'getSelectList');
                    }
                });
        };
        self.getFormulaTips = function () {
            if (_h.isEmpty(self.input())) {
                if (self.tips().length)
                    self.tips.removeAll();
                return;
            }
            ApiService.request(
                {
                    url: "getFormulaTooltip",
                    data: {
                        controllerName: 4,
                        formula: self.input()
                    },
                    success: function (data) {
                        self.tips.removeAll();
                        if (_h.any(data))
                            for (var i = 0; i < data.length; i++) {
                                self.tips.push(new TipItem(data[i]));
                            }
                        var infoBox = document.getElementById("info-t");
                        if (infoBox) {
                            var row = infoBox.getElementsByClassName("row")[0];
                            var leftSide = document.getElementById("formula_left");
                            var rightSide = document.getElementById("formula_right");
                            rightSide.style.borderLeft = " 1px solid #ccc";
                            row.style.width = "";
                            leftSide.style.opacity = "1";
                            self.showWideInfo(false);
                        }
                    },
                    error: function (data) {

                    }
                });
        };
        self.getNodes = function (term) {
            if (!self.treeId())
                return;
            ApiService.request(
                {
                    url: "getNodeSelection",
                    data: {
                        searchKey: term,
                        id: self.treeId(),
                        controllerName: self.controllerName,
                        branchSelectable: true
                    },
                    success: function (data) {
                        self.nodes = data;
                        self.configNodeSelect();
                    },
                    error: function (data) {
                        var text = _h.getApiMessage("LoadTreeBranchesError");
                        _h.failToast(text);
                    }
                });
        };
        self.init = function (model) {
            if (model.value())
                self.input(model.value());
            self.controllerName = model.controllerName;

            if (self.controllerName === 50) {
                var colList = model.parent.parentForm.formulaColSelectList;
                self.showColumn = true;
                self.showPercentage = false;
                if (colList && colList.length)
                    for (var i = 0; i < colList.length; i++) {
                        self.columns.push(colList[i]);
                    }
            }
            self.getCompanyList();
            self.getTreeSelectList();
            self.getFormulaTips();
            self.element = document.getElementById(self.inputId);
            self.toggleOperators();
            self.toggleTabs();
            if (!_h.isNullOrEmpty(params))
                params.value.subscribe(function (newValue, oldValue) {
                    setTimeout(function () {
                        if (params.value() !== self.input() && params.value.isValid())
                            self.input(newValue);
                    }, 350);
                });
        };
        self.showWideInfo = ko.observable(false);
        self.toggleWidthInfoBox = function () {
            var leftSide = document.getElementById("formula_left");
            var rightSide = document.getElementById("formula_right");
            if (!self.showWideInfo()) {
                $("#formula_left").css({
                    "display": "none"
                });
                rightSide.style.border = "none";
                rightSide.style.width = "max-content";
                self.showWideInfo(true);
            } else {
                $("#formula_left").css({
                    "display": "",
                    "width": "",
                });
                rightSide.style.width = "";
                rightSide.style.borderLeft = " 1px solid #ccc";
                self.showWideInfo(false);
            }
        };
        self.onNodeItemClick = function (itemValue) {
            if (!_h.isNullOrEmpty(itemValue)) {
                if (self.lastOperator() === "]") {
                    self.eraseText(11);
                }
                var p = self.input(), nodePhrase = "";
                if (self.lastOperator() !== "[")
                    return;
                if (self.isGroup && (self.controllerName === 4 || self.controllerName === 32)) {
                    if (_h.isNullOrEmpty(self.formulaValueType()))
                        self.formulaValueType("F");
                    nodePhrase = "node:" + itemValue.code + "-" + self.companyId() + "-" + self.formulaValueType() + "]";
                    self.input(p + nodePhrase);
                    self.lastOperator("]");
                } else {
                    nodePhrase = itemValue.code + "]";
                    self.input(p + "node:" + nodePhrase);
                    self.lastOperator("]");
                }
                self.inBracket(false);
                self.toggleOperators();
                self.toggleTabs();
            }
        };
        self.configNodeSelect = function () {
            var options = {
                tType: "NodeSelect",
                location:"Formula",
                multi: false,
                nodes: self.nodes,
                substituteNode: true,
                rootId: self.treeId(),
                controllerName: self.controllerName,
                onClickItem: self.onNodeItemClick,
                selectedItems: null,
                branchSelectable: self.branchSelectable
            };
            $("#tree_view_fl").treeView(options);
        };
        self.onConsolidateCompanyClick = function (model, e) {
            var value = $(e.target).attr("data-value");
            if (!_h.isNullOrEmpty(value)) {
                if (self.lastOperator() === "]") {
                    self.eraseText(11);
                }
                var p = self.input();
                if (self.lastOperator() !== "[")
                    return;
                self.input(p + "percent:" + value + "]");
                self.lastOperator("]");
                self.inBracket(false);
                self.toggleOperators();
                self.toggleTabs();
            }
        };
        self.init(params);
        self.calculateOpenListLoc = function () {
            var box = $(".cal-box");
            if (box.length > 0) {
                box.css('top', "");
                var ulHeight = box.height();
                var pageHeight = $("body").height();
                var viewportOffset = box.get(0).getBoundingClientRect();
                var rest = pageHeight - viewportOffset.top;
                if (rest < ulHeight) {
                    var ulTop = Number(box.css('top').replace("px", ""));
                    var newTop = ulTop - ulHeight - 8;
                    box.css('top', newTop + "px");
                }
            }
        }
    },
    template: "<!-- ko template: { name: 'formula-maker-t' } --><!-- /ko -->"
}); 