var { BaseInnerModel, FormBuilder, BaseModel, BaseInfoModel, BaseSecondaryForm } = require('./baseModels.js');
import { ApiService } from "../../util/apiService.js";
require('knockout.validation');

export class SelectItem extends BaseInnerModel {
    constructor(model) {
        super(model);
        if (!this["selected"])
            this.selected = ko.observable(false);
    }
}
export class DesignItem {
    constructor(model) {
        this.text = ko.observable(model.text);
        this.value = ko.observable(model.value);
        this.type = ko.observable(model.type);
        this.active = ko.observable(model.active);
        this.previewMode = ko.observable(false);
        this.triggerEditable = ko.observable(false);
        this.refreshToolBar = ko.observable(false);
        this.editable = ko.observable(model.editable || false);
        this.lockedBy = ko.observable(model.lockedBy);
        this.lockedByUserId = ko.observable(model.lockedByUserId);

        this.lockedCaption = ko.pureComputed(function () {
            var lockedBy = this.lockedBy();
            if (lockedBy)
                return "قفل شده توسط " + lockedBy;
        }, this);
    }
}
export class TreeMapSelect extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.currencyType = ko.observable(model["currencyType"]);
    }
}

export class ColumnSelectItem extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.selected = ko.observable();
        this.enumValues = ko.observableArray();
        if (_h.any(model.values)) {
            for (var i = 0; i < model.values.length; i++) {
                var val = model.values[i];
                if (typeof val === 'object')
                    this.enumValues.push(new SelectItem(val));
                else
                    this.enumValues.push(new SelectItem({ text: val, value: val }));
            }
        }
    }
}

export class TableSelectItem extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.fields = ko.observableArray();
        if (_h.any(model.fields))
            for (var j = 0; j < model.fields.length; j++) {
                var field = new ColumnSelectItem(model.fields[j]);
                this.fields.push(field);
            }
    }
}

export class CompanySelectItem extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.disabled = ko.observable(false);
        this.hide = ko.observable(false);
    }
}

export class TreeBalanceReportSelectItem extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.selected = ko.observable();
    }
}

export class TreeSelectItem extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.text = ko.observable(model.name);
        this.value = ko.observable(model.id);
        this.files = model.files;
    }
}

export class TreeAdjustmentSelectItem extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.items = ko.observableArray();
        if (_h.any(model.items))
            for (let i = 0; i < model.items.length; i++) {
                this.items.push(new SelectItem(model.items[i]));
            }
    }
}

export class CompanyTokenInfo {
    constructor(model, companyId) {
        this.id = ko.observable(model.id);
        this.name = ko.observable(model.name);
        this.show = ko.observable(true);
        this.selected = ko.observable(model.id === companyId);
        this.preSelected = ko.observable(false);
        this.periods = ko.observableArray();
        this.fillPeriods(model.periods);
    }

    fillPeriods(list) {
        this.periods.removeAll();
        if (_h.any(list)) {
            for (let i = 0; i < list.length; i++) {
                let target = list[i];
                this.periods.push(new PeriodInfo(target));
            }
        }
    }
}

export class PeriodInfo extends BaseInfoModel {
    constructor(model) {
        super(model);
        this.preSelected = ko.observable(model.selected || false);
        this.getColorRow = ko.pureComputed(function () {
            if (this.stateType === 0)
                return '#ccc';
            if (this.closed)
                return 'red';
            return 'black';
        }.bind(this));
    }
}

export class PeriodSelectItem extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.description = model.description;
    }
}

export function Column(item, parent) {
    var self = this;
    self.parentContext = parent;
    self.colParent = item.colParent;
    self.name = item.colName;
    self.fa = item.fa;
    self.tablecol = item.tablecol;
    self.sortDir = ko.observable(item.sortDir);
    self.visibleCol = ko.observable(item.visibleCol);
    self.visibleItem = ko.observable(item.visibleItem || false);
    self.activeGroupBy = ko.observable(item.activeGroupBy);
    self.groupDir = ko.observable(item.groupDir);
    self.groupBy = item.groupBy;
    self.className = item.className;
    self.size = item.size;
    self.width = item.width;
    self.type = item.type;
    self.alias = item.alias;
    self.template = item.template;
    self.popup = item.popup;
    self.click = item.click;
    self.disableSort = item.disableSort;
    self.enumSourceName = item.enumSourceName;
    self.templateName = item.templateName;
    self.filterType = item.filterType || false;
    self.randomId = Math.random() * (10000000 - 100) + 100;
    self.createTagId = ko.computed(function () {
        return "col-" + self.randomId;
    });
    self.sortDir.subscribe(function (newValue) {
        if (newValue !== undefined && newValue !== null && self.parentContext) {
            _h.kocnx().saveTableState(self.parentContext);
        }
    });
    self.visibleCol.subscribe(function (newValue) {
        if (newValue !== undefined && newValue !== null && self.parentContext) {
            _h.kocnx().saveTableState(self.parentContext);
            setTimeout(function () {
                self.parentContext.renderedHandler()
            }, 1)
        }
    });
    self.visibleItem.subscribe(function (newValue) {
        if (newValue !== undefined && newValue !== null && self.parentContext) {
            self.parentContext.checkVisibleItem(self);
            _h.kocnx().saveTableState(self.parentContext);
            setTimeout(function () {
                self.parentContext.renderedHandler()
            }, 1)
        }
    });
    self.getSize = function () {
        if (self.width)
            return self.width + "px";
        else
            return self.size + "%";
    }
    self.getClass = function () {
        return "col-title " + self.type + "-ty";
    }
};

export class TreeFormulaSelectItem extends BaseInfoModel {
    constructor(model) {
        super(model);
    }
}

export class TreeFormulaMakerSelectItem extends BaseInfoModel {
    constructor(model) {
        super(model);
        this.valueTypeText = _h.getEnumText(valueTypes, model.valueType);
        this.disabled = ko.observable(false);
        this.hide = ko.observable(false);
    }
}

export class UserProfile extends BaseSecondaryForm {
    constructor(viewmodel, model) {
        super(viewmodel,
            [
                { name: "id", type: "ob", val: model.id },
                { name: "firstName", type: "ob", val: model.firstName },
                { name: "lastName", type: "ob", val: model.lastName },
                { name: "userName", type: "ob", val: model.userName },
                { name: "mobile", type: "ob", val: model.mobile },
                { name: "email", type: "ob", val: model.email },
                { name: "phoneNumber", type: "ob", val: model.phoneNumber },
                { name: "fax", type: "ob", val: model.fax },
                { name: "location", type: "ob", val: model.location },
            ],
            "userProfileCaption");
        this.setValidationObject();
        this.createForm();
    }

    setValidationObject() {
        var self = this;
        this.validationObject = ko.validatedObservable({
            firstName: self.firstName.extend({
                required: true,
                minLength: 3,
                maxLength: 32,
                persianOnly: null
            }),
            lastName: self.lastName.extend({
                required: true,
                minLength: 3,
                maxLength: 32,
                persianOnly: null
            }),
            userName: this.userName.extend({
                required: true,
                minLength: 4,
                remoteIsUniqueRule: { params: [this.id, "User", "userName"] },
                userNameValidation: null,
                maxLength: 20
            }),
            email: self.email.extend({
                englishOnly: null,
                email: true
            }),
            mobile: self.mobile.extend({
                persianMobile: null,
                numberOnly: null,
                minLength: {
                    params: 11,
                    message: "شماره تلفن همراه باید 11 کاراکتر عددی باشد"
                },
                maxLength: {
                    params: 11,
                    message: "شماره تلفن همراه باید 11 کاراکتر عددی باشد"
                }
            }),
            phoneNumber: self.phoneNumber.extend({
                phoneNumberCheck: null,
            }),

            fax: self.fax.extend({
                phoneNumberCheck: null
            }),
            location: self.location.extend({
                maxLength: 32,
                persianOnly: null
            }),
        });
    }

