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

    export class ImportVmiBinsModalController extends common.BaseUploadController {
        locationId: string;
        uploadInProgress = false;
        startUploadingTime: number;
        uploadServerErrors: string[] = [];
        importErrors = [];
        dataToImport: VmiBinModel[];
        importSuccessfully: boolean;
        hasAnyValidationErrors: boolean;
        vmiBins: VmiBinModel[];
        firstRowHeading = true;

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

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

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

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

        protected rowMapper(row: string[]): any {
            return { Name: row[0], binNumber: row[1], minQty: row[2], maxQty: row[3], lastCountQty: row[4] };
        }

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

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

        protected cancelImport(): void {
            this.resetErrors();
        }

        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(popupSelector?: string): void {
            this.addVmiBins();
        }

        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})?$/;
            let index = 0;
            this.importErrors = this.errorProducts.map(error => ({ ...error }));
            for (const item of this.itemsToSearch) {
                index++;
                const productId = erpNumberToIdMap[item.Name.toLowerCase()];
                if(!productId){
                    continue;
                }

                const binNumber = item.binNumber ?? item.Name;
                const vmiBin = this.vmiBins.find((bin) => bin.binNumber === binNumber);

                if (vmiBin) {
                  this.importErrors.push({
                    index: index,
                    error: UploadError[UploadError.Existed],
                    name: item.Name,
                    object: {name: item.Name, binNumber: binNumber}
                  });
                } else if (item.minQty < 0) {
                  this.importErrors.push({
                    index: index,
                    error: UploadError[UploadError.NegativeCount],
                    name: item.Name,
                  });
                } else if ((+item.minQty || 0) > (+item.maxQty || 0)) {
                  this.importErrors.push({
                    index: index,
                    error: UploadError[UploadError.MinBigerMax],
                    name: item.Name,
                  });
                } else if (item.lastCountQty < 0) {
                    this.importErrors.push({
                        index: index,
                        error: UploadError[UploadError.BinNegativeCount],
                        name: item.Name,
                    });
                } else if (item.lastCountQty && !regexp.test(item.lastCountQty)) {
                    this.importErrors.push({
                        index: index,
                        name: item.Name,
                        error: UploadError[UploadError.WrongType],
                    });
                } else if (item.binNumber && item.binNumber.length > 25) {
                  this.importErrors.push({
                    index: index,
                    error: UploadError[UploadError.Over25Chars],
                    name: item.Name,
                    object: {name: item.Name, binNumber: binNumber}
                  });
                } else {
                  this.dataToImport.push({
                    productId: productId,
                    binNumber: item.binNumber,
                    minimumQty: +item.minQty || 0,
                    maximumQty: +item.maxQty || 0,
                    lastCountQty: +item.lastCountQty || 0,
                  } as any);
                }
            }
            this.hasAnyValidationErrors = this.importErrors.length > 0 || this.uploadServerErrors.length > 0;
        }

        importVmiBins(): void{
            this.vmiBinService.addVmiBinCollection(this.locationId, this.dataToImport).then(
                (vmiBinCollectionModel: VmiBinCollectionModel) => { this.addVmiBinsCompleted(); },
                (error: any) => { this.addVmiBinsFailed(error); });
        }

        addVmiBins(): void {
            this.processBeforeImporting();
            if (!this.hasAnyValidationErrors) {
                this.importVmiBins();
            }
        }

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

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

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

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

    angular
        .module("insite")
        .controller("ImportVmiBinsModalController", ImportVmiBinsModalController)
        .service("importVmiBinsModalService", ImportVmiBinsModalService)
        .directive("iscImportVmiBinsModal", () => ({
            restrict: "E",
            replace: true,
            templateUrl: "/PartialViews/Vmi-ImportVmiBinsModal",
            controller: "ImportVmiBinsModalController",
            controllerAs: "vm",
            bindToController: true
        }));
}