var { BaseModel, BaseFormModel, BaseInfoModel, BaseSecondaryForm } = require('../master/baseModels.js');
import { ApiService } from "../../util/apiService.js";
require('knockout.validation');
import { BaseViewModel } from '../master/baseViewModel.js';
import { PhraseTranslator } from '../master/phraseTranslator.js';
import Big from "../../vendors/big.js";


export class MappingData extends BaseModel {
    notShow = ko.observable(false);

    constructor(model) {
        super(model);
        this.isDeleted = ko.observable();
        this.dragMode = ko.observable(false);
        this.selected = ko.observable(false);
        this.shiftSelected = ko.observable(false);
        this.pageSelect = ko.observable();
        this.order = ko.observable();
        this.selected.subscribe(function (newValue) {
            if (newValue !== undefined && newValue !== null) {
                const context = _h.kocnx();
                const isExistInList = context.mvm().childModel().hasExistRecordInSelectItem(this.id());
                if (newValue) {
                    if (!this.isMapped()) {
                        if (!isExistInList) {
                            context.mvm().childModel().allSelectedRecords.push({ id: this.id(), debtor: this.debtor(), creditor: this.creditor() });
                            context.mvm().childModel().calculateTotalPrice();
                        }
                    }
                } else {
                    if (!this.isMapped()) {
                        if (isExistInList) {
                            var rest = context.mvm().childModel().allSelectedRecords().filter(a => a.id !== this.id());
                            context.mvm().childModel().allSelectedRecords(rest);
                            context.mvm().childModel().calculateTotalPrice();
                        }
                    }
                }
                setTimeout(function () {
                    this.configDragFunctionality(context.mvm().childModel().allSelectedRecords().length);
                }.bind(this),
                    100);
            }
        }, this);
        this.styleRowValue = ko.pureComputed(function () {
            if (this.isMapped() === true && this.notShow() === false)
                return 'color:  #62cb31;-webkit-user-select: none;user-select: none;';
            return "-webkit-user-select: none;user-select: none;";
        }, this);
    }

    configDragFunctionality() {
        const list = $(".table-row-selected");
        const dlist = $("tr:not(.table-row-selected)");
        let el;
        if (_h.any(list))
            for (let i = 0; i < list.length; i++) {
                el = list[i];
                el.setAttribute("draggable", true);
                el.addEventListener('dragstart',
                    function (event) {
                        const length = _h.kocnx()
                            .mvm().childModel().allSelectedRecords().length;
                        const div = document.getElementById('drag-label');
                        div.style.display = "block";
                        const span = div.getElementsByTagName("span")[0];
                        span.innerText = length;
                        event.dataTransfer.setDragImage(div, 60, 0);
                    });
            }

        if (_h.any(dlist))
            for (let j = 0; j < dlist.length; j++) {
                const elem = dlist[j];
                elem.setAttribute("draggable", false);
            }
    }
}

export function MappingDataViewModel() {
    const self = this;
    self.allSelectedRecords = ko.observableArray();
    self.totalPrice = ko.observable(0);
    self.totalPriceSign = ko.observable("");
    self.caption = ko.observable();
    self.refreshSign = ko.observable(false);
    self.toggleShowMapped = function () {
        self.showMapped(!self.showMapped());
        self.getRecords();
    };
    self.hasExistRecordInSelectItem = function (id) {
        return self.allSelectedRecords().filter(a => a.id === id).length > 0;
    };
    self.clearAllSelectedRecords = function () {
        if (self.selectedRowRecord() !== null && self.selectedRowRecord() !== undefined)
            self.selectedRowRecord(null);
        self.selectedRowRecords.removeAll();
        for (let i = 0; i < self.records().length; i++) {
            self.records()[i].selected(false);
        }
        self.allSelectedRecords.removeAll();
        self.totalPrice(0);
    };
    self.init = function () {
        self.fillTableProperties();
        self.getRecords();
        self.iconSize("icon-image-small");
    };
    ko.utils.extend(self, new BaseViewModel({
        entityName: "MappingData",
        getList: false,
        apiService: {
            actionList: ["filterby", "getdatacollection"]
        },
        buttons: [
            { name: 'showMappedSw', access: false, cMenu: false, templateName: "showMapped-button-template" },
            { name: 'help', access: false, cMenu: false },
            { name: 'refresh', access: false, cMenu: false },
            { name: 'tools', access: false, cMenu: false }
        ],
        filters: [
            { name: 'showMapped', def: false },
            { name: 'treeId' },
            { name: 'sheetId' }
        ],
        tableStyle: "font-size: 11px;table-layout: fixed;",
        styleRow: "styleRowValue",
        sortDirection: "Ascending",
        sortProperty: "code",
        context: self,
        searchKeyType: "enter",
        cols: mappingDataModelRes,
        selectRow: true,
        saveState: true,
        contextMenu: false,
        isMultiSelectRows: true,
        resizable: true,
        filterbyColumn: true
    }));
    self.btnVisibility = ko.computed(function () {
        self.vishelp(true);
        self.visrefresh(true);
        self.vistools(true);
    });
    self.getRecords = function () {
        if (!self.validationObject.isValid()) {
            self.validationObject.errors.showAllMessages();
            return false;
        }
        const model = self.createFilterByModel();
        self.apiService.request({
            name: "filterby",
            data: model,
            success: function (data) {
                self.records.removeAll();
                if (!_h.isNullOrEmpty(self.selectedRowRecord()))
                    self.selectedRowRecord(null);
                self.selectedRowRecords.removeAll();
                self.extraBufferKey(null);
                if (!_h.isNullOrEmpty(data)) {
                    self.total(data.total);
                    if (_h.any(data.list))
                        for (let j = 0; j < data.list.length; j++) {
                            const target = data.list[j];
                            const record = new MappingData(target);
                            var isSelected = self.allSelectedRecords().filter(a => a.id.indexOf(target.id) !== -1).length > 0;
                            record.selected(isSelected);
                            self.records.push(record);
                        }
                }
                if (self.configTable.resizable)
                    _h.initResizeTable();
            },
            error: function () {
                toast.error(self.entityName, 'getList');
            }
        });
    };
    self.selectAll = ko.observable(false);
    self.debtorOnly = ko.observable(false);
    self.creditorOnly = ko.observable(false);
    self.pageFrom = ko.observable();
    self.pageTo = ko.observable();
    self.pageNumberList = ko.observableArray();
    self.pageList = ko.observableArray();
    self.refreshPageList = ko.computed(function () {
        self.pageNumberList.removeAll();
        if ((self.total() / self.pageSize()) < 1) {
            self.pageNumberList.push({ text: "1", value: 1 });
        } else {
            const count = self.total() / self.pageSize();
            for (let i = 0; i < count; i++) {
                self.pageNumberList.push({ text: "" + (i + 1), value: i + 1 });
            }
        }
        self.pageList.removeAll();
    });
    self.selectBy = function () {
        const model = self.createFilterByModel();
        model.selectAll = self.selectAll();
        model.debtorOnly = self.debtorOnly();
        model.creditorOnly = self.creditorOnly();
        model.pageFrom = self.pageFrom();
        model.pageTo = self.pageTo();
        if (_h.any(self.pageList()))
            model.pageList = self.pageList();

        self.apiService.request({
            name: "getDataCollection",
            data: model,
            success: function (data) {
                self.clearAllSelectedRecords();
                if (!_h.isNullOrEmpty(data) && _h.any(data)) {
                    for (let j = 0; j < data.length; j++) {
                        const item = data[j];
                        var isExist = self.allSelectedRecords().filter(a => a.id === item.id).length > 0;
                        if (!isExist) {
                            self.allSelectedRecords.push({ id: item.id, debtor: item.debtor, creditor: item.creditor });
                        }
                    }
                    for (let k = 0; k < self.records().length; k++) {
                        const target = self.records()[k];
                        var isExist = self.allSelectedRecords().filter(a => a.id === target.id()).length > 0;
                        if (isExist) {
                            target.selected(true);
                        }

                    }
                    setTimeout(function () {
                        self.calculateTotalPrice();
                    }, 50);
                }

            },
            error: function () {
                toast.error(self.entityName, 'getList', "SelectCollection");
            }
        });
    };
    self.clearSelectBoxes = function () {
        self.selectAll(false);
        self.debtorOnly(false);
        self.creditorOnly(false);
        self.pageFrom("");
        self.pageTo("");
        if (!_h.isNullOrEmpty(self.pageList()) && self.pageList().length > 0)
            self.pageList.removeAll();
        self.clearAllSelectedRecords();
    };
    self.validationObject = ko.validatedObservable({
        pageFrom: self.pageFrom.extend({
            pageRangeValidate: [self.pageFrom, self.pageTo, self.pageNumberList]
        }),
        pageTo: self.pageTo.extend({
            pageRangeValidate: [self.pageFrom, self.pageTo, self.pageNumberList]
        })
    });
    self.afterDeleteMappingNodes = function (list) {
        for (let i = 0; i < list.length; i++) {
            const item = new MappingData(list[i]);
            self.records.push(item);
        }
    }
    self.calculateTotalPrice = function () {
        self.totalPrice(0);
        var positive = 0;
        var negative = 0;
        for (var i = 0; i < self.allSelectedRecords().length; i++) {
            var target = self.allSelectedRecords()[i];
            var isNegative = Big(_h.clearNumber(target.creditor)).gt(0);
            var dblVal = Big(_h.clearNumber(target.creditor)).gt(0) && Big(_h.clearNumber(target.debtor)).gt(0);
            if (!dblVal) {
                if (isNegative) {
                    negative = negative + parseFloat(_h.clearNumber(target.creditor));
                } else {
                    positive = positive + parseFloat(_h.clearNumber(target.debtor));
                }
            } else {
                negative = negative + parseFloat(_h.clearNumber(target.creditor));
                positive = positive + parseFloat(_h.clearNumber(target.debtor));
            }
           
        }

        var res = positive - negative;
        self.totalPrice(_h.formatNumber(res, true));
        self.totalPriceSign(res > 0 ? 'بد' : 'بس');
    }
}