    createForm() {
        const controls = [
            this.createLine({ t: 'txb', val: this.firstName },
                { t: 'txb', val: this.lastName }, true, 0),
            this.createLine({ t: 'txb', val: this.userName },
                { t: 'txb', val: this.email }, true, 30),
            this.createLine({ t: 'txb', val: this.phoneNumber },
                { t: 'txb', val: this.mobile }, true, 30),
            this.createLine({ t: 'txb', val: this.location },
                { t: 'txb', val: this.fax }, true, 30)
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: "custom", resText: 'editFormBtn', vis: true, click: this.parentVM.editUserProfile },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}

export class ResetPasswordModel extends BaseSecondaryForm {
    constructor(viewModel, model) {
        super(viewModel, [
            { name: "userId", type: "ob", val: model["userId"] },
            { name: "currentPassword", type: "ob" },
            { name: "newPassword", type: "ob" },
            { name: "confirmNewPassword", type: "ob" },
        ], "adminResetPasswordCaption");
        this.setValidationObject(model);
        this.createForm();
    }

    setValidationObject(model) {
        var obj = {};
        var self = this;
        var min = _h.getSd().pmc;
        if (!model.userId)
            obj.currentPassword = self.currentPassword.extend({ englishOnly: 1, required: true });
        obj.newPassword = self.newPassword.extend({
            required: true,
            englishOnly: true,
            passwordComplexity: [min]
        });
        obj.confirmNewPassword = self.confirmNewPassword.extend({
            confirmPassword: { params: self.newPassword },
            required: true
        });
        self.validationObject = ko.validatedObservable(obj);
    }

    createForm() {
        const controls = [];
        if (_h.isNullOrEmpty(this.userId()))
            controls.push(this.createLine({ t: 'txb', val: this.currentPassword, type: 'password' },
                null, true, 30));
        controls.push(this.createLine({ t: 'txb', val: this.newPassword, type: 'password' },
            { t: 'txb', val: this.confirmNewPassword, type: 'password' }, true, 30));

        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [{
                    name: "custom", resText: 'editFormBtn', vis: true, click: !_h.isNullOrEmpty(this.userId()) ?
                        this.parentVM.adminResetPassword : _h.kocnx().editChangePassword
                },
                { name: 'cancel', click: _h.kocnx().closeForm }
                ]
            }
        });
    }
}

export class Menu extends BaseInfoModel {
    constructor(model) {
        super(model);
        this.disable = ko.observable(model.disable);
        this.active = ko.observable(model.active);
    }
}

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

export class ChangeLogViewModel extends FormBuilder {
    constructor() {
        super();
        this.caption = ko.observable(_h.getLocalizedText("changeslogCaption"));
        this.appVersions = ko.observableArray();
        this.init();
        this.createForm();
    }

    init() {
        ApiService.request(
            {
                url: "/api/changelog/filterby",
                data: { id: this.id },
                success: function (data) {
                    this.appVersions.removeAll();
                    if (_h.any(data))
                        for (var j = 0; j < data.length; j++) {
                            var target2 = data[j];
                            var record2 = new AppVersion(target2);
                            this.appVersions.push(record2);
                        }
                }.bind(this),
                error: function (data) {
                    var text = _h.getApiMessage("ErrorLoadVersion");
                    _h.failToast(text);
                }
            });
    }

    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'changelog-content-f' }, undefined, true, 30, 30),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}

export class AppVersion extends BaseInfoModel {
    constructor(model) {
        super(model);
        this.changeLogs = ko.observableArray(model.changeLogs);
    }
}

export class HelpViewModel extends FormBuilder {
    constructor(parent, e) {
        super();
        this.parent = parent;
        this.caption = ko.observable(_h.getLocalizedText("helpCaption"));
        this.selectedRow = ko.observable();
        this.na = ko.observable();
        this.de = ko.observable();
        this.records = [];
        this.init(e);
        this.createForm();
    }

    init(searchKey, e) {
        var tab;
        var loc = $(e.target).attr("data-location");
        if (loc)
            tab = _h.getEnumItem(controllerNames, loc);
        var menu = _h.getEnumItemByText(pageNames, this.parent.pageName());

        if (_h.isNullOrEmpty(tab))
            $.each(controllerNames, function (i, p) {
                if (p.enText.toLowerCase() === window.resDomain.toLowerCase())
                    tab = p;
            });
        var model = {
            menu: menu.value,
            tab: tab.value,
            searchKey: searchKey
        };
        ApiService.request(
            {
                url: "/api/help/filterby",
                data: model,
                success: function (data) {
                    this.records = [];
                    if (_h.any(data)) {
                        for (var j = 0; j < data.length; j++) {
                            var record = new Help(data[j]);
                            this.records.push(record);
                        }
                        $("#tree_view_hp").treeView({
                            tType: "Help",
                            location: "Help",
                            nodes: this.records,
                            rootId: "10",
                            onSelectRow: this.onSelectRow
                        });
                    }
                }.bind(this),
                error: function (data) {
                }
            });
    }

    onSelectRow(item) {
        this.na = ko.observable(item.na);
        this.de = ko.observable(item.de);
    }

    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'help-content-t' }, undefined, true, 30, 30),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}

export class Help extends BaseInfoModel {
    constructor(model) {
        super(model);
        this.children = [];
        if (_h.any(model.children))
            for (let i = 0; i < model.children.length; i++) {
                var target = model.children[j];
                var record = new Help(target);
                this.children.push(record);
            }
    }
}

export class TipItem extends BaseInfoModel {
    constructor(model) {
        super(model);
        if (!_h.isNullOrEmpty(model.pathNodes))
            self.path = model.pathNodes.join('=>');
        else
            self.path = "";
    }
}

export class ConnectionManager extends BaseSecondaryForm {
    constructor(viewModel, model) {
        super(viewModel, [
            { name: "entityName", type: "", val: "Connection" },
            { name: "controllerName", type: "", val: model.controllerName },
            { name: "selectedRow", type: "ob" },
            { name: "hasNextStage", type: "ob" },
            { name: "lastPriority", type: "ob" },
            { name: "records", type: "obar" },
            { name: "permissions", type: "obar" },
            { name: "selectItems", type: "obar" }]
            , model.caption);

        this.visCreateBtn = ko.pureComputed(function () {
            var first = !this.selectedRow() ||
                !this.selectedRow().processItem() ||
                this.selectedRow().processItem().percent() === 100;
            var second = !_h.isNullOrEmpty(this.selectedRow()) && this.selectedRow().resultMode() === false;
            return first && second && this.permissions().indexOf(3) !== -1 && this.selectedRow().id() === undefined;
        }.bind(this));
        this.visEditBtn = ko.pureComputed(function () {
            var first = !this.selectedRow() ||
                !this.selectedRow().processItem() ||
                this.selectedRow().processItem().percent() === 100;
            var second = !_h.isNullOrEmpty(this.selectedRow()) && this.selectedRow().resultMode() === false;
            return first && second && this.permissions().indexOf(3) !== -1 && this.selectedRow().id() !== undefined;
        }.bind(this));
        this.visExecuteBtn = ko.pureComputed(function () {
            var first = !this.selectedRow() ||
                !this.selectedRow().processItem() ||
                this.selectedRow().processItem().percent() === 100;
            var second = !_h.isNullOrEmpty(this.selectedRow()) && this.selectedRow().resultMode() === false;
            return first && second && this.selectedRow().id() !== undefined;
        }.bind(this));
        this.visCompleteRunBtn = ko.pureComputed(function () {
            var first = !this.selectedRow() ||
                !this.selectedRow().processItem() ||
                this.selectedRow().processItem().percent() === 100;
            var second = !_h.isNullOrEmpty(this.selectedRow()) && this.selectedRow().resultMode() === true;
            return first && second && this.selectedRow().resultErrors().length === 0;
        }.bind(this));

        this.getRecords();
        this.getSelectList();
        this.createForm();
    }

