import { OnInit, OnDestroy, Component, ViewEncapsulation, TemplateRef } from "@angular/core";
import { takeUntil, finalize } from "rxjs/operators";
import { IUserAccount, Page, Pagination, GenericResponse, GenericStatus, IResource } from "../../../../../shared/models";
import { AppData } from "../../../../../app.data";
import { NgbModalRef, NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { Cubicle } from "../../../../../shared/entities/cubicle";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { ApiResources, UtilHelper } from "../../../../../shared/helpers";
import { HttpService, NotifyService, ResourceService } from "../../../../../shared/services";
import { WhiteSpaceValidator } from "../../../../../shared/validators";

class TrackBy {
    role(item: Cubicle) {
        return item.cubicleId;
    }
}
class FilterOptions {
    cubicleName: string = null;
    cubicleId: number;
    assign: number = null;
    locationId?: number = null;
}
class Filters {
    options: FilterOptions;
    applied: boolean;
    constructor() {
        this.init();
    }

    init() {
        this.options = new FilterOptions();
        this.applied = undefined;
    }
}

    @Component({
        templateUrl: "./cubicle.html",
        encapsulation: ViewEncapsulation.None
    })

export class CubiclePage implements OnInit, OnDestroy {

    page: Page;
    filters: Filters;
    trackBy: TrackBy;
    modalRef: NgbModalRef;
    submitting: boolean;
    submitted: boolean;
    cubicleRecords: Array<Cubicle>;
    loading: boolean;
    cubicleForm: FormGroup;
    pagination: Pagination;
    request: any;
    loadingstatus: boolean;
    activeStatus: Array<IResource>;
    filteredcubicleNames = [];
    locations: Array<IResource>;

    constructor(
        private readonly appData: AppData,
        private readonly formBuilder: FormBuilder,
        private readonly httpService: HttpService,
        private readonly modalService: NgbModal,
        private readonly notifyService: NotifyService,
        private readonly resourceService: ResourceService) {
        this.loading = true;
        this.page = new Page();
        this.filters = new Filters();
        this.trackBy = new TrackBy();
        this.loading = true;
        this.initPagination();
    }

    private initPagination() {
        this.pagination = new Pagination();
        this.pagination.pageIndex = 1;
        this.pagination.pageSize = 10;
    }

    onNextPage() {
        $("body,html").animate({ scrollTop: 0 });
        this.fetchCubicles();
    }

    onApplyFilters() {
        this.filters.applied = UtilHelper.isFiltersApplied(this.filters.options);
        this.loading = true;
        this.initPagination();
        this.fetchCubicles();
        this.onCloseFilters();
    }

    onCloseFilters() {
        $("body").removeClass("right-bar-enabled");
    }

    onResetFilters() {
        this.loading = true;
        this.filters.init();
        this.initPagination();
        this.fetchCubicles();
        this.onCloseFilters();
    }

    fetchCubicles() {
        this.loading = true;
        const request = {
            ...this.pagination,
            ...this.filters.options
        };
        this.httpService.post(ApiResources.getURI(ApiResources.cubicles.base, ApiResources.cubicles.fetch), request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.cubicleRecords = response.data;
                        this.cubicleRecords.forEach(x => {
                            if (x.providerId > 0) {
                                x.activeStatusName = "Assigned";
                            }
                            else if (x.providerId == null) {
                                x.activeStatusName = "Unassigned";
                            }
                        });
                        UtilHelper.applyPagination(this.cubicleRecords, this.pagination);
                    }
                },
            );
    }

    private filterCubicles() {
        this.loading = true;
        const request = {};
        this.httpService.post(ApiResources.getURI(ApiResources.cubicles.base, ApiResources.cubicles.fetch), request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.loading = false))
            .subscribe(
                (response: GenericResponse) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.filteredcubicleNames = response.data;
                    }
                },
            );
    }

    private fetchactiveStatus() {
        this.loadingstatus = true;
        this.resourceService.activeStatus()
            .pipe(finalize(() => { this.loadingstatus = false }))
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.activeStatus = response;
            });
    }

    private fetchLocations() {
        this.resourceService.locations()
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((response: Array<IResource>) => {
                this.locations = response;
            });
    }

    onSubmit() {
        this.submitted = true;
        if (this.cubicleForm.invalid) {
            return;
        }
        this.submitting = true;
        this.request = {
            ...this.cubicleForm.getRawValue(),
            createdBy: this.page.userAccount.accountId,
            createdByName: this.page.userAccount.fullName,
            loginRoleId: this.page.userAccount.roleId,
            logFrom: this.page.userAccount.roleId,
            /*locationId: this.page.userAccount.locationId,*/
            locationName: this.page.userAccount.locationName,
        };
        if (this.request.locationId == null) {
            this.request.locationId = this.page.userAccount.locationId;
        }
        let url = ApiResources.getURI(ApiResources.cubicles.base, ApiResources.cubicles.insert);
        if (this.request["cubicleId"] > 0) {
            this.request = {
                ...this.cubicleForm.getRawValue(),
                modifiedBy: this.page.userAccount.accountId,
                logFrom: this.page.userAccount.roleId,
                modifiedByName: this.page.userAccount.fullName,
            };
            url = ApiResources.getURI(ApiResources.cubicles.base, ApiResources.cubicles.update);
        }
        this.httpService.post(url, this.request)
            .pipe(takeUntil(this.page.unSubscribe))
            .pipe(finalize(() => this.submitted = this.submitting = false))
            .subscribe(
                (response: any) => {
                    if (response.status === GenericStatus[GenericStatus.Success]) {
                        this.notifyService.successToast(`Record ${this.request["cubicleId"] > 0 ? 'updated' : 'added'} successfully.`);
                    }
                    if (response === -1) {
                        this.notifyService.warningToast("This cubicle already exists.");
                        return;
                    }
                    if (response.status === GenericStatus[GenericStatus.Info]) {
                        this.notifyService.warningToast(response.message);
                    }
                    this.onCloseModal();
                    this.fetchCubicles();
                    this.filterCubicles();
                },
            );
    }

    onDeleteDepartment(cubicle: Cubicle) {
        this.notifyService.delete(() => {
            this.httpService
                .post(ApiResources.getURI(ApiResources.cubicles.base, ApiResources.cubicles.delete), {
                    cubicleId: cubicle.cubicleId, modifiedByName: this.page.userAccount.fullName,
                    createdBy: this.page.userAccount.accountId,
                    modifiedBy: this.page.userAccount.accountId,
                    name: cubicle.name
                })
                .pipe(takeUntil(this.page.unSubscribe))
                .subscribe(
                    (response: GenericResponse) => {
                        if (response.status === GenericStatus[GenericStatus.Success]) {
                            this.notifyService.successToast("Cubicle deleted successfully.");
                            this.fetchCubicles();
                            this.filterCubicles();
                        }
                        else if (response.status === GenericStatus[GenericStatus.Error]) {
                            if (response.message.includes("violates foreign key constraint")) {
                                this.notifyService.warningToast("Cubicle can't be deleted. Please contact Administrator.");
                            }
                        }
                        else if (response.status === GenericStatus[GenericStatus.Info]) {
                            this.notifyService.warningToast("Cubicle which is assigned cannot be deleted.");
                        }
                    });
        });
    }

    private buildForm() {
        this.cubicleForm = this.formBuilder.group({
            cubicleId: 0,
            name: [null, [Validators.required, Validators.maxLength(250), WhiteSpaceValidator.isValid]],
            /*activeStatusId: [null, [Validators.required]],*/
            locationId: [null, [Validators.required]]
        });
    }
    onOpenModel(content: TemplateRef<any>, record?: Cubicle) {
        this.buildForm();
        if (record) {
            this.cubicleForm.patchValue({
                cubicleId: record.cubicleId,
                name: record.name,
                /*activeStatusId: record.activeStatusId,*/
                locationId: record.locationId
            });
        }
        this.modalRef = this.modalService.open(content, {
            backdrop: "static",
            keyboard: false,
            centered: false,
            windowClass: "custom-modal effect-scale"
        });
    }
    get form() { return this.cubicleForm.controls; }
    onCloseModal() {
        try {
            this.modalRef.close();
            this.modalRef = undefined;
        } catch (e) {
            // ignored;
        }

        this.loading = false;
        this.submitting = undefined;
        this.submitted = undefined;
    }

    ngOnDestroy() {
        this.onCloseModal();
        this.page.unsubscribeAll();
    }

    ngOnInit() {
        this.appData.userAccount
            .pipe(takeUntil(this.page.unSubscribe))
            .subscribe((userAccount: IUserAccount) => {
                if (userAccount) {
                    this.page.userAccount = userAccount;
                    this.filterCubicles();
                    this.fetchCubicles();
                    this.fetchLocations();
                    this.fetchactiveStatus();
                } else {
                    this.page.userAccount = undefined;
                }
            });
    }

}