module insite.vmiCount {
    "use strict";
    import VmiCountModel = Insite.Catalog.WebApi.V1.ApiModels.VmiCountModel;
    import VmiBinModel = Insite.Catalog.WebApi.V1.ApiModels.VmiBinModel;
    import UploadError = common.UploadError;
    import VmiBinCollectionModel = Insite.Catalog.WebApi.V1.ApiModels.VmiBinCollectionModel;

    export class ImportVmiCountsModalController extends common.BaseUploadController {
        locationId: string;
        vmiBins: VmiBinModel[];
        supportedExtensions = ["csv"];
        uploadInProgress = false;
        startUploadingTime: number;
        uploadServerErrors: string[] = [];
        importErrors = [];
        vmiCounts: VmiCountModel[];
        hasAnyValidationErrors: boolean;
        importSuccessfully: boolean;
        searchFilter: vmiBin.ISearchFilter = {
            sort: "product.shortDescription"
        };
        firstRowHeading = true;

        static $inject = ["$rootScope", "$scope", "productService", "coreService", "settingsService", "vmiCountService", "importVmiCountsModalService", "$timeout", "vmiBinService"];

        constructor(
            protected $rootScope: ng.IRootScopeService,
            protected $scope: ng.IScope,
            protected productService: catalog.IProductService,
            protected coreService: core.ICoreService,
            protected settingsService: core.ISettingsService,
            protected vmiCountService: IVmiCountService,
            protected importVmiCountsModalService: IImportVmiCountsModalService,
            protected $timeout: ng.ITimeoutService,
            protected vmiBinService: vmiBin.IVmiBinService) {
            super($scope, productService, coreService, settingsService);
        }

        $onInit(): void {
            super.$onInit();
            this.importVmiCountsModalService.registerDisplayFunction((data) => {
                this.cleanupUploadData();
                this.badFile = false;
                this.uploadLimitExceeded = false;
                this.locationId = data.locationId;
                this.uploadInProgress = false;
                this.uploadServerErrors.length = 0;
                this.fileName = "";
                this.file = null;
                this.vmiBins = data.vmiBins || this.getAllVmiBins();
                this.coreService.displayModal(angular.element("#import-vmi-counts-modal"));
                this.validateAllRecords = true;
                this.importErrors = [];
                this.hasAnyValidationErrors = false;
                this.vmiCounts = [];
                this.importSuccessfully = false;
                this.coreService.displayModal(
                    angular.element("#import-vmi-counts-modal")
                );
            });
        }

        protected skipFirstCsvRowHeading(row: string[]): boolean {
            const result = row && row.length === 3 && row.every(o => o) && isNaN(parseFloat(row[2]));
            return result;
        }

        protected rowMapper(row: string[]): any {
            return { Name: row[0], binNumber: row[1], currentQty: row[2] };
        }

        resetErrors(): void {
            this.uploadInProgress = false;
            this.errorProducts = [];
            this.importErrors = [];
            this.uploadServerErrors = [];
            this.hasAnyValidationErrors = false;
            this.firstRowHeading = true;
        }

        protected closeModal(): void {
            this.resetErrors();
            this.coreService.closeModal("#import-vmi-counts-modal");
        }

        protected showUploadingPopup() {
            this.uploadInProgress = true;
            this.startUploadingTime = Date.now();
        }

        protected hideUploadingPopup() {
            this.$timeout(() => {
                this.uploadInProgress = false;
            }, Math.max(0, 300 - (Date.now() - this.startUploadingTime)));
        }

        protected uploadProducts(): void {
            this.addVmiCounts();
        }