    getRecords() {
        var filterModel = {
            controllerName: this.controllerName
        };
        ApiService.request(
            {
                url: "/api/connection/filterby",
                data: filterModel,
                success: function (data) {
                    this.records.removeAll();
                    this.permissions.removeAll();
                    if (!_h.isNullOrEmpty(data)) {
                        if (_h.any(data.list)) {
                            for (var m = 0; m < data.list.length; m++) {
                                var target = data.list[m];
                                var record = new Connection();
                                record.fillModel(target, data.lastPriority);
                                this.records.push(record);
                            }
                            var first = this.records()[0];
                            if (_h.isNullOrEmpty(this.selectedRow())) {
                                this.selectedRow(first);
                                first.selected(true);
                            }
                        }
                        if (_h.any(data.permissions)) {
                            for (var i = 0; i < data.permissions.length; i++) {
                                this.permissions.push(data.permissions[i]);
                            }
                        }

                        this.lastPriority(data.lastPriority);
                    }
                    _h.fixLabelsSize();
                }.bind(this),
                error: function (data) {
                    toast.error(this.entityName, 'getList');
                }.bind(this)
            });
    }

    getSelectList() {
        var filterModel = {
            controllerName: this.controllerName
        };
        ApiService.request(
            {
                url: "/api/connection/getselectitems",
                data: filterModel,
                success: function (data) {
                    this.selectItems.removeAll();
                    if (_h.any(data)) {
                        for (var m = 0; m < data.length; m++) {
                            var target = data[m];
                            var record = new SelectItem(target);
                            this.selectItems.push(record);
                        }
                    }
                }.bind(this),
                error: function (data) {

                }
            });
    }

    executeBtn(item) {
        var model = item[1].selectedRow().getRunProperties();
        if (model === false)
            return model;
        ApiService.request(
            {
                url: "/api/connection/postrun",
                data: model,
                success: function (data) {
                    _h.kocnx().checkProcessQueue();
                    localStorage.setItem("ProcessToken", "");
                },
                error: function (data) {

                }
            });
    }

    cancelExecuteBtn() {
        this.resultMode(false);
        this.properties.removeAll();
        this.resultErrors.removeAll();
        this.outputFiles.removeAll();
    }

    createBtn() {
        var self = this;
        this.getLastPriority(function (res) {
            if (res !== null) {
                var record = new Connection();
                record.fillEmpty(self.controllerName, res);
                var moduleConnection = new ModuleConnectionProperties(self);
                moduleConnection.fillEmpty();
                record.connectionProperties(moduleConnection);
                self.selectedRow(record);
                record.editMode(false);
            }
        });
    }

    getLastPriority(callback, id) {
        var model = {
            controllerName: this.controllerName,
            isConnection: true,
            id: id
        };
        ApiService.request({
            url: "/api/common/getlastpriority",
            data: model,
            success: function (data) {
                callback(data);
            },
            error: function (data) {
                toast.error(self.entityName, 'get', 'LastPriority');
                callback(null);
            },
            messageType: 'get',
            messageKey: "LastPriority"
        });
    }

    create() {
        var model = this.selectedRow().toServer();
        if (model === false)
            return model;
        ApiService.request(
            {
                url: "/api/connection/post",
                data: model,
                success: function (data) {
                    if (!_h.isNullOrEmpty(data)) {
                        this.getRecords();
                        this.lastPriority(data.lastPriority);
                        toast.success(this.entityName, 'post');
                    }
                }.bind(this),
                error: function (data) {
                    toast.error(this.entityName, 'post');
                }.bind(this)
            });
    }

    edit() {
        var model = this.selectedRow().toServer(true);
        if (model === false)
            return model;
        ApiService.request(
            {
                url: "/api/connection/put",
                data: model,
                success: function (data) {
                    if (!_h.isNullOrEmpty(data)) {
                        this.getRecords();
                        this.lastPriority(data.lastPriority);
                        toast.success(this.entityName, 'put');
                    }
                }.bind(this),
                error: function (data) {
                    toast.error(this.entityName, 'put');
                }.bind(this)
            });
    }

    deleteBtn(parents, item) {
        if (_h.isNullOrEmpty(item.id())) {
            this.selectedRow(null);
            return;
        }
        var id = item.id();
        ApiService.request(
            {
                url: "/api/connection/delete",
                data: { id: id },
                success: function (data) {
                    if (!_h.isNullOrEmpty(data)) {
                        parents[0].getRecords();
                        parents[0].lastPriority(data.lastPriority);
                        toast.success(parents[0].entityName, 'del');
                    }
                }.bind(this),
                error: function (data) {
                    toast.error(parents[0].entityName, 'del');
                }.bind(this)
            });
    }

    onRowClick(item) {
        if (this.selectedRow() !== null && this.selectedRow() !== undefined)
            this.selectedRow().selected(false);
        item.lastPriority(this.lastPriority());
        this.selectedRow(item);
        item.selected(true);
        item.connectionProperties().getInformation(this.permissions(), item.id());
        this.fixLabelSize();
    }

    fixLabelSize() {
        var modal = $(".modal.in");
        var labels = modal.find(".control-label");
        for (var i = 0; i < labels.length; i++) {
            var label = labels[i];
            var sizes = _h.calDim($(label).text(), "11px", "Iransans", "400");
            $(label).css("width", sizes[1] + 10);
        }
    }

    createForm() {
        this.width = "60%";
        const controls = [
            this.createLine({ t: 'tm', templateName: 'connection-manager-form-t' }, undefined, true, 0, 0)
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    {
                        name: "custom",
                        resText: 'createFormBtn',
                        vis: this.visCreateBtn,
                        click: this.create.bind(this)
                    },
                    {
                        name: "custom",
                        resText: 'editFormBtn',
                        vis: this.visEditBtn,
                        click: this.edit.bind(this)
                    },
                    {
                        name: "custom",
                        resText: 'executeConnction',
                        vis: this.visExecuteBtn,
                        click: this.executeBtn.bind(this)
                    },
                    {
                        name: "tmp",
                        templateName: 'connection-manager-footer-form-t',
                        vis: true,
                        click: null
                    },

                    { name: 'cancel', click: _h.kocnx().closeForm }
                ]
            }
        });
    }
}

