import { BaseModel, BaseFormModel, BaseInnerModel, BaseSecondaryForm } from '../master/baseModels.js';
import { ApiService } from "../../util/apiService.js";
import { PeriodSelectItem, Column } from '../master/model.js';
require('knockout.validation');

export class Period extends BaseModel {
    constructor(model) {
        super(model);
        this.styleRowValue = ko.pureComputed(function () {
            if (this.stateType() === 0)
                return 'color: #ccc;';
            if (this.closed())
                return 'color: red;';
            return 'color: black;';
        }, this);
    }
}
export class PeriodForm extends BaseFormModel {
    constructor(model, editMode, copyMode, list) {
        super(model, editMode);
        this.copyMode = ko.observable(copyMode || false);
        this.periodCopyType = ko.observable(0);
        this.periodHistoryItemsMessage = ko.observable();
        this.destinationPeriodId = ko.observable(null);
        this.periodHistoryItems = ko.observableArray();
        this.destinationPeriods = ko.observableArray();
        this.selectList = ko.observableArray();
        this.basePeriodId = ko.observable();
        if (!editMode) {
            this.periodType(0);
            this.endDateAdjust();
        }
        if (copyMode) {
            let selectedRecord = model.getSelectedRecord();
            this.fillCopyModel(selectedRecord.id(), list);
        }
        this.periodState.subscribe(function (newValue) {
            if (newValue !== undefined && newValue !== null) {
                if (this.auditState() >= 0 && newValue >= 0) {
                    this.timeEnd.valueHasMutated();
                    this.timeEnd.isValid();
                }
            }
        }.bind(this));
        this.auditState.subscribe(function (newValue) {
            if (newValue !== undefined && newValue !== null) {
                if (this.periodState() >= 0 && newValue >= 0) {
                    this.timeEnd.valueHasMutated();
                    this.timeEnd.isValid();
                }
            }
        }.bind(this));
        this.timeEnd.subscribe(function (newValue) {
            if (newValue !== undefined && newValue !== null) {
                this.getSelectList(newValue);
            }
        }.bind(this));
        this.isLockDateControl = ko.pureComputed(function () {
            if (this.periodState() === null || this.periodState() === undefined ||
                this.auditState() === null || this.auditState() === undefined) {
                return true;
            } else {
                return this.editMode();
            }
        }, this);
        this.condFirst = ko.pureComputed(function () {
            return this.copyMode() === false || (this.copyMode() === true && this.periodCopyType() === 0)
        }, this);
        this.condSecond = ko.pureComputed(function () {
            return _h.kocnx().currentCompany().irt === false &&
                (this.copyMode() === false || (this.copyMode() === true && this.periodCopyType() === 0)) &&
                !_h.isNullOrEmpty(this.startDate()) && !_h.isNullOrEmpty(this.timeEnd())
        }, this);
        this.condThird = ko.pureComputed(function () {
            return this.copyMode() === true && this.periodCopyType() === 1;
        }, this);
        this.setValidationObject();
        this.createForm();
    }
    fillCopyModel(id, modelList) {
        this.basePeriodId(id);
        this.periodType(0);
        if (_h.any(modelList.dependancies))
            for (let p in modelList.dependancies) {
                if (modelList.dependancies.hasOwnProperty(p)) {
                    let target = modelList.dependancies[p];
                    let rec = new PeriodDependency(target, this);
                    this.periodHistoryItems.push(rec);
                }
            }
        if (_h.any(modelList.destinationPeriods))
            for (let j = 0; j < modelList.destinationPeriods.length; j++) {
                this.destinationPeriods.push(new PeriodSelectItem(modelList.destinationPeriods[j]));
            }
        for (let i = 0; i < this.periodHistoryItems().length; i++) {
            this.periodHistoryItems()[i].assign(true);
        }

    };
    checkDependentList(target) {
        var checkDependents = target.checkDependent;
        var uncheckDependents = target.uncheckDependent;
        if (target.assign()) {
            for (let i = 0; i < this.periodHistoryItems().length; i++) {
                let rec = this.periodHistoryItems()[i];
                if (checkDependents.length > 0 && checkDependents.indexOf(rec.id()) !== -1) {
                    rec.assign(true);
                    rec.disabled(true);
                }
            }
        } else {
            var anyCheck = false;
            for (let i = 0; i < this.periodHistoryItems().length; i++) {
                let record = this.periodHistoryItems()[i];
                if (uncheckDependents.length > 0 && uncheckDependents.indexOf(record.id()) !== -1 && record.assign()) {
                    anyCheck = true;
                }
                if (checkDependents.length > 0 && checkDependents.indexOf(record.id()) !== -1) {
                    var targetId = record.id();
                    var countDependent = 0;
                    for (let j = 0; j < this.periodHistoryItems().length; j++) {
                        let innerRecord = this.periodHistoryItems()[j];
                        if (innerRecord.checkDependent.length > 0 && targetId !== target.id() &&
                            innerRecord.checkDependent.indexOf(targetId) !== -1 && innerRecord.assign()) {
                            countDependent++;
                        }
                    }
                    if (countDependent === 0)
                        record.disabled(false);
                }
            }
            if (anyCheck)
                target.assign(true);
        }
    }
    getSelectList(newValue) {
        ApiService.request(
            {
                url: "/api/period/getparentperiodlist",
                data: {
                    endDate: newValue
                },
                success: function (data) {
                    this.selectList.removeAll();
                    if (_h.any(data))
                        for (let j = 0; j < data.length; j++) {
                            this.selectList.push(new PeriodSelectItem(data[j]));
                        }
                }.bind(this),
                error: function (data) {

                }
            });
    }
    setValidationObject() {
        let self = this;
        self.validationObject = ko.validatedObservable({
            periodState: self.periodState.extend({
                required: {
                    onlyIf: function () { return self.periodCopyType() === 0 || self.copyMode() === false; }
                }
            }),
            periodType: self.periodType.extend({
                required: {
                    onlyIf: function () { return self.periodCopyType() === 0 || self.copyMode() === false; }
                }
            }),
            auditState: self.auditState.extend({
                required: {
                    onlyIf: function () { return self.periodCopyType() === 0 || self.copyMode() === false; }
                }
            }),
            startDate: self.startDate.extend({
                required: {
                    onlyIf: function () {
                        return self.editMode() === false
                            || (self.copyMode() === true && self.periodCopyType() === 0);
                    }
                },
                beforeEndDate: { params: [self.timeEnd] }
            }),
            periodCopyType: self.periodCopyType.extend({
                required: {
                    onlyIf: function () { return self.copyMode() === true; }
                },
            }),
            destinationPeriodId: self.destinationPeriodId.extend({
                required: {
                    onlyIf: function () { return self.periodCopyType() === 1 && self.copyMode() === true; }
                },
            }),
            timeEnd: self.timeEnd.extend({
                required: {
                    onlyIf: function () {
                        return self.editMode() === false
                            || (self.copyMode() === true && self.periodCopyType() === 0);
                    }
                },
                afterStartDate: { params: [self.startDate] },
                onlyOneYearDef: { params: [self.startDate] },
                remoteIsPeriodUniqueValidationRule: { params: [self.id, self.periodState, self.auditState, self.startDate, self.periodType] }
            }),
            groupPeriod: self.groupPeriod.extend({
                required: {
                    onlyIf: function () { return _h.kocnx().currentCompany().irt === false; }
                }
            })
        });
    }
    endDateAdjust() {
        let date = dateHelper.getDateLastDayOfYear();
        this.timeEnd(date);
        ko.validation.registerExtenders();
    }
    toServer() {
        let period = ko.toJS(this);
        delete period["validationObject"];
        delete period["formButtons"];
        delete period["formControls"];
        delete period["parentVM"];
        delete period["editMode"];
        delete period["ad"];
        delete period["selected"];
        delete period["ruleModel"];
        let list = [];
        ko.utils.arrayFilter(this.periodHistoryItems(), function (item) {
            if (item.assign()) {
                list.push(item.id());
            }
        });
        period.periodItems = list;
        period.periodHistoryItems = null;
        if (list.length === 0 && this.copyMode()) {
            this.periodHistoryItemsMessage(_h.getApiMessage("ErrorMinPeriodCopyItem"));
            return null;
        }
        this.periodHistoryItemsMessage("");

        return period;
    };
    createForm() {
        const controls = [
            this.createLine({ t: 'slc', val: this.periodCopyType, options: periodCopyTypes }, undefined, this.copyMode),
            this.createLine({ t: 'slc', val: this.periodState, options: periodStates },
                { t: 'slc', val: this.periodType, options: periodTypes }, this.condFirst, 30),

            this.createLine({ t: 'slc', val: this.auditState, options: auditStates }, undefined, this.condFirst, 30),
            this.createLine({ t: 'dpk', val: this.startDate, dateType: 'fa', dis: this.editMode },
                { t: 'dpk', val: this.timeEnd, dateType: 'fa', dis: this.isLockDateControl }, this.condFirst, 30),
            this.createLine({ t: 'txa', val: this.description }, undefined, this.condFirst, 30),

            this.createLine({ t: 'slc', val: this.groupPeriod, options: this.selectList, dis: this.editMode, renderFunc: _h.periodSelectRowTemplate },
                undefined, this.condSecond, 30),

            this.createLine({ t: 'slc', val: this.destinationPeriodId, options: this.destinationPeriods, renderFunc: _h.periodSelectRowTemplate },
                undefined, this.condThird, 30),

            this.createLine({ t: 'tm', templateName: 'period-history-form-t' }, undefined, true, 30, 30),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'create', vis: !this.editMode() && !this.copyMode(), click: this.parentVM.create },
                    { name: 'edit', vis: this.editMode() === true && !this.copyMode(), click: this.parentVM.edit },
                    { name: 'copy', vis: this.copyMode, click: this.parentVM.copy },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}
export class ComparativePeriodsForm extends BaseSecondaryForm {
    constructor(viewModel, model) {
        super(viewModel, [
            { name: "id", type: "ob", val: model.id },
            { name: "title", type: "ob", val: model.title }
        ], "comparativesCaption");

        if (_h.any(model.comparativePeriods))
            for (var i = 0; i < model.comparativePeriods.length; i++) {
                this[model.comparativePeriods[i].order + "ComparativePeriod"] = ko.observable(model.comparativePeriods[i].id);
            }
        else {
            this["1ComparativePeriod"] = ko.observable(null);
            model.comparativePeriods = [{ order: 1, id: null }]
        }

        this.setValidationObject();
        this.createForm();
    }
    addComparativePeriods() {
        var order = this.getLastOrder() + 1;
        if (order > 15)
            return;
        this[order + "ComparativePeriod"] = ko.observable(null);
        this.formControls.push(this.createLine({
            t: 'slc', val: this[order + "ComparativePeriod"],
            options: this.parentVM.filteredSelectList, renderFunc: _h.periodSelectRowTemplate, hlp: "secondComparativePeriodHelp"
        }, null, true, 40));
        this.setValidationObject();
    }
    getLastOrder() {
        var number = 0;
        for (const key of Object.keys(this)) {
            const char = key.slice(0, 2);
            var numb = char.match(/\d/g);
            if (numb && numb.length) {
                var number = parseFloat(char.replace(/[^0-9]/g, ''));
            }
        }
        return number;
    }
    getComparativePeriodsList() {
        var array = [];
        var order = this.getLastOrder();
        for (var f = 0; f < order; f++) {
            array.push({ order: f + 1, id: this[(f + 1) + "ComparativePeriod"]() });
        }
        return array;
    }
    setValidationObject() {
        var self = this;
        var obj = {};
        self.validationObject = ko.validatedObservable(obj);
        var comparativePeriods = this.getComparativePeriodsList();
        for (var i = 0; i < comparativePeriods.length; i++) {
            var params = [];
            for (var j = 0; j < comparativePeriods.length; j++) {
                if (comparativePeriods[j].order !== comparativePeriods[i].order) {
                    params.push(self[comparativePeriods[j].order + "ComparativePeriod"]);
                }
            }
            if (i === comparativePeriods.length - 1) {
                obj[comparativePeriods[i].order + "ComparativePeriod"] = self[comparativePeriods[i].order + "ComparativePeriod"].extend({
                    validation: {
                        validator: function (val, someOtherVal) {
                            var count = 0;
                            var order = self.getLastOrder();
                            for (var f = 0; f < order; f++) {
                                var cpVal = self[(f + 1) + "ComparativePeriod"]();
                                if (!_h.isEmpty(cpVal) && cpVal > 0) {
                                    count = count + 1;
                                }
                            }
                            if (count > 0 || val > 0)
                                return true;
                            return false;
                        },
                        message: 'حداقل یکی از دوره های مقایسه باید انتخاب شده باشد'
                    },
                    noEqualPeriod: {
                        params: params
                    }
                });
            }
            else {
                obj[comparativePeriods[i].order + "ComparativePeriod"] = self[comparativePeriods[i].order + "ComparativePeriod"].extend({
                    noEqualPeriod: {
                        params: params
                    }
                });
            }
        }
        self.validationObject = ko.validatedObservable(obj);
    }
    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'comparative-title-form-t' }, undefined, true, 30, 0),
        ];
        for (const key of Object.keys(this)) {
            const char = key.slice(0, 2);
            var numb = char.match(/\d/g);
            if (numb && numb.length) {
                var number = parseFloat(char.replace(/[^0-9]/g, ''));
                var hlp = "firstComparativePeriodHelp";
                if (number > 1) {
                    hlp = "secondComparativePeriodHelp";
                }
                controls.push(this.createLine({
                    t: 'slc', val: this[key],
                    options: this.parentVM.filteredSelectList, renderFunc: _h.periodSelectRowTemplate, hlp: hlp
                },
                    null, true, 40));
            }
        }

        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'custom', resText: "comparativesEditBtn", vis: true, click: this.parentVM.editComparatives },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
    toServer() {
        var list = this.getComparativePeriodsList();
        return {
            id: this.id(),
            comparativePeriods: list
        };
    }
}
export class PeriodDeleteForm extends BaseSecondaryForm {
    constructor(viewModel, model, list) {
        super(viewModel, [
            { name: "id", type: "ob", val: model.id() },
            { name: "title", type: "ob", val: model.title() },
            { name: "list", type: "obar" },
        ], { text: 'حذف ' + model.title() });

        for (var p in list) {
            if (list.hasOwnProperty(p)) {
                var target = new PeriodDependency(list[p], this);
                this.list.push(target);
            }
        }
        this.createForm();
    }
    checkDependentList(target) {
        var checkDependents = target.checkDependent;
        var uncheckDependents = target.uncheckDependent;
        if (target.assign()) {
            for (let i = 0; i < this.list().length; i++) {
                let rec = this.list()[i];
                if (checkDependents.length > 0 && checkDependents.indexOf(rec.id()) !== -1) {
                    rec.assign(true);
                    rec.disabled(true);
                }
            }
        } else {
            var anyCheck = false;
            for (let i = 0; i < this.list().length; i++) {
                let rec = this.list()[i];
                if (uncheckDependents.length > 0 && uncheckDependents.indexOf(rec.id()) !== -1 && rec.assign()) {
                    anyCheck = true;
                }
                if (checkDependents.length > 0 && checkDependents.indexOf(rec.id()) !== -1) {
                    var targetId = rec.id();
                    var countDependent = 0;
                    for (let j = 0; j < this.list().length; j++) {
                        let innerRecord = this.list()[j];
                        if (innerRecord.checkDependent.length > 0 && targetId !== target.id() &&
                            innerRecord.checkDependent.indexOf(targetId) !== -1 && innerRecord.assign()) {
                            countDependent++;
                        }
                    }
                    if (countDependent === 0)
                        rec.disabled(false);
                }
            }
            if (anyCheck)
                target.assign(true);
        }
    }
    toServer() {
        var array = [];
        for (let i = 0; i < this.list().length; i++) {
            let rec = this.list()[i];
            if (rec.assign()) {
                array.push(rec.id());
            }
        }
        return {
            id: this.id(),
            items: array
        };
    }
    createForm() {
        const controls = [
            this.createLine({ t: 'tm', templateName: 'delete-content-form-t' }, undefined, true, 0, 0),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'custom', resText: "deletePeriodCaption", vis: true, click: this.parentVM.delete },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }
}
export class PeriodDependency extends BaseInnerModel {
    constructor(model, parent) {
        super(model);
        this.parent = parent;
        this.checkDependent = model.checkDependent;
        this.uncheckDependent = model.uncheckDependent;
        this.assign = ko.observable(false);
        this.disabled = ko.observable(false);
        this.assign.subscribe(function (newValue) {
            if (newValue !== undefined && newValue !== null) {
                this.parent.checkDependentList(this);
            }
        }.bind(this));
    }
}
export class SendPeriodForm extends BaseSecondaryForm {
    constructor(viewModel, model) {
        super(viewModel, [
            { name: "magazineFileId", type: "ob", val: model.submittedMagazine },
        ], "sendPeriodInfo");
        this.magazines = ko.observableArray();
        this.getList(model.id);
        this.setValidationObject();
        this.createForm();
    }