export class EffectedMappingForm extends BaseSecondaryForm {
    constructor(viewModel, files, list) {
        super(viewModel, [
            { name: "treeList", type: "obar" },
            { name: "mappingResultErrorList", type: "obar" },
            { name: "showprogressBar", type: "ob", val: false },
            { name: "progressBar", type: "ob", val: 0 },
            { name: "selectTree", type: "ob" },
            { name: "showSaveBtn", type: "ob", val: true },
            { name: "checkAllFiles", type: "ob", val: false },
            { name: "notUnEffectedSelected", type: "ob", val: false },

        ], { text: "اعمال/لغو اثر فایل تراز" });
        this.width = "50%";
        for (let i = 0; i < list.length; i++) {
            const record = new TreeEffectedMappingItem(list[i], files);
            if (i === 0) {
                record.selected(true);
                this.selectTree(record);
            }
            this.treeList.push(record);
        }
        this.visShowSaveBtn = ko.pureComputed(function () {
            return !this.showSaveBtn();
        }.bind(this));


        this.checkAllFiles.subscribe(function (newValue) {
            if (!_h.isNullOrEmpty(newValue)) {
                for (let i = 0; i < this.selectTree().files().length; i++) {
                    var file = this.selectTree().files()[i];
                    file.selected(newValue);
                }
            }
        }.bind(this));
        this.createForm();
    }

    changeTreeTarget(item) {
        this.selectTree(item);
        this.clearSelectedItem();
        item.selected(true);
    };

    clearSelectedItem() {
        for (let i = 0; i < this.treeList().length; i++) {
            var tree = this.treeList()[i];
            tree.selected(false);
        }
    };

    toServer() {
        const model = {
            list: []
        };
        for (let i = 0; i < this.treeList().length; i++) {
            var tree = this.treeList()[i];
            const treeItem = {
                treeId: tree.treeId,
                name: tree.name,
                mappedFiles: [],
                nonMappedFiles: []
            };
            for (let j = 0; j < tree.files().length; j++) {
                var file = tree.files()[j];
                if (file.selected() && !file.before()) {
                    treeItem.mappedFiles.push(file.value());
                }
                if (!file.selected() && file.before()) {
                    treeItem.nonMappedFiles.push(file.value());
                }
            }
            model.list.push(treeItem);
        }
        return model;
    }

    backToForm() {
        this.showSaveBtn(true);
    };

    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'treeeffected-content-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    {
                        name: "custom",
                        resText: 'exeEffectedMappingBtn',
                        vis: true,
                        click: this.parentVM.updateEffectedMapping
                    },
                    {
                        name: "custom",
                        resText: 'returnToProgressBtn',
                        vis: this.visShowSaveBtn,
                        click: this.backToForm.bind(this)
                    },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}

export class TreeEffectedMappingItem extends BaseInfoModel {
    constructor(model, fileList) {
        super(model);
        this.currencyType = ko.observable(model.currencyType);
        this.selected = ko.observable();
        this.files = ko.observableArray();
        if (_h.any(fileList))
            for (let k = 0; k < fileList.length; k++) {
                const p = fileList[k];
                if (p.currencyType() === this.currencyType()) {
                    const checkItem = new FileItem(p);
                    if (_h.any(model.mappedFiles))
                        for (let l = 0; l < model.mappedFiles.length; l++) {
                            const mappedFile = model.mappedFiles[l];
                            if (p.value() === mappedFile) {
                                checkItem.selected(true);
                                checkItem.before(true);
                            }
                        }
                    this.files.push(checkItem);
                }
            }
    }
}