export function Connection() {
    var self = this;
    self.selected = ko.observable(false);
    self.editMode = ko.observable(true);
    self.id = ko.observable(undefined);
    self.priority = ko.observable();
    self.lastPriority = ko.observable();
    self.name = ko.observable();
    self.controllerName = 0;
    self.timeCreated = ko.observable();
    self.connectionProperties = ko.observable();
    self.outputType = ko.observable();
    self.properties = ko.observableArray();
    self.resultErrors = ko.observableArray();
    self.resultMode = ko.observable(false);
    self.outputFiles = ko.observableArray();
    self.processItem = ko.observable();
    self.fillEmpty = function (controllerName, priority) {
        self.controllerName = controllerName;
        self.priority(priority + 1);
        self.lastPriority(priority + 1);
    };
    self.fillModel = function (model, lastPriority) {
        self.id(model.id);
        self.name(model.name);
        self.priority(model.priority);
        self.lastPriority(lastPriority);
        self.controllerName = model.controllerName;
        self.timeCreated(model.timeCreated);
        var record = new ModuleConnectionProperties(self);
        record.fillEmpty();
        self.connectionProperties(record);
        self.connectionProperties().fillModel(model.connectionProperties);
    };
    self.downloadFile = function (item) {
        window.open(item.address);
    }
    self.toServer = function (editMode) {
        if (!self.validationObject.isValid()) {
            self.validationObject.errors.showAllMessages();
            return false;
        }
        var model = {
            id: self.id(),
            name: self.name(),
            priority: self.priority(),
            controllerName: self.controllerName,
            timeCreated: self.timeCreated(),
            connectionProperties: null
        };
        if (!self.connectionProperties().validationObject.isValid()) {
            self.connectionProperties().validationObject.errors.showAllMessages();
            return false;
        }
        model.connectionProperties = self.connectionProperties().toServer(editMode);
        if (model.connectionProperties && _h.any(model.connectionProperties.parameters)) {
            model.connectionProperties.parameters = ko.toJS(model.connectionProperties.parameters);
        }
        if (!model.connectionProperties.isValidParameters && self.editMode() === true) {
            return false;
        }
        return model;
    };
    self.getRunProperties = function () {
        if (!self.validationObject.isValid()) {
            self.validationObject.errors.showAllMessages();
            return false;
        }
        if (!self.connectionProperties().validationObject.isValid()) {
            self.connectionProperties().validationObject.errors.showAllMessages();
            return false;
        }
        model.connectionProperties = self.connectionProperties().toServer();
        if (!model.connectionProperties.isValidParameters) {
            return false;
        }
        if (model.connectionProperties && _h.any(model.connectionProperties.parameters)) {
            var validParams = [
                "name",
                "key", "value", "file", "fileType"
            ];
            var data = [];

            for (var i = 0; i < model.connectionProperties.parameters.length; i++) {
                var param = model.connectionProperties.parameters[i];
                var objParam = {};
                for (var l in param) {
                    if (param.hasOwnProperty(l) && validParams.indexOf(l) !== -1) {
                        objParam[l] = param[l]();
                    }
                }
                data.push(objParam);
            }
            model.connectionProperties.parameters = data;
        }
        return {
            connectionId: self.id(),
            parameterValues: model.connectionProperties.parameters
        };
    };
    self.validationObject = ko.validatedObservable({
        name: self.name.extend({
            required: true
        }),
        priority: self.priority.extend({
            required: true
        }),
        connectionProperties: self.connectionProperties
    });
    self.onCancel = function () {
        _h.kocnx().processManagement().cancelBtn(self.processItem);
    }
}

export function ModuleConnectionProperties() {
    var self = this;
    self.executableFileName = ko.observable();
    self.parameters = ko.observableArray();
    self.connectionString = ko.observable();
    self.query = ko.observable();
    self.fillEmpty = function () {
    };
    self.fillModel = function (model) {
        self.executableFileName(model.executableFileName);
        if (_h.any(model.parameters))
            for (var i = 0; i < model.parameters.length; i++) {
                var record = new ConnectionParameter(model.parameters[i]);
                self.parameters.push(record);
                if (model.parameters[i].customSelectSource)
                    record.getSelectData();
            }
    };
    self.toServer = function (editMode) {
        var isValid = true;
        var hasFile = false;
        if (_h.any(self.parameters()))
            for (var i = 0; i < self.parameters().length; i++) {
                var param = self.parameters()[i];
                if (param.require() === true && (_h.isNullOrEmpty(param.value()) || param.value() === "")) {
                    isValid = false;
                    param.error(true);
                } else {
                    param.error(false);
                }
                if (param.parameterType() === 6 && param.isFileValid() === false) {
                    isValid = false;
                    param.error(true);
                } else if (param.parameterType() === 6 && _h.isNullOrEmpty(param.file()) && param.require() === true) {
                    isValid = false;
                    param.error(true);
                } else if (param.parameterType() === 6 && (!_h.isNullOrEmpty(param.file()) || param.require() === false)) {
                    param.error(false);
                    param.fileMessage(undefined);
                }

                if (!_h.isNullOrEmpty(param.file()))
                    hasFile = true;
            }
        return {
            executableFileName: self.executableFileName(),
            parameters: self.parameters(),
            isValidParameters: isValid,
            hasFile: hasFile
        };
    };
    self.validationObject = ko.validatedObservable({
        executableFileName: self.executableFileName.extend({
            required: true
        })
    });
    self.addParameter = function () {
        self.parameters.push(new ConnectionParameter({ key: "", name: "", value: undefined }));
    };
    self.removeParameter = function (item) {
        self.parameters.remove(item);
    };
    self.getInformation = function (permissions, id) {
        for (var i = 0; i < self.parameters().length; i++) {
            if (self.parameters()[i].parameterType() === 6 &&
                permissions.indexOf(3) === -1 && !self.parameters()[i].loadInfo())
                self.parameters()[i].getInfo(id);
        }
    };
}

export function ResultConnectionProperties(model) {
    var self = this;
    self.faName = ko.observable(model.faName);
    self.name = ko.observable(model.name);
    self.parameterType = ko.observable(model.parameterType);
    self.value = ko.observable(model.defaultValue);
    self.selectList = ko.observable(model.selectList);
    self.valueList = ko.observableArray();
    self.require = ko.observable(model.require);
    self.error = ko.observable(false);
    self.outputType = ko.observable(model.outputType);
    self.valueList.subscribe(function (newValue) {
        if (!_h.isNullOrEmpty(newValue)) {
            self.value(newValue);
        }
    });
}