    setValidationObject() {
        var self = this;
        self.validationObject = ko.validatedObservable({
            magazineFileId: self.magazineFileId.extend({
                required: true
            })
        });
    }
    getList(id) {
        ApiService.request({
            url: "/api/period/getSavedMagazines",
            data: { id: id },
            success: function (list) {
                var inList = false;
                if (this.magazineFileId() && list.length)
                    for (var i = 0; i < list.length; i++) {
                        if (list[i].value === this.magazineFileId()) {
                            inList = true;
                        }
                    }
                if (!inList) this.magazineFileId(null);
                this.magazines(list);
            }.bind(this),
            error: function () {
                toast.error("Period", 'getList', 'SavedMagazines');
            }
        });
    }
    createForm() {
        const controls = [
            this.createLine({ t: 'slc', val: this.magazineFileId, options: this.magazines },
                null, true, 30),
        ];
        this.formControls(controls);
        this.formButtons({
            name: 'footer-form-t', data: {
                buttons: [
                    { name: 'custom', resText: "SendFormBtn", vis: true, click: this.parentVM.send },
                    { name: 'cancel', click: _h.kocnx().closeForm }]
            }
        });
    }

}
export function HistoryViewModel() {
    var self = this;
    self.records = ko.observableArray();
    self.tableProperties = ko.observableArray();
    self.grecords = ko.observableArray();
    self.gtableProperties = ko.observableArray();
    self.periodId = ko.observable();
    self.showHistory = ko.observable(true);
    self.showGroupHistory = ko.observable(true);
    self.getRecords = function () {
        ApiService.request(
            {
                url: "/api/period/gethistory",
                data: { id: self.periodId() },
                success: function (data) {
                    self.records.removeAll();
                    self.grecords.removeAll();
                    if (!_h.isNullOrEmpty(data)) {
                        if (_h.any(data.closingHistory)) {
                            for (var j = 0; j < data.closingHistory.length; j++) {
                                var closingHistory = data.closingHistory[j];
                                self.records.push(new History(closingHistory));
                            }
                        }
                        if (_h.any(data.submitHistory)) {
                            for (var i = 0; i < data.submitHistory.length; i++) {
                                var submitHistory = data.submitHistory[i];
                                self.grecords.push(new History(submitHistory));
                            }
                        }
                    }
                    _h.fixLabelsSize();
                },
                error: function (data) {
                    var text = _h.getApiMessage("errorLoadHistoryPeriod");
                    _h.failToast(text);
                }
            });
    }
    self.init = function () {
        for (var p in periodhistoryModelRes) {
            if (periodhistoryModelRes.hasOwnProperty(p)) {
                var target1 = periodhistoryModelRes[p];
                if (!target1.onlyGroup && target1.tablecol) {
                    self.tableProperties.push(new Column(target1));
                }
            }
        }
        for (var g in periodhistoryModelRes) {
            if (periodhistoryModelRes.hasOwnProperty(g)) {
                var target = periodhistoryModelRes[g];
                if (target.tablecol)
                    self.gtableProperties.push(new Column(target));

            }
        }
        self.getRecords();
    }
}
export class History extends BaseModel {
    constructor(model) {
        super(model);
    }
}