export class FileItem extends BaseInfoModel {
    constructor(model) {
        super(model);
        this.selected = ko.observable(false);
        this.before = ko.observable();
        this.randomId = Math.random() * (10000000 - 100) + 100;
    }

    createTagId() {
        return "FileItem-" + this.randomId;
    };
}

export class MappingResultError extends BaseInfoModel {
    constructor(model) {
        super(model);
        this.errorMessage = ko.computed(function () {
            let text = _h.getApiMessage(this.code);
            if (this.code === "FileNotMappedCompletely") {
                text += " - " + "خط " + this.differenceCount;
            }
            return text;
        }.bind(this));
    }

}

export class SubstituteNode extends BaseModel {
    constructor(model) {
        super(model);
    }
}

export class SubstituteNodeForm extends BaseFormModel {
    constructor(viewModel, editMode) {
        super(viewModel, editMode);
        this.activeControl = 0;
        this.nodeId = ko.observable();
        this.substituteId = ko.observable();
        this.nodeName = "";
        this.substituteName = "";
        if (editMode) {
            var model = viewModel.getSelectedRecord();
            this.nodeName = model.nodeName() + " ( " + model.nodeCode() + " )";
            this.substituteName = model.substituteName() + " ( " + model.substituteCode() + " )";
            this.nodeId(model.nodeId());
            this.substituteId(model.substituteId());
        }
        this.setValidationObject();
        this.createForm();
    }

    setValidationObject() {
        var self = this;
        self.validationObject = ko.validatedObservable({
            nodeId: self.nodeId.extend({
                required: true
            }),
            substituteId: self.substituteId.extend({
                required: true
            })
        });
    }

    setActiveFocus(name) {
        self.activeControl = Number(name);
    };

    onNodeSelect(name, value) {
        switch (name) {
            case "nodeId":
                this.nodeId(value);
                break;
            case "substituteId":
                this.substituteId(value);
                break;
        }
    };

    createForm() {
        const controls = [
            this.createLine({
                t: 'slcn', treeId:
                    _h.kocnx().mvm().treeId, slcType: "single", branchSelectable: false, val: this.nodeId,
                valName: this.nodeName
            }, undefined, true),
            this.createLine({
                t: 'slcn', treeId:
                    _h.kocnx().mvm().treeId, slcType: "single", branchSelectable: false, val: this.substituteId,
                valName: this.substituteName
            }, undefined, true, 30),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'create', vis: !this.editMode(), click: this.parentVM.create },
                    { name: 'edit', vis: this.editMode() === true, click: this.parentVM.edit },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}

export function SubstituteNodeViewModel() {
    const self = this;
    self.createBtn = function () {
        _h.kocnx()
            .openForm(new SubstituteNodeForm(self));
    };
    self.editBtn = function () {
        _h.kocnx()
            .openForm(new SubstituteNodeForm(self, true));
    };
    self.removeFilter = function () {
        self.nodeName(null);
        self.nodeId(null);
        self.getRecords();
    };
    self.refreshFormNodeSelect = function (item) {
        if (self.showForm()) {
            if (self.selectedRecord().activeControl === 1) {
                self.selectedRecord().nodeId(item.id());
                self.selectedRecord().nodeName("(" + item.code + ")" + item.name);
                self.selectedRecord().nodeCode(item.code);
            }
            if (self.selectedRecord().activeControl === 2) {
                self.selectedRecord().substituteId(item.id());
                self.selectedRecord().substituteName("(" + item.code + ")" + item.name);
                self.selectedRecord().substituteCode(item.code);
            }
        } else {
            self.nodeName(item.name);
            self.pageNumber(1);
            self.nodeId(item.id());
            self.getRecords();
        }
    };
    self.deleteListBtn = function () {
        var model = {
            idList: []
        };
        const array = [], items = [];
        ko.utils.arrayFilter(self.records(), function (record) {
            if (record.selected()) {
                model.idList.push(record.id());
                items.push(record);
            }
        });
        const message = items.length > 1 ?
            toast.createMessage(self.entityName, 'delrange', null, 'confirm') :
            toast.createMessage(self.entityName, 'del', null, 'confirm');
        _h.confirmDeleteAlert(message,
            function (res) {
                if (res) {
                    self.apiService.request({
                        name: "delete",
                        data: model,
                        success: function (data) {
                            if (!_h.isNullOrEmpty(data)) {
                                if (_h.any(items))
                                    for (let i = 0; i < items.length; i++) {
                                        self.records.remove(items[i]);
                                    }
                                toast.success(self.entityName, 'delrange');
                            }
                        },
                        error: function () {
                            toast.error(self.entityName, 'delrange');
                        }
                    });
                }
            });
    };
    self.init = function () {
        self.fillTableProperties();
        self.getRecords();
        self.iconSize("icon-image-small");
    };
    ko.utils.extend(self, new BaseViewModel({
        entityName: "SubstituteNode",
        getList: true,
        apiService: {
            actionList: ["filterby", "post", "put", "delete"]
        },
        buttons: [
            { name: 'delete', access: true, icon: 'Delete', cMenu: true },
            { name: 'deleteList', access: true, icon: 'Delete', cMenu: true },
            { name: 'edit', access: true, icon: 'Edit', cMenu: true },
            { name: 'help', access: false, cMenu: false },
            { name: 'refresh', access: false, cMenu: false },
            { name: 'tools', access: false, cMenu: false },
            { name: 'create', access: false, cMenu: false }
        ],
        filters: [
            { name: 'treeId' },
            { name: 'nodeId' },
            { name: 'nodeName' }
        ],
        tableStyle: "font-size: 11px;",
        sortDirection: "Ascending",
        sortProperty: "nodeCode",
        context: self,
        searchKeyType: "enter",
        cols: substituteNodeModelRes,
        selectRow: true,
        saveState: true,
        contextMenu: true,
        isMultiSelectRows: true,
        resizable: true
    }));
    self.btnVisibility = ko.computed(function () {
        const idList = self.multiCommandExecute("selectedItemIds");
        const selectedCount = idList.length;
        self.visedit(selectedCount === 1);
        self.visdelete(selectedCount === 1);
        self.visdeleteList(selectedCount > 1);
        self.viscreate(true);
        self.vishelp(true);
        self.visrefresh(true);
        self.vistools(true);
    });
    self.deleteBtn = function () {
        self.deleteListBtn();
    };
    self.shortNodeName = ko.computed(function () {
        if (_h.isNullOrEmpty(self.nodeName())
            || self.nodeName() === ""
            || self.nodeName().length < 30)
            return self.nodeName();
        return self.nodeName().substr(0, 27) + "...";
    });

}

export class MappingRule extends BaseModel {
    constructor(model) {
        super(model);

        this.shortName = ko.pureComputed(function () {
            let code = this.nodeCode();
            if (code)
                code += "-";
            if (this.nodeName().length < 30)
                return code + this.nodeName();
            return code + this.nodeName().substr(0, 27) + "...";
        }, this);
    }
}

export class MappingRuleForm extends BaseFormModel {
    constructor(viewModel, editMode, res, treeId) {
        super(viewModel, editMode, undefined, ["createMappingRuleCaption", "editMappingRuleCaption"]);
        this.width = "500px";
        this.ruleModel = ko.observable();
        this.lastPriority = ko.observable();
        let record = new TableConditionSet(this);
        this.result = ko.observable();
        if (!editMode) {
            this.treeId = ko.observable(treeId);
            this.autoPlacement = ko.observable(false);
            this.lastPriority(res + 1);
            this.priority(res + 1);
            record.fillEmpty(undefined);
            this.ruleModel(record);
        }
        else {
            var model = viewModel.multiCommandExecute("selectedRowRecord");
            this.lastPriority(res);
            if (!_h.isEmpty(model.nodeName())) {
                var nodeName = model.nodeName() + " ( " + model.nodeCode() + " ) ";
                this.nodeName(nodeName);
            }
            const rule = new PhraseTranslator().getModel(model.rule());
            record.fillModel(rule, model.ruleAggregation());
            this.ruleModel(record);
        }

        this.showResultBtn = ko.observable(true);
        this.showResultBlock = ko.observable(false);
        this.changeResultStatus = ko.computed(function () {
            if (this.showResultBtn()) {
                this.showResultBlock(false);
                this.showCancel(true);
            } else {
                this.showResultBlock(true);
                this.showCancel(false);
            }

        }.bind(this));
        this.setValidationObject();
        this.createForm();
        this.fillResultModel();
    }
    fillResultModel() {
        var modelResult = new MappingRuleDataViewModel(this);
        modelResult.treeId(this.treeId());
        modelResult.rule(this.rule());
        modelResult.balanceSheetId(_h.kocnx().mvm().sheetId());
        this.result(modelResult);
    }