export function ConnectionParameter(model) {
    var self = this;
    self.loadInfo = ko.observable(false);
    self.key = ko.observable(model.key);
    self.name = ko.observable(model.name);
    self.value = ko.observable(model.defaultValue);
    self.selectList = ko.observableArray(model.selectList);
    self.valueList = ko.observableArray();
    self.defaultValueList = ko.observableArray();
    self.parameterType = ko.observable(model.parameterType);
    self.require = ko.observable(model.require);
    self.defaultValue = ko.observable(model.defaultValue);
    self.error = ko.observable(false);
    self.tip = ko.observable(model.tip);
    self.error.subscribe(function (newValue) {
        if (!_h.isNullOrEmpty(newValue)) {
            try {
                if (_h.kocnx().formModel().permissions().indexOf(3) === -1) {
                    setTimeout(
                        function () {
                            self.error(false);
                        }, 5000);
                }
            } catch (e) {
                //
            }
        }
    });
    self.customSelectSource = ko.observable(model.customSelectSource);
    self.toggleRequire = function () {
        self.require(!self.require());
    };
    self.valueList.subscribe(function (newValue) {
        if (!_h.isNullOrEmpty(newValue)) {
            self.value(newValue);
        }
    });
    self.defaultValueList.subscribe(function (newValue) {
        if (!_h.isNullOrEmpty(newValue)) {
            self.defaultValue(newValue);
        }
    });
    self.parameterType.subscribe(function (newValue) {
        if (newValue === 4) {
            if (self.selectList().length === 0)
                self.selectList.push({ text: "", value: "" });
        }
    });
    self.addSelectItem = function () {
        self.selectList.push({ text: "", value: "" });
    };
    self.removeSelectItem = function (item) {
        self.selectList.remove(item);
    };
    self.fileName = ko.observable();
    self.file = ko.observable();
    self.isFileValid = ko.observable();
    self.fileType = ko.observable();
    self.fileMessage = ko.observable();
    self.handleFileChoose = function (files) {
        var file = files;
        var ext = _h.getExtension(file.name);
        self.fileName(file.name);
        switch (ext.toLowerCase()) {
            case "csv":
                self.fileType(0);
                _h.toBase64(file, function (res) {
                    self.file(res);
                });
                self.fileName(file.name);
                self.fileMessage("");
                self.isFileValid(true);
                break;
            case "xls":
                self.fileType(8);
                _h.toBase64(file, function (res) {
                    self.file(res);
                });
                self.fileName(file.name);
                self.fileMessage("");
                self.isFileValid(true);
                break;
            case "xlsx":
                self.fileType(9);
                _h.toBase64(file, function (res) {
                    self.file(res);
                });
                self.fileName(file.name);
                self.fileMessage("");
                self.isFileValid(true);
                break;
            default:
                self.fileType(-1);
                _h.toBase64(file, function (res) {
                    self.file(res);
                });
                self.fileName(file.name);
                self.fileMessage(" فرمت های صحیح فایل " + " xls, xlsx, csv " + "می باشد");
                self.isFileValid(false);
                break;
        }
    };
    self.getSelectData = function () {
        ApiService.request(
            {
                url: "/api/connection/getcustomselectitems",
                data: { procedureName: self.customSelectSource() },
                success: function (data) {
                    self.selectList.removeAll();
                    if (_h.any(data)) {
                        for (var i = 0; i < data.length; i++) {
                            self.selectList.push(data[i]);
                        }
                    }
                },
                error: function (data) {

                }
            });
    };
    self.getInfo = function (id) {
        ApiService.request({
            url: "/api/connection/getconnectioninfo",
            data: { id: id },
            success: function (data) {
                self.selectList.removeAll();
                if (!_h.any(data)) {
                    for (var i = 0; i < data.length; i++) {
                        self.selectList.push(data[i]);
                    }
                }
            },
            error: function (data) {

            }
        });
    };
}

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

export class FolderManagement extends BaseSecondaryForm {
    constructor(viewModel, model) {
        super(viewModel, [
            { name: "parent", type: "", val: viewModel },
            { name: "controllerName", type: "", val: model.controllerName },
            { name: "folders", type: "obar" },
            { name: "tags", type: "obar" }
        ], "folderManagementCaption");

        this.getRecords();
        this.createForm();
    }

    getRecords() {
        ApiService.request(
            {
                url: "getTableInfo",
                data: {
                    controllerName: this.controllerName
                },
                success: function (data) {
                    this.folders.removeAll();
                    this.tags.removeAll();
                    if (_h.any(data.folders))
                        for (var j = 0; j < data.folders.length; j++) {
                            var target = data.folders[j];
                            this.folders.push(new Folder(target));
                        }
                    if (_h.any(data.tags))
                        for (var k = 0; k < data.tags.length; k++) {
                            this.tags.push({ text: data.tags[k], value: data.tags[k] });
                        }
                }.bind(this),
                error: function (data) {
                    toast.error("Folder", 'getList');
                }
            });
    };

    update() {
        var model = {
            controllerName: this.controllerName,
            Folders: ko.toJS(this.folders)
        };
        ApiService.request({
            url: "putfolders",
            data: model,
            success: function (data) {
                if (!_h.isNullOrEmpty(data)) {
                    this.parent.getFolderList();
                    this.parent.getRecords();
                    _h.kocnx().closeForm();
                }
            }.bind(this),
            error: function (data) {
            }
        });
    };

    addFolder() {
        this.folders.push(new Folder({ text: "", value: undefined }));
    };

    removeFolder(item) {
        if (this.folders().length > 0)
            this.folders.remove(item);
    };

    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'folder-management-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: "custom", resText: 'editFormBtn', vis: true, click: this.update.bind(this) },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    };
}

export class ProcessQueue extends BaseSecondaryForm {
    constructor(viewModel) {
        super(viewModel,
            [
                { name: "sign", type: "ob", val: false },
                { name: "hasActiveItem", type: "ob", val: false },
                { name: "showForm", type: "ob", val: false },
                { name: "list", type: "obar" },
                { name: "interval", type: "", val: null }
            ],
            "ongoingOperations");

        this.checkActiveItems = ko.computed(function () {
            var hasActiveProcess = false,
                hasConsolidation = false,
                hasConnection = false,
                hasReportNode = false;

            if (this.list().length > 0)
                for (var i = 0; i < this.list().length; i++) {
                    if ((this.list()[i].processStatus() === 1
                        || this.list()[i].processStatus() === 2
                        || this.list()[i].processStatus() === 6)
                        && (this.list()[i].processType() !== 4 && this.list()[i].processType() !== 3))
                        hasActiveProcess = true;

                    if ((this.list()[i].processStatus() === 1
                        || this.list()[i].processStatus() === 2
                        || this.list()[i].processStatus() === 6)
                        && this.list()[i].processType() === 4)
                        hasReportNode = true;

                    if ((this.list()[i].processStatus() === 1
                        || this.list()[i].processStatus() === 2
                        || this.list()[i].processStatus() === 6)
                        && this.list()[i].processType() === 5)
                        hasConsolidation = true;
                }
            this.hasActiveItem(hasActiveProcess || hasReportNode || hasConsolidation || hasConnection);
            if (hasReportNode || hasConsolidation || hasConnection) {
                this.showForm(false);
            }

        }.bind(this));
    }
    deleteBtn(item) {
        let model = {
            id: item.id()
        };
        var parent = this[0];
        ApiService.request(
            {
                url: "/api/process/delete",
                data: model,
                success: function (data) {
                    parent.list.remove(item);
                    parent.toggleInterval();
                }.bind(this),
                error: function (data) {

                }
            });
    }
    cancelBtn(item) {
        let model = {
            id: item.id()
        };
        var parent = this[0];
        ApiService.request(
            {
                url: "/api/process/putcancel",
                data: model,
                success: function (data) {
                    item.processStatus(2);
                    parent.toggleInterval();
                }.bind(this),
                error: function (data) {

                }
            });
    }
    getData(isFirstLoad, callback) {
        if (window.inCTvm)
            return;
        ApiService.request(
            {
                notShowAjaxLoader: true,
                url: "/api/process/getlist",
                data: "",
                success: function (data) {
                    if (!_h.isNullOrEmpty(data)) {
                        this.list.removeAll();
                        for (var i = 0; i < data.length; i++) {
                            var item;
                            if (isFirstLoad) {
                                if (data[i].processType !== 4) {
                                    item = new ProcessItem(data[i]);
                                    this.list.push(item);
                                }
                            } else {
                                item = new ProcessItem(data[i]);
                                this.list.push(item);
                            }
                        }
                        setTimeout(function () {
                            localStorage.removeItem("ProcessToken");
                        }, 400);
                        callback(true);
                    }
                }.bind(this),
                error: function (data) {
                    callback(false);
                }
            });
    }
    toggleInterval(sign) {
        if (!_h.isNullOrEmpty(this.interval)) {
            clearInterval(this.interval);
        }
        if (this.hasActiveItem()) {
            this.interval = setInterval(function () {
                if (this.hasActiveItem())
                    this.getData(undefined, function () { });
                else
                    clearInterval(this.interval);
            }.bind(this), 1000 * 3);
        }
    }
    init(sign, isFirstLoad) {
        if (!sign) {
            this.openForm();
        }
        this.getData(isFirstLoad, function (res) {
            if (res) {
                this.toggleInterval(sign);
            }
        }.bind(this));
    }
    toggleShowErrors(item) {
        item.showErrors(!item.showErrors());
    }
    toggleShowWarning(item) {
        item.showWarning(!item.showWarning());
    }
    toggleShowOutputFiles(item) {
        item.showOutputFiles(!item.showOutputFiles());
    }
    closeForm() {
        this.showForm(false);
    }
    getActiveItem(type) {
        var item = null;
        if (this.list().length > 0)
            for (var i = 0; i < this.list().length; i++) {
                var target = this.list()[i];
                if ((target.processStatus() === 1 ||
                    target.processStatus() === 2 ||
                    target.processStatus() === 6) &&
                    target.processType() === type)
                    item = target;
            }
        return item;
    }
    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'process-management-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
    openForm() {
        this.showForm(true);
        $(".process-box").draggable({
            scroll: true,
            handle: ".panel-heading"
        });
    }
}