        processBeforeImporting(): void {
            const erpNumberToIdMap = {};
            for (const product of this.products) {
                if (product.erpNumber) {
                    erpNumberToIdMap[product.erpNumber.toLowerCase()] = product.id;
                }

                if (product.customerName) {
                    erpNumberToIdMap[product.customerName.toLowerCase()] = product.id;
                }
            }

            let regexp = /^\d{0,13}(\.\d{1,5})?$/; // regex for decimal(18,5)
            let index = 1;

            this.importErrors = this.errorProducts.map(error => ({ ...error }));
            for (const item of this.itemsToSearch) {
                index++;
                if (!item.Name) {
                    this.importErrors.push({
                        index: index,
                        name: item.Name,
                        error: UploadError[UploadError.ProductRequired],
                    });
                }

                const vmiBin = this.vmiBins.find((bin) => bin.binNumber.toLowerCase() === item.binNumber.toLowerCase());
                if (vmiBin) {
                    if (item.Name !== vmiBin.product.erpNumber && item.Name) {
                        this.importErrors.push({
                            index: index,
                            name: item.Name,
                            error: UploadError[UploadError.Mismatch],
                        });
                    }

                    if (!item.currentQty?.trim()) {
                        this.importErrors.push({
                        index: index,
                        name: item.Name,
                        error: UploadError[UploadError.CountNotProvided],
                        });
                    } else if(!regexp.test(item.currentQty)){
                        this.importErrors.push({
                            index: index,
                            name: item.Name,
                            error: UploadError[UploadError.WrongType],
                        });
                    } else if (+item.currentQty && item.currentQty < 0) {
                        this.importErrors.push({
                        index: index,
                        name: item.Name,
                        error: UploadError[UploadError.NegativeCount],
                        });
                    } else {
                        const productId = erpNumberToIdMap[item.Name.toLowerCase()];
                        if (vmiBin.id && productId) {
                            this.vmiCounts.push({
                                vmiBinId: vmiBin.id,
                                productId: erpNumberToIdMap[item.Name.toLowerCase()],
                                count: item.currentQty,
                            } as any);
                        }
                    }
                } else {
                    this.importErrors.push({
                        index: index,
                        name: item.Name,
                        error: UploadError[UploadError.BinNotFound],
                    });
                }
            }
            this.importErrors = this.importErrors.sort((a,b) => (a.index < b.index ? -1 : 1));
            this.hasAnyValidationErrors =
            this.importErrors.length > 0 ||
            this.errorProducts.length > 0 ||
            this.uploadServerErrors.length > 0;
        }

        importCounts(): void {
            this.vmiCountService
            .addVmiCountCollection(this.locationId, this.vmiCounts)
            .then(
                () => {
                    this.addVmiCountsCompleted();
                },
                (error: any) => {
                    this.addVmiCountsFailed(error);
                }
            );
        }

        addVmiCounts(): void {
            this.processBeforeImporting();
            if (!this.hasAnyValidationErrors) {
                this.importCounts();
            }
        }

        protected addVmiCountsCompleted(): void {
            this.importSuccessfully = true;
            this.$rootScope.$broadcast("vmi-counts-were-imported");
        }

        protected addVmiCountsFailed(error: any): void {
            if (error && error.message) {
                this.uploadServerErrors = error.message.split("\r\n");
            }
        }

        getAllVmiBins(): void {
            const paginationParam = {
                page: 1,
                pageSize: 9999 // get all vmi bins
            } as PaginationModel;
            this.vmiBinService.getVmiBins(this.locationId, this.searchFilter, paginationParam).then(
                (getVmiBinCollection: VmiBinCollectionModel) => { this.getAllVmiBinsCompleted(getVmiBinCollection); },
                (error: any) => { this.getAllVmiBinsFailed(error); });
        }

        protected getAllVmiBinsCompleted(getVmiBinCollection: VmiBinCollectionModel): void {
            this.vmiBins = getVmiBinCollection.vmiBins;
        }

        protected getAllVmiBinsFailed(error: any): void {
        }
    }

    export interface IImportVmiCountsModalService {
        display(data: any): void;
        registerDisplayFunction(p: (data: any) => void);
    }

    export class ImportVmiCountsModalService extends base.BasePopupService<any> {
        protected getDirectiveHtml(): string {
            return "<isc-import-vmi-counts-modal></isc-import-vmi-counts-modal>";
        }
    }

    angular
        .module("insite")
        .controller("ImportVmiCountsModalController", ImportVmiCountsModalController)
        .service("importVmiCountsModalService", ImportVmiCountsModalService)
        .directive("iscImportVmiCountsModal", () => ({
            restrict: "E",
            replace: true,
            templateUrl: "/PartialViews/Vmi-ImportVmiCountsModal",
            controller: "ImportVmiCountsModalController",
            controllerAs: "vm",
            bindToController: true
        }));
}