    setValidationObject() {
        const self = this;
        this.validationObject = ko.validatedObservable({
            priority: self.priority.extend({
                required: true
            }),
            nodeId: self.nodeId.extend({
                required: {
                    onlyIf: function () {
                        return self.autoPlacement() === false;
                    }
                }
            }),
            ruleModel: self.ruleModel.extend({
                validation: {
                    validator: function (val, someOtherVal) {
                        const array = self.ruleModel().validateForm();
                        return !array.length;
                    }
                }
            })
        });
    }

    toggleAutoPlacement() {
        this.autoPlacement(!this.autoPlacement());
    }

    onNodeSelect(name, value, itemValue) {
        this.nodeId(value);
    }

    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'mappingrule-form-t' }, undefined, true, 30, 30),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    {
                        name: "custom",
                        resText: 'showResult',
                        vis: this.showResultBtn,
                        click: this.showResults.bind(this),
                        icon: "ModalResult"
                    },
                    {
                        name: "custom",
                        resText: 'returnToForm',
                        vis: this.showResultBlock,
                        click: this.returnToForm.bind(this),
                        icon: "Returned"
                    },
                    {
                        name: 'create',
                        vis: !this.editMode() && _h.kocnx().permitPeriodEdit(),
                        click: this.parentVM.create
                    },
                    {
                        name: 'edit',
                        vis: this.editMode() === true && _h.kocnx().permitPeriodEdit(),
                        click: this.parentVM.edit
                    },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }

    returnToForm() {
        this.showResultBtn(true);
        $(".modal-box").css("width", "500px");
    }

    showResults() {
        this.fillResultModel();
        this.showResultBtn(false);
        this.result().init();
        $(".modal-box").css("width", "700px");
    }

    toServer() {
        let data = ko.toJS(this);
        delete data["validationObject"];
        delete data["formButtons"];
        delete data["formControls"];
        delete data["parentVM"];
        delete data["editMode"];
        delete data["ad"];
        delete data["selected"];
        delete data["ruleModel"];
        delete data["result"];
        return data;
    }
}