export class ProcessItem extends BaseInnerModel {
    constructor(model) {
        super(null, [
            { name: "id", type: "ob", val: model.id },
            { name: "title", type: "ob", val: model.title },
            { name: "processType", type: "ob", val: model.processType },
            { name: "processStatus", type: "ob", val: model.processStatus },
            { name: "percent", type: "ob", val: model.percent },
            { name: "remainingSeconds", type: "ob", val: model.remainingSeconds },
            { name: "outputFiles", type: "obar", val: model.outputFiles },
            { name: "errors", type: "obar" },
            { name: "warnings", type: "obar" },
            { name: "showErrors", type: "ob", val: false },
            { name: "showWarning", type: "ob", val: false },
            { name: "showOutputFiles", type: "ob", val: false },
            { name: "refresh", type: "ob", val: false },
            { name: "output", type: "ob", val: model.output },
            { name: "input", type: "ob", val: model.input },
        ]);
        if (_h.any(model.errors))
            for (var i = 0; i < model.errors.length; i++) {
                var target = model.errors[i];
                if (target.selfDescriptive) {
                    this.errors.push(target.description);
                } else {
                    var text = _h.getApiMessage(target.code);
                    text = _h.completeError(text, target);
                    this.errors.push(text);
                }
            }
        if (_h.any(model.warnings))
            for (var j = 0; j < model.warnings.length; j++) {
                var warning = model.warnings[j];
                if (warning.selfDescriptive) {
                    this.warnings.push(warning.description);
                } else {
                    var textWarning = _h.getApiMessage(warning.code);
                    textWarning = _h.completeError(textWarning, warning);
                    this.warnings.push(textWarning);
                }
            }
        if (!_h.isNullOrEmpty(model.output))
            this.setOutput(model.output);
    }
    setOutput(list) {
        var context = _h.kocnx();
        switch (this.processType()) {
            case 1:
                if (!_h.isNullOrEmpty(_h.kocnx().ddvm()))
                    _h.kocnx().ddvm().changeCalculateDocumentsStatus(list);
                break;
            case 4:
                if (context.treevm())
                    context.treevm()
                        .nodeReportHandler(this.id(), this.input(), this.output(),
                            this.percent(), this.title(), this.processStatus());
                break;
            case 5:
                if (context.covm())
                    context.covm()
                        .consolidationProcessHandler(this.id(), this.input(), this.output(),
                            this.percent(), this.title(), this.processStatus(), this);
                break;
            case 6:
                var host = "";
                if (context.brvm())
                    host = "brvm";
                if (context.bvm())
                    host = "bvm";
                if (context.tavm())
                    host = "tavm";
                context
                    .connectionProcessHandler(this.id(), this.input(), this.output(),
                        this.percent(), this.title(), this.processStatus(), this, host);
                break;
        }
    }
    downloadFile(m) {
        if (!_h.isEmpty(m.address)) {
            _h.downloadFile(m.address.replace("~", ""));
        } else {
            var file = m.outputFiles()[0];
            _h.downloadFile(file.address.replace("~", ""));
        }
    }
}

export class NodeReportForm extends BaseSecondaryForm {
    constructor(viewModel) {
        super(viewModel,
            [
                { name: "id", type: "ob" },
                { name: "percent", type: "ob" },
                { name: "title", type: "ob" },
                { name: "processStatus", type: "ob" },
                { name: "nodeReportSelects", type: "obar" },
                { name: "reportGroups", type: "obar" },
                { name: "inProgress", type: "ob", val: false },
            ], "nodeReportCaption")
        this.visBtn = ko.pureComputed(function () {
            if (this.inProgress()) {
                _h.adjustModalPosition("60%");
                return false;
            } else {
                _h.adjustModalPosition("");
                return true;
            }
        }.bind(this));
        this.createForm();
    }
    fillReports(list) {
        var activeTab;
        if (_h.any(list))
            for (var i = 0; i < list.length; i++) {
                var target = list[i];
                var oldRecord = false;
                if (_h.any(this.reportGroups()))
                    for (var j = 0; j < this.reportGroups().length; j++) {
                        var old = this.reportGroups()[j];
                        if (old.title() === target.title)
                            oldRecord = old;
                    }
                if (oldRecord) {
                    oldRecord.fillItems();
                    if (target.reportItems.length > 0 && !activeTab)
                        activeTab = oldRecord;
                } else {
                    var newRecord = new ReportGroup(target);
                    this.reportGroups.push(newRecord);
                    if (target.reportItems.length > 0 && !activeTab)
                        activeTab = newRecord;
                }
            }

        if (activeTab)
            activeTab.active(true);
    };
    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'nodereport-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: "custom", resText: 'createFormBtn', vis: this.visBtn, click: this.parentVM.nodeReport },
                    { name: 'cancel', click: this.parentVM.nodeReportCancel }]
            }
        });
    }
}

export class ReportGroup {
    constructor(model) {
        this.randomId = _h.createRandomNumber();
        this.title = ko.observable(model.title);
        this.reportItems = ko.observableArray(model.reportItems);
        this.active = ko.observable(false);
        this.createTagId = ko.pureComputed(function () {
            return this.constructor.name + this.randomId;
        }.bind(this));
    }
    fillItems() {
        this.reportItems(undefined);
    }
}

export class NodeReportSelect {
    constructor(model) {
        this.id = ko.observable(model.value);
        this.title = ko.observable(model.text);
        this.selected = ko.observable(true);
        this.randomId = _h.createRandomNumber();
        this.createTagId = ko.computed(function () {
            return this.constructor.name + this.randomId;
        }.bind(this));
    }
}

export class ReportPreviewColumn extends BaseInnerModel {
    constructor(model) {
        super(model);
    }