export function MappingRuleViewModel() {
    const self = this;
    self.createBtn = function () {
        self.getLastPriority(function (res) {
            _h.kocnx()
                .openForm(new MappingRuleForm(self, false, res, self.treeId()));
        }, self.treeId());
    };
    self.editBtn = function () {
        self.getLastPriority(function (res) {
            _h.kocnx()
                .openForm(new MappingRuleForm(self, true, res, self.treeId()));
        }, self.treeId());
    };
    self.exportExcelBtn = function () {
        const selectedRecord = self.getSelectedRecord();
        const model = {
            controllerName: 59,
            inputData: {
                mappingRuleId: selectedRecord.id(),
                treeId: self.treeId(),
                balanceSheetId: self.balanceSheetId(),
                type: 1
            }
        };
        _h.kocnx().createExcel(model);
    };
    self.applyRuleBtn = function () {
        const item = self.multiCommandExecute("selectedRowRecord");
        const idList = [];
        idList.push(item.id());
        self.applyRules(idList);
    };
    self.applyRulesBtn = function () {
        const idList = self.multiCommandExecute("selectedItemIds");
        if (idList.length === 0) {
            const text = _h.getApiMessage("ActionSelectListEmptyError");
            _h.warningToast(text);
        } else {
            self.applyRules(idList);
        }
    };
    self.applyRules = function (idList) {
        const model = {
            idList: idList,
            treeId: self.treeId(),
            balanceSheetId: self.balanceSheetId()
        };
        self.apiService.request({
            name: "postapplyrules",
            data: model,
            success: function (data) {
                if (!_h.isNullOrEmpty(data)) {
                    if (idList.length === 1)
                        toast.success(self.entityName, 'custom', 'applyMappingRule');
                    if (idList.length > 1)
                        toast.success(self.entityName, 'custom', 'applyMappingRules');

                    if (_h.any(data.models)) {
                        _h.kocnx().mvm().childModel().refreshSign(true);
                        $("#tree_view").treeView("refreshTree", data.models);
                    }
                    self.getRecords();
                }
            },
            error: function () {
                if (idList.length === 1)
                    toast.error(self.entityName, 'custom', 'applyMappingRule');
                if (idList.length > 1)
                    toast.error(self.entityName, 'custom', 'applyMappingRules');
            }
        });
    };
    self.cancelRuleBtn = function () {
        const item = self.multiCommandExecute("selectedRowRecord");
        const idList = [];
        idList.push(item.id());
        self.cancelRules(idList);
    };
    self.cancelRulesBtn = function () {
        const idList = self.multiCommandExecute("selectedItemIds");
        if (idList.length === 0) {
            const text = _h.getApiMessage("ActionSelectListEmptyError");
            _h.warningToast(text);
        } else {
            self.cancelRules(idList);
        }
    };
    self.cancelRules = function (idList) {
        const model = {
            idList: idList,
            treeId: self.treeId(),
            balanceSheetId: self.balanceSheetId()
        };
        self.apiService.request({
            name: "postrollbackrules",
            data: model,
            success: function (data) {
                if (!_h.isNullOrEmpty(data)) {
                    if (idList.length === 1)
                        toast.success(self.entityName, 'custom', 'cancelMappingRule');
                    if (idList.length > 1)
                        toast.success(self.entityName, 'custom', 'cancelMappingRules');

                    if (_h.any(data.models)) {
                        $("#tree_view").treeView("refreshTree", data.models);

                    }
                    self.getRecords();
                }
            },
            error: function () {
                if (idList.length === 1)
                    toast.error(self.entityName, 'custom', 'cancelMappingRule');
                if (idList.length > 1)
                    toast.error(self.entityName, 'custom', 'cancelMappingRules');
            }
        });
    };
    self.deleteListBtn = function () {
        const model = {
            idList: [],
            treeId: self.treeId(),
            balanceSheetId: self.balanceSheetId()
        };
        const items = [];
        for (var i = 0; i < self.records().length; i++) {
            const record = self.records()[i];
            if (record.selected()) {
                model.idList.push(record.id());
                items.push(record);
            }
        }
        let message;
        if (items.length > 1) {
            message = toast.createMessage(self.entityName, 'delrange', null, 'confirm');
        } else {
            message = toast.createMessage(self.entityName, 'del', null, 'confirm');
        }
        _h.confirmDeleteAlert(message,
            function (res) {
                if (res) {
                    self.apiService.request({
                        name: "delete",
                        data: model,
                        success: function (data) {
                            if (!_h.isNullOrEmpty(data)) {
                                if (_h.any(items))
                                    for (let i = 0; i < items.length; i++) {
                                        self.records.remove(items[i]);
                                    }
                                self.afterUpdate(data.models);
                                toast.success(self.entityName, 'delrange');
                            }

                        },
                        error: function () {
                            toast.error(self.entityName, 'delrange');
                        }
                    });
                }
            });
    };
    self.init = function () {
        self.fillTableProperties();
        self.getRecords();
        self.iconSize("icon-image-small");
    };
    ko.utils.extend(self, new BaseViewModel({
        entityName: "MappingRule",
        getList: true,
        apiService: {
            actionList: ["filterby", "post", "put", "delete", "postapplyrules", "postrollbackrules"]
        },
        buttons: [
            { name: 'up', access: true, icon: 'Up', cMenu: true },
            { name: 'down', access: true, icon: 'Down', cMenu: true },
            { name: 'delete', access: true, icon: 'Delete', cMenu: true },
            { name: 'deleteList', access: true, icon: 'Delete', cMenu: true },
            { name: 'edit', access: true, icon: 'Edit', cMenu: true },
            { name: 'exportExcel', access: true, icon: 'ExportExcel', cMenu: true },
            { name: 'applyRule', access: true, icon: 'MappingOn', cMenu: true },
            { name: 'cancelRule', access: true, icon: 'MappingOff', cMenu: true },
            { name: 'applyRules', access: true, icon: 'MappingOn', cMenu: true },
            { name: 'cancelRules', access: true, icon: 'MappingOff', cMenu: true },
            { name: 'help', access: false, cMenu: false },
            { name: 'refresh', access: false, cMenu: false },
            { name: 'tools', access: false, cMenu: false },
            { name: 'create', access: false, cMenu: false }
        ],
        filters: [
            { name: 'treeId' },
            { name: 'balanceSheetId' }
        ],
        extraParams: ["lastPriority"],
        tableStyle: "font-size: 11px;",
        sortDirection: "Ascending",
        sortProperty: "priority",
        context: self,
        searchKeyType: "enter",
        cols: mappingruleModelRes,
        selectRow: true,
        saveState: true,
        contextMenu: true,
        isMultiSelectRows: true,
        resizable: true
    }));
    self.btnVisibility = ko.computed(function () {
        const selectedList = self.multiCommandExecute("selectedItems");
        const context = _h.kocnx();
        const permitPeriodEdit = context.permitPeriodEdit();
        if (_h.isNullOrEmpty(selectedList))
            return;

        if (selectedList.length === 0) {
            self.viscreate(permitPeriodEdit);
            self.visedit(false);
            self.visdelete(false);
            self.visdeleteList(false);
            self.visup(false);
            self.visdown(false);
            self.visapplyRule(false);
            self.viscancelRule(false);
            self.visapplyRules(false);
            self.viscancelRules(false);
            self.visexportExcel(false);
        }

        if (selectedList.length === 1) {
            let item = self.getSelectedRecord();
            if (item === null || item === undefined)
                item = selectedList[0];
            self.viscreate(permitPeriodEdit);
            self.visedit(permitPeriodEdit);
            self.visdelete(permitPeriodEdit);
            self.visdeleteList(false);
            self.visup(permitPeriodEdit && item.priority() > 1);
            self.visdown(permitPeriodEdit && self.lastPriority() !== item.priority());
            self.visapplyRule(permitPeriodEdit);
            self.viscancelRule(permitPeriodEdit);
            self.visapplyRules(false);
            self.viscancelRules(false);
            self.visexportExcel(true);
        }
        if (selectedList.length > 1) {
            self.viscreate(permitPeriodEdit);
            self.visedit(false);
            self.visdelete(false);
            self.visdeleteList(permitPeriodEdit);
            self.visup(false);
            self.visdown(false);
            self.visapplyRule(false);
            self.viscancelRule(false);
            self.visapplyRules(permitPeriodEdit);
            self.viscancelRules(permitPeriodEdit);
            self.visexportExcel(false);
        }

        self.vishelp(true);
        self.visrefresh(true);
        self.vistools(true);
    });
    self.deleteBtn = function () {
        self.deleteListBtn();
    };
}

export function TableConditionSet(parentForm) {
    const self = this;
    self.parentForm = parentForm;
    self.operatorsList = [];
    self.showDropDown = ko.observable(false);
    self.conditions = ko.observableArray();
    self.shortcuts = ko.observableArray();
    self.result = ko.observable("");
    self.text = ko.observable("");
    self.translatePhrase = function () {
        if (self.conditions().length === 1) {
            self.parentForm["rule"]("");
            if (self.conditions()[0].leftSide() &&
                self.conditions()[0].leftSide() !== "" &&
                self.conditions()[0].operator() &&
                self.conditions()[0].operator() !== "") {
                const phrase = self.conditions()[0].createConditionPhrase();
                self.result("[cs1:" + phrase + "]");
                self.parentForm["rule"](self.result());
            }
        }
        if (!_h.isNullOrEmpty(self.text()) && self.text() !== "") {
            if (self.conditions().length > 1) {
                let text = self.text();
                self.parentForm["rule"]("");
                for (let i = 0; i < self.conditions().length; i++) {
                    const target = self.conditions()[i];
                    const ph = target.createConditionPhrase();
                    const cName = "Cs" + (i + 1);
                    if (self.text().indexOf(cName) !== -1) {
                        const condStr = "[cs" + (i + 1) + ":" + ph + "]";
                        text = self.replace(text, cName, condStr);
                        self.result(text);
                    }
                }
                self.parentForm["rule"](self.result());
            }
        }
    };
    self.replace = function (text, cName, condStr) {
        var index = text.indexOf(cName);
        var cNLen = cName.length
        if (index > 0) {
            var first = text.substring(0, index);
            var last = text.substring(index + cNLen);
            return first + condStr + last;
        } else {
            var last = text.substring(index + cNLen);
            return condStr + last;
        }
    }
    self.fillModel = function (conditions, agr) {
        self.init(conditions, agr);
    };
    self.fillEmpty = function () {
        self.init(undefined);
    };
    self.addCondition = function () {
        const record = self.getConditionModel();
        record.fillModel(undefined);
        self.conditions.push(record);
    };
    self.removeCondition = function (item) {
        if (self.conditions().length > 1) {
            self.conditions.remove(item);
            $('a[href="#cond-0"]').trigger('click');
            self.translatePhrase();
        }
    };
    self.init = function (conditions, agr) {
        let record = null;
        if (_h.any(conditions))
            for (let i = 0; i < conditions.length; i++) {
                const condition = conditions[i];
                record = self.getConditionModel();
                record.fillModel(condition);
                self.conditions.push(record);
            }
        else {
            record = self.getConditionModel();
            record.fillModel(undefined);
            self.conditions.push(record);
        }
        if (!_h.isNullOrEmpty(agr)) {
            agr = agr.replace(/[c]/g, "C");
            self.text(agr);
        }
        self.operatorsList = {
            1000: { text: "Cs", data: "Cs", keyCode: 1000, enabled: ko.observable(false), after: [38, 124, 41] },
            40: { text: "(", data: "(", keyCode: 40, enabled: ko.observable(false), after: [40, 1000] },
            41: { text: ")", data: ")", keyCode: 41, enabled: ko.observable(false), after: [38, 124, 41] },
            38: { text: "و (AND)", data: "&&", keyCode: 38, enabled: ko.observable(false), after: [1000, 40] },
            124: { text: "یا (OR)", data: "||", keyCode: 124, enabled: ko.observable(false), after: [1000, 40] }
        };
        self.updateOperatorState();
        self.translatePhrase();
    };
    self.getConditionModel = function () {
        return new TableCondition(self.parentForm, self);
    };
    self.lastOperator = ko.observable();
    self.middleTyping = ko.observable();
    self.updateOperatorState = function () {
        if (_h.isNullOrEmpty(self.lastOperator()) || self.lastOperator() === "") {
            self.operatorsList[40].enabled(true);
            self.operatorsList[1000].enabled(true);
        } else {
            const last = self.operatorsList[self.lastOperator()];
            for (const prop in self.operatorsList) {
                if (self.operatorsList.hasOwnProperty(prop)) {
                    const target = self.operatorsList[prop];
                    if (last.after.indexOf(target.keyCode) !== -1) {
                        if (target.keyCode !== 41)
                            target.enabled(true);
                        else {
                            const rs = self.isAllowAddRightParentheses();
                            target.enabled(rs);
                        }
                    } else {
                        target.enabled(false);
                    }

                }
            }
        }
    };
    self.clickOperator = function (item) {
        self.text(self.text() + item.value.data);
        self.lastOperator(item.value.keyCode);
        self.updateOperatorState();
        self.translatePhrase();
    };
    self.clickCondition = function (model, index, cond) {
        self.text(self.text() + "Cs" + index);
        self.lastOperator(self.operatorsList[1000].keyCode);
        self.updateOperatorState();
        self.translatePhrase();
    };
    self.isAllowAddRightParentheses = function () {
        const lPCount = self.text().replace(/[^(]/g, "").length;
        const rPCount = self.text().replace(/[^)]/g, "").length;
        if (lPCount === 0)
            return false;
        if (lPCount === rPCount)
            return false;
        return lPCount > rPCount;
    };
    self.proxyKeyDown = function (data, event) {
        const itemOperator = self.operatorsList[event.keyCode];
        if (itemOperator && itemOperator.enabled()) {
            self.text(self.text() + self.operatorsList[event.keyCode].data);
            self.lastOperator(self.operatorsList[event.keyCode].keyCode);
            self.updateOperatorState();
        } else {
            if (event.keyCode === 67 && !self.middleTyping()) {
                self.middleTyping(true);
                if (self.operatorsList[1000].enabled()) {
                    self.text("Cs");
                }
            }
            if (event.keyCode >= 49 && event.keyCode <= 57 && self.middleTyping()) {
                const condition = self.conditions()[event.keyCode - 48];
                if (condition && condition.validationObject.isValid()) {
                    self.text(self.text() + "Cs" + (event.keyCode - 48));
                    self.middleTyping(false);
                    self.lastOperator(1000);
                }
            }
            if (event.keyCode === 46) {
                event.preventDefault();
                self.text("");
                self.lastOperator(undefined);
                self.updateOperatorState();
            }
            if (event.keyCode === 8) {
                event.preventDefault();
                if (!self.middleTyping())
                    self.clearOnStep();
                else {
                    const rest = self.text().substring(0, self.text().length - 2);
                    self.text(rest);
                    self.middleTyping(false);
                }
            }
        }
        self.translatePhrase();
    };
    self.refreshShortcuts = ko.computed(function () {
        if (self.conditions().length > 1) {
            self.shortcuts.removeAll();
            let and = "";
            let or = "";
            ko.utils.arrayForEach(self.conditions(), function (f, index) {
                if (f.validationObject.isValid()) {
                    if (index + 1 !== self.conditions().length) {
                        and += "Cs" + (index + 1) + "&&";
                        or += "Cs" + (index + 1) + "||";
                    } else {
                        and += "Cs" + (index + 1);
                        or += "Cs" + (index + 1);
                    }
                }
            });
            self.shortcuts.push(and);
            self.shortcuts.push(or);
        } else {
            self.shortcuts.removeAll();
        }
    });
    self.clickShortcut = function (item) {
        self.text("");
        self.text(item);
        self.lastOperator(1000);
        self.updateOperatorState();
        self.translatePhrase();
    };
    self.clearOnStep = function () {
        const last = self.lastOperator();
        if (last !== undefined && last !== "") {
            const itemOperator = self.operatorsList[last];
            let lastChar = "";
            const rest = self.text().substring(0, self.text().lastIndexOf(itemOperator.data));
            self.text(rest);
            lastChar = self.text().substring(self.text().length - 1);
            self.guessLastOperator(lastChar);

        }
    };
    self.guessLastOperator = function (lastChar) {
        if (lastChar === undefined || lastChar === "")
            self.lastOperator(undefined);
        else if ($.isNumeric(lastChar))
            self.lastOperator(1000);
        else if (lastChar === "(")
            self.lastOperator(40);
        else if (lastChar === ")")
            self.lastOperator(41);
        else if (lastChar === "&")
            self.lastOperator(38);
        else if (lastChar === " |")
            self.lastOperator(124);

    };
    self.validationObject = ko.validatedObservable({
        conditions: self.conditions,
        text: self.text.extend({
            required: {
                onlyIf: function () {
                    return self.conditions().length > 1;
                }
            },
            isAllConditionsUse: {
                params: self.conditions
            },
            isConditionsUseValid: {
                params: self.conditions
            },
            remoteIsValidExpression: {
                onlyIf: function () {
                    return self.conditions().length > 1 && self.text() !== undefined && self.text() !== "";
                },
                params: [true, false, 59]
            }
        })
    });
    self.reset = function (loc) {
        const zero = self.conditions()[0];
        zero.reset(loc);
        self.conditions.removeAll();
        self.conditions.push(zero);
    };
    self.validateForm = function () {
        const array = [];
        for (let i = 0; i < self.conditions().length; i++) {
            const target = self.conditions()[i];
            const condArray = { propFaName: "شرط " + (i + 1), propName: "Condition " + (i + 1), children: [] };
            for (let p in target.validationObject()) {
                if (target.validationObject().hasOwnProperty(p)) {
                    const valObj = target.validationObject()[p];
                    if (!_h.isNullOrEmpty(valObj.error()))
                        condArray.children.push({ propName: p, error: valObj.error() });
                }

            }
            if (condArray.children.length > 0)
                array.push(condArray);
        }
        if (!_h.isNullOrEmpty(self.text.error())) {
            if (!self.validationObject.isValid())
                self.validationObject.errors.showAllMessages();

            array.push({
                propName: "ConditionAggregation",
                propFaName: "تجمیع شروط ",
                error: self.text.error()
            });
        }
        return array;
    };
}