    toggleExcluded() {
        if (this.required())
            this.excluded(false);
        else {
            this.excluded(!this.excluded());
        }
    };

    formatName() {
        if (this.required())
            return _h.getLocalizedText(this.name()) + " (ضروری) ";
        return _h.getLocalizedText(this.name());
    };
}

export class ReportPreviewRow extends BaseInnerModel {
    constructor(model, parent) {
        super(null, [
            { name: "parent", type: "", val: parent },
            { name: "excluded", type: "ob", val: false },
            { name: "id", type: "ob", val: model.id },
            {
                name: "horizontalCell",
                type: "ob",
                val: model.horizontalCells.length ? model.horizontalCells[0] : undefined
            },
        ]);
        if (_h.any(model.cells))
            for (var j = 0; j < model.cells.length; j++) {
                var field = model.cells[j];
                this[field.order] = field.value;
            }
        this.visibleHorizontalCell = ko.computed(function () {
            var count = 0;
            for (let i = 0; i < this.parent.columns().length; i++) {
                var col = this.parent.columns()[i];
                if (!col.excluded() && col.isHorizontal()) {
                    count++;
                }
            }
            return count === 1;
        }.bind(this));
    }
}

export class ReportPreview extends BaseSecondaryForm {
    constructor(viewModel, model) {
        super(viewModel, [
            { name: "columns", type: "obar" },
            { name: "rows", type: "obar" },
            { name: "pageOrientation", type: "ob", val: 1 },
            { name: "reportType", type: "ob", val: 1 },
            { name: "controllerName", type: "", val: model.controllerName },
        ], { text: "پیش نمایش" });

        this.visibleColCount = ko.computed(function () {
            var count = 2;
            for (let i = 0; i < this.columns().length; i++) {
                var col = this.columns()[i];
                if (!col.excluded() && !col.isHorizontal()) {
                    count++;
                }
            }
            return count;
        }.bind(this));
        this.configResizeFunctionality();
        if (_h.any(model.columns))
            for (var i = 0; i < model.columns.length; i++) {
                var col = new ReportPreviewColumn(model.columns[i]);
                this.columns.push(col);
            }
        if (_h.any(model.rows))
            for (var j = 0; j < model.rows.length; j++) {
                var row = new ReportPreviewRow(model.rows[j], this);
                this.rows.push(row);
            }
        this.createForm();
    }

    configResizeFunctionality() {
        $('#report-table th.report-column').resizable({
            handles: 'w',
            minWidth: 5,
            _h: "resizable-_h",
            stop: function (event, ui) {
                $(event.target).css("left", 0);
            }
        });
    }

    clickRow(row) {
        row.excluded(!row.excluded());
    }

    clickInnerRow(row, x, m) {
        row.excluded(!row.excluded());
    }

    togglePageOrientation() {
        if (this.pageOrientation() === 1)
            this.pageOrientation(2);
        else
            this.pageOrientation(1);
    }

    toggleReportType() {
        if (this.reportType() === 1)
            this.reportType(2);
        else
            this.reportType(1);
    }

    getColsData() {
        var colsWidth = [];
        var cols = $("#report-table thead th");
        for (var i = 0; i < cols.length; i++) {
            var col = cols[i];
            var name = $(col).attr("data-name");
            var target = this.getColumn(name);
            if (target) {
                var width = $(col).css("width");
                target.width(width);
                target.order(i + 1);
            }
        }
        return colsWidth;
    }

    getColumn(name) {
        var target = null;
        for (let i = 0; i < this.columns().length; i++) {
            var col = this.columns()[i];
            if (name === col.name())
                target = col;
        }
        return target;
    }

    toServer() {
        this.getColsData();
        var excludedRows = [];
        for (var i = 0; i < this.rows().length; i++) {
            if (this.rows()[i].excluded())
                excludedRows.push(this.rows()[i].id());
        }
        return {
            excludedRows: excludedRows,
            input: {},
            pageOrientation: this.pageOrientation(),
            columns: ko.toJS(this.columns()),
            controllerName: this.controllerName,
            reportType: this.reportType()
        };
    }