export function TableCondition(parent, parentSet) {
    const self = this;
    self.parentForm = parent;
    self.parentSet = parentSet;
    self.leftSideItems = ko.observableArray(ruleBases);
    self.leftSide = ko.observable();
    self.operator = ko.observable();
    self.rightSide = ko.observable();
    self.rightSideDataTypes = ko.observableArray([]);
    self.rightSideDataType = ko.observable();
    self.operators = ko.observableArray();
    self.onSelect = function (controlName) {
        switch (controlName) {
            case "leftSide":
                self.operator(undefined);
                self.operators.removeAll();

                switch (self.leftSide()) {
                    case 1:
                        self.operators.push(
                            { text: "Match", enText: "Match", value: 14, color: "", dataTypes: [15] });
                        self.rightSideDataType(15);
                        break;
                    case 2:
                        self.operators.push({ text: ">", enText: ">", value: 1, color: "", dataTypes: [0] });
                        self.operators.push({ text: "<", enText: "<", value: 2, color: "", dataTypes: [0] });
                        self.operators.push({ text: "=", enText: "=", value: 3, color: "", dataTypes: [0] });
                        self.operators.push({ text: "<>", enText: "<>", value: 4, color: "", dataTypes: [0] });
                        self.operators.push({ text: ">=", enText: ">=", value: 5, color: "", dataTypes: [0] });
                        self.operators.push({ text: "<=", enText: "<=", value: 6, color: "", dataTypes: [0] });
                        self.rightSideDataType(0);
                        break;
                }
                self.rightSide(undefined);
                self.parentSet.translatePhrase();
                break;
            case "operator":

                self.parentSet.translatePhrase();
                break;
        }
    };
    self.rightSideDataType.subscribe(function (newValue) {
        self.parentSet.translatePhrase();
    });
    self.rightSide.subscribe(function (newValue) {
        self.parentSet.translatePhrase();
    });
    self.validationObject = ko.validatedObservable({
        rightSide: self.rightSide.extend({
            required: {
                onlyIf: function () {
                    const conditionCount = self.parentSet !== "" && self.parentSet.conditions().length > 1;
                    const hasLeftSideValue = self.leftSide && self.leftSide() !== "";
                    const hasOperatorValue = self.operator && self.operator() !== "";
                    const reqiureVal = self.rightSideDataType && self.rightSideDataType() !== "" && self.rightSideDataType() !== 13;

                    return conditionCount && (hasLeftSideValue || hasOperatorValue) && reqiureVal;
                }
            }
        }),
        leftSide: self.leftSide.extend({
            required: {
                onlyIf: function () {
                    return self.parentSet !== "" && self.parentSet.conditions().length > 1;
                }
            }
        }),
        operator: self.operator.extend({
            required: {
                onlyIf: function () {
                    const conditionCount = self.parentSet !== "" && self.parentSet.conditions().length > 1;
                    const hasLeftSideValue = self.leftSide && self.leftSide() !== "";
                    return conditionCount && hasLeftSideValue;
                }
            }
        })
    });
    self.fillModel = function (model) {
        if (model) {
            self.leftSide(Number(model.leftSide));
            self.onSelect("leftSide");
            self.operator(model.operator.value);
            self.onSelect("operator");
            self.rightSideDataType(model.rightSide.type);
            self.rightSide(model.rightSide.value);
        }
    };
    self.createConditionPhrase = function () {
        let ph = "[compare:'" + self.leftSide() + "']";
        ph += _h.getEnumEnText(
            [{ text: "Match", enText: "Match", value: 14, color: "", dataTypes: [15] },
            { text: ">", enText: ">", value: 1, color: "", dataTypes: [0] },
            { text: "<", enText: "<", value: 2, color: "", dataTypes: [0] },
            { text: "=", enText: "=", value: 3, color: "", dataTypes: [0] },
            { text: "<>", enText: "<>", value: 4, color: "", dataTypes: [0] },
            { text: ">=", enText: ">=", value: 5, color: "", dataTypes: [0] },
            { text: "<=", enText: "<=", value: 6, color: "", dataTypes: [0] }],
            self.operator());
        const val = self.rightSideDataType();
        let right = "";
        switch (val) {
            case 0:
                right = "int:'";
                break;
            case 15:
                right = "pattern:'";
                break;
            case 20:
                right = "likepattern:'";
                break;
            case null:
            case undefined:
            case "":
            case "-":
            case 13:
                return ph;
        }
        if (self.rightSide() !== undefined)
            ph += "[" + right + self.rightSide() + "']";
        else
            ph += "[" + right + "']";
        return ph;
    };
    self.reset = function () {
        self.leftSide(undefined);
        self.operator(undefined);
        self.rightSideDataType(undefined);
        self.rightSide(undefined);
    };
}