    createForm() {
        this.width = "80%";
        const controls = [
            this.createLine({ t: 'tm', templateName: 'reportpreview-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: "custom", resText: 'createFileBtn', vis: true, click: this.parentVM.downloadReport },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}

export class FileUploadForm extends FormBuilder {
    constructor(model, parent, schemaMode) {
        super();
        this.width = "600px";
        this.parent = parent;
        this.fileTypeExpect = model.fileType;
        this.id = ko.observable(model.id);
        this.file = ko.observable();
        this.fileName = ko.observable();
        this.fileType = ko.observable();
        if (schemaMode)
            this.schemaMode = ko.observable(schemaMode);
        else
            this.schemaMode = ko.observable(false);

        this.setValidationObject(model.fileType);
        switch (model.fileType) {
            case "Excel":
                this.caption = _h.getLocalizedText("ImportExcelCaption");
                break;
            case "BackUp":
                this.caption = _h.getLocalizedText("ImportBackUpCaption");
                break;
        }
        this.createForm();
    }

    handleFileChoose(files) {
        var file = files;
        this.fileName(file.name);
        var ext = _h.getExtension(file.name);
        _h.toBase64(file, function (res) {
            this.file(res);
        }.bind(this));
        if (this.fileTypeExpect === "Excel") {
            switch (ext) {
                case "xls":
                    this.fileType(8);
                    break;
                case "xlsx":
                    this.fileType(9);
                    break;
                case "csv":
                    this.fileType(0);
                    break;
            }
        }
        if (this.fileTypeExpect === "BackUp") {
            switch (ext) {
                case "dbuf":
                    this.fileType(10);
                    break;
            }
        }
        this.fileName(file.name);
    }

    toServer() {
        return {
            controllerName: _h.findControllerName(this.parent.entityName),
            inputData: {
                id: this.id(),
                fileType: this.fileType(),
                fileTypeExpect: this.fileTypeExpect,
                fileName: this.fileName(),
                file: this.file()
            }
        };
    }

    setValidationObject(fileType) {
        var items = {};
        var self = this;
        switch (fileType) {
            case "Excel":
                items.file = this.file.extend({
                    require: true,
                    checkExcel: { params: [self.fileName] }
                });
                break;
            case "Image":
                items.file = this.file.extend({
                    require: true,
                    checkImage: { params: [self.fileName] }
                });
                break;
            case "BackUp":
                items.file = this.file.extend({
                    require: true,
                    checkBackupFile: { params: self.fileName }
                });
                break;
        }
        this.validationObject = ko.validatedObservable(items);
    }

    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'upload-controlform-t' }, undefined, true, 30, 30),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'create', vis: true, click: _h.kocnx().importFile },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}

export class TableTemplateInfo extends BaseInnerModel {
    constructor(model) {
        super(model);
        this.showContent = ko.observable(false);
    }
}

export class LoginViewModel extends BaseSecondaryForm {
    constructor(viewModel) {
        super(viewModel,
            [
                { name: "isPasswordComplexity", type: "ob" },
                { name: "showCaptcha", type: "ob" },
                { name: "userName", type: "ob", val: _h.kocnx().currentUser().un },
                { name: "password", type: "ob" },
                { name: "captchaStr", type: "ob" }
            ],
            "LoginCaption");

        this.captchaStr.subscribe(function (newValue) {
            if (newValue !== null) {
                if (this.captchaError() !== null)
                    this.captchaError(null);
            }
        }.bind(this));
        this.width = "500px";
        this.minWidth = "500px";
        //this.backgroundColor = true;
        this.showCancel(false);
        this.createForm();
        this.init();
    }
    refreshValidationMessages() {
        this.userName.valueHasMutated();
        this.password.valueHasMutated();
    }

    setValidationObject(complexity, showCaptcha) {
        const obj = {};
        var self = this;
        var min = _h.getSd().pmc;

        obj.userName = self.userName.extend({
            required: true,
            englishOnly: true,
            minLength: 4,
            maxlength: 20
        });
        obj.password = self.password.extend({
            required: true,
            englishOnly: true
        });
        if (showCaptcha)
            obj.captchaStr = self.captchaStr.extend({ required: true });

        self.validationObject = ko.validatedObservable(obj);
    }
    getCaptcha() {
        this.captchaStr(null);
        var root = location.protocol + '//' + location.host;
        const img = document.getElementById("Captcha_Image");
        img.src = root + '/account/getcaptcha' + "?t=" + new Date().getTime();
    }
    login(parents) {
        var loginModel = parents[1];
        if (!loginModel.validationObject.isValid()) {
            loginModel.validationObject.errors.showAllMessages();
            return false;
        }
        let model = {
            userName: loginModel.userName(),
            password: loginModel.password(),
            captcha: loginModel.captchaStr()
        };
        window.inCTvm = true;
        ApiService.request({
            url: "/account/postnewtoken",
            data: model,
            success: function (d) {
                if (_h.isEmpty(d)) {
                    var text = _h.getApiMessage("ErrorUnknownServer");
                    _h.failToast(text);
                    _h.backToLogin();
                    return;
                }
                if ((window.resDomain === "Magazine" && window.resSecondDomain === "pageeditor") || window.resDomain === "TableTemplate")
                    _h.kocnx().changeTvm(d, false);
                else
                    _h.kocnx().changeTvm(d, true);
                $(".modal-back").removeClass("trans-modal-back");
                _h.kocnx().closeForm();
                window.inCTvm = false;
            }.bind(this),
            error: function (status) {
                let text;
                window.inCTvm = false;
                switch (status) {
                    case 552:
                        text = _h.getApiMessage("InvalidUserOrPasswordError");
                        _h.failToast(text);
                        loginModel.showCaptcha(true);
                        loginModel.getCaptcha();
                        loginModel.setValidationObject(true, true);
                        break;
                    case 553:
                    case 558:
                    case 554:
                    case 556:
                    case 557:
                        _h.backToLogin();
                        break;
                    case 559:
                        text = _h.getApiMessage("CaptchaInValid");
                        loginModel.captchaError(text);
                        loginModel.getCaptcha();
                        break;
                    case 560:
                        text = _h.getApiMessage("CaptchaTimeOut");
                        loginModel.captchaError(text);
                        loginModel.getCaptcha();
                        break;
                    case 561:
                        text = _h.getApiMessage("UserHasNoAccessInSystem");
                        _h.failToast(text);
                        break;
                    case 571:
                        text = _h.getApiMessage("CompanyIsNotActive");
                        _h.failToast(text);
                        break;
                    default:
                        text = _h.getApiMessage("ErrorUnknownServer");
                        _h.failToast(text);
                        break;
                }
            }
        });
    }
    init() {
        var res = $(".login-box").attr("data-tag") === "True";
        if (res) {
            this.showCaptcha(true);
            this.getCaptcha();
            this.setValidationObject(true, true);
        } else {
            this.setValidationObject(true, false);
        }
        this.refreshValidationMessages();
        $(".modal-back").addClass("trans-modal-back");
    }
    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'mini-login-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: "custom", resText: 'loginbtn', vis: true, click: this.login }
                ]
            }
        });
    }

}


export class AppConfigForm extends BaseSecondaryForm {

    constructor(viewModel,data) {
        super(viewModel,
            [
                { name: "blockedIpList", type: "obar"},
            ],
            "AppConfigCaption");
        this.pattern = { mask: "999.999.999.999/99", placeholder: "___.___.___.___/__" }; 
        this.mask = ko.observable(this.mask);
        this.placeholder = ko.observable(this.placeholder);
        this.createForm();
        this.init(data);
        this.setValidationObject();
    }

    init(data) {
        if (_h.any(data.blockedIpList))
            for (var i = 0; i < data.blockedIpList.length; i++) {
                var item = data.blockedIpList[i];
                this.blockedIpList.push(new BlockIpAddress(item));
            }
        else
            this.blockedIpList.push(new BlockIpAddress({ id: 0, ip: "" }));

    }

    addIP() {
        this.blockedIpList.push(new BlockIpAddress({ id: 0, ip: "" }));
    }

    removeIP(item) {
        this.blockedIpList.remove(item);
    }

    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'blockedIpList-form-t' }, undefined, true, 30, 0)
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: "custom", resText: 'editFormBtn', vis: true, click: this.parentVM.editAppConfig },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
    setValidationObject() {
        var self = this;
        self.validationObject = ko.validatedObservable({
            blockedIpList: self.blockedIpList
        });
    }
    toServer() {
        return {
            blockedIpList: ko.toJS(this.blockedIpList)
        };
    }
}

export class BlockIpAddress {
    constructor(model) {
        this.id = ko.observable(model.id);
        this.ip = ko.observable(model.ip);
        this.validationObject = ko.validatedObservable({
            ip: this.ip.extend({
                required: true,
                IsValidIpAddress: true
            })
        });
    }
}

export class LoginHistory extends BaseSecondaryForm {
    constructor(viewModel, model) {  
        super(viewModel,
            [
                { name: "lastFailedLogin", type: "ob" },
                { name: "failedLoginCount", type: "ob" },
                { name: "list", type: "obar" }
            ],
            "LoginHistoryCaption");
        this.lastFailedLogin = ko.observable(model.lastFailedLogin);
        this.failedLoginCount = ko.observable(model.failedLoginCount);
        this.list = ko.observableArray(model.models);
        this.createForm();
    }

    createForm() {
        this.width = "40%";
        const controls = [
            this.createLine({ t: 'tm', templateName: 'loginhistory-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}
export class SecurityConfig extends BaseSecondaryForm {
    constructor(viewModel, list) {
        super(viewModel,
            [
                { name: "list", type: "obar" },
                { name: "lastGroup", type: "ob" },
            ],
            "SecurityConfigCaption");
        if (_h.any(list))
            for (let i = 0; i < list.length; i++) {
                var target = list[i];
                var gName = target.groupName;
                if (!this.lastGroup() || this.lastGroup() !== gName)
                    this.lastGroup(gName);
                else
                    this.lastGroup("");
                target.groupName = this.lastGroup();
                var record = new SecurityConfigItem(target);
                this.list.push(record);
            }
        this.createForm();
    }

    createForm() {
        this.width = "40%";
        const controls = [
            this.createLine({ t: 'tm', templateName: 'securityconfig-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: "custom", resText: 'editFormBtn', vis: true, click: this.parentVM.changeSecurityConfig },
                    { name: 'cancel', click: this.parentVM.closeForm }]
            }
        });
    }
}

class SecurityConfigItem {
    constructor(model) {
        this.id = model.id;
        this.groupName = model.groupName;
        this.title = model.title;
        this.description = model.description;
        this.dataType = model.dataType;
        this.value = ko.observable(model.value);
    }
}