export class MappingRuleData extends BaseModel {
    constructor(model) {
        super(model);
    }
}

export function MappingRuleDataViewModel(parent) {
    const self = this;
    self.parent = parent;
    self.exportRuleExcelBtn = function () {
        const model = {
            controllerName: 59,
            inputData: {
                treeId: self.treeId(),
                balanceSheetId: self.balanceSheetId(),
                type: 0,
                rule: self.parent.rule(),
                mappingRuleId: self.parent.id()
            }
        };
        _h.kocnx().createExcel(model);
    };
    self.init = function () {
        self.fillTableProperties();
        self.getRecords();
    };
    ko.utils.extend(self, new BaseViewModel({
        entityName: "MappingRuleData",
        getList: true,
        apiService: {
            actionList: ["filterby"]
        },
        buttons: [
            { name: 'exportRuleExcel', access: true, icon: 'ExportExcel', cMenu: true },
            { name: 'refresh', access: false, cMenu: false }
        ],
        extraParams: ["totalCreditor", "totalDebtor"],
        filters: [
            { name: 'treeId' },
            { name: 'balanceSheetId' },
            { name: 'rule' },
            { name: 'mappingRuleId' }
        ],
        footerTemplate: "mappingruledata-footertable-template",
        tableStyle: "font-size: 11px;",
        sortDirection: "Ascending",
        sortProperty: "code",
        context: self,
        searchKeyType: "enter",
        cols: mappingruledataModelRes,
        selectRow: true,
        saveState: true,
        contextMenu: true,
        resizable: true
    }));
    self.btnVisibility = ko.computed(function () {
        self.visexportRuleExcel(self.records().length > 0);
        self.visrefresh(true);
    });
}

export function MappingSrcViewModel() {
    const self = this;
    self.records = [];

    self.entityName = "MappingSrc";
    self.apiService = new ApiService({
        actionList: ["autopost",
            "filterby"]
    }, self.entityName);
    self.searchKey = ko.observable();
    self.filterType = ko.observable(0);
    self.treeId = ko.observable();
    self.treeName = ko.observable();
    self.showMapped = ko.observable(false);
    self.showMapped.subscribe(function (newValue) {
        if (_h.isNullOrEmpty(newValue)) return;
        $("#tree_view_l").treeView("collectOpenBranches");
        $("#tree_view_l").treeView("changeShowMapped", newValue);
    });
    self.configTools = function () {
        $("#tree_view_l").treeView({
            tType: "MappingSrc",
            location: "MappingSrc",
            nodes: self.records,
            rootId: self.treeId(),
            permitPeriodEdit: _h.kocnx().permitPeriodEdit(),
            controllerName: 16,
            mappingSide: 2,
            showMapped: self.showMapped(),
            rootName: self.treeName()
        });
    };
    self.onEnterSearchKey = function (model, e) {
        if (e.keyCode === 13) {
            self.getRecords(function (res) {
            });
        }
        return true;
    };
    self.showFilterItem = function (item) {
        return item.type !== 2 && item.type !== 3;
    };
    self.expandAll = function () {
        $("#tree_view_l").treeView("expandAll");
    };
    self.collapseAll = function () {
        $("#tree_view_l").treeView("collapseAll");
    };
    self.toggleShowMapped = function () {
        self.showMapped(!self.showMapped());
        self.getRecords(function (res) {
            $("#tree_view_l").treeView("openBranches");
        });
    };
    self.autoMapBtn = function () {
        const model = {
            codes: [],
            treeId: self.treeId()
        };
        const items = $("#tree_view_l").treeView("selectedItems");
        if (items)
            for (let i = 0; i < items.length; i++) {
                const item = items[i];
                model.codes.push(item.id + "");
            }
        self.apiService.request(
            {
                name: "/api/mapping/autopost",
                data: model,
                success: function (data) {
                    toast.success(self.entityName, 'custom', 'applyAutoMapping');
                    _h.kocnx().mvm().getRecords(function (res) {
                    });
                    self.getRecords(function (res) {
                    });
                },
                error: function (data) {
                    toast.error(self.entityName, 'custom', 'applyAutoMapping');
                }
            });
    };
    self.exportExcelBtn = function () {
        const model = {
            controllerName: 16,
            inputData: {
                id: self.treeId()
            }
        };
        _h.kocnx().createExcel(model);
    };
    self.getRecords = function (callback) {
        self.apiService.request({
            name: "/api/mapping/filterby",
            data: {
                treeId: self.treeId(),
                filterType: self.filterType(),
                searchKey: self.searchKey(),
                mappingSide: 2,
                showMapped: self.showMapped()
            },
            success: function (data) {
                if (!_h.isNullOrEmpty(data)) {
                    if (_h.any(data.nodes))
                        self.records = data.nodes;
                    else
                        self.records = [];
                    self.configTools();
                }
                callback(true);
            },
            error: function (data) {
                const text = _h.getApiMessage("ErrorLoadMapTree");
                _h.failToast(text);
                callback(false);
            }
        });
    };
    self.init = function () {
        self.getRecords(function (res) {
        });
    };
}

$(document).on("shown.bs.tab", '.mapping-tab a[data-toggle="tab"]', function (e) {
    const target = $(e.target).attr("href");
    const tabName = target.replace("-t", "").replace("#", "");
    var context = _h.kocnx();
    switch (tabName) {
        case "balancesheetmapping":
            _h.kocnx().mvm().activeSide(1);
            if (context.mvm().childModel().refreshSign()) {
                context.mvm().childModel().refreshSign(false);
                context.mvm().childModel().getRecords();
            }
            break;
        case "substitutenode":
            context.mvm().activeSide(2);
            context.mvm().onClickleftSideTab();
            break;
        case "mappingruletab":
            context.mvm().activeSide(3);
            context.mvm().onClickleftSideTab();
            break;
    }
});