import { Component, ElementRef, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { ModalDialogOptions, ModalDialogService, RouterExtensions } from '@nativescript/angular';
import { EventData, TextField } from '@nativescript/core';
import { action } from '@nativescript/core/ui/dialogs';
import { Select, Store } from '@ngxs/store';
import { FeedbackType } from 'nativescript-feedback';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs/operators';
import { ModalDatePickerComponent } from '../../components/modal-view-date-picker/modal-view-date-picker.component';
import { PurchaseTypeAllOutput } from '../../entities/output/purchaseTypeAllOutput';
import { WarehouseAllOutput } from '../../entities/output/warehouseAllOutput';
import { WarehouseItemCategoryAllOutput } from '../../entities/output/warehouseItemCategoryAllOutput';
import { WarehouseItemDetailOutput } from '../../entities/output/warehouseItemDetailOutput';
import { WarehouseItemUpdateOutput } from '../../entities/output/warehouseItemUpdateOutput';
import {
    CreateItemUpdate,
    LoadItemDetail,
    LoadPurchaseTypeAll,
    LoadWarehouseAll,
    LoadWarehouseItemCategoryAll
} from '../../state-mgmt/material-update.action';
import { MaterialUpdateState } from '../../state-mgmt/material-update.state';
import { feedbackMessage } from '../../utils/feedback-messages';
import { czechStringfromDate, dateFromCzechString } from '../../utils/myFunctions';

@Component({
    selector: 'MaterialUpdate',
    moduleId: module.id,
    templateUrl: './material-update.component.html',
    styleUrls: ['./material-update.component.scss']
})

export class MaterialUpdateComponent implements OnInit {
    @ViewChild('name', { static: true }) name: ElementRef;
    @ViewChild('warehouse', { static: true }) warehouse: ElementRef;
    @ViewChild('category', { static: true }) category: ElementRef;
    @ViewChild('inventoryNumber', { static: true }) inventoryNumber: ElementRef;
    @ViewChild('description', { static: true }) description: ElementRef;
    @ViewChild('actualPrice', { static: true }) actualPrice: ElementRef;
    @ViewChild('note', { static: true }) note: ElementRef;
    @ViewChild('commercialRent', { static: true }) commercialRent: ElementRef;
    @ViewChild('unitRent', { static: true }) unitRent: ElementRef;
    @ViewChild('eventRent', { static: true }) eventRent: ElementRef;
    @ViewChild('rentPrice', { static: true }) rentPrice: ElementRef;
    @ViewChild('rentNote', { static: true }) rentNote: ElementRef;
    @ViewChild('purchaseType', { static: true }) purchaseType: ElementRef;
    @ViewChild('purchaseDate', { static: true }) purchaseDate: ElementRef;
    @ViewChild('purchaseNote', { static: true }) purchaseNote: ElementRef;
    @ViewChild('serialNumber', { static: true }) serialNumber: ElementRef;
    @ViewChild('accountNumber', { static: true }) accountNumber: ElementRef;
    @ViewChild('purchasePrice', { static: true }) purchasePrice: ElementRef;

    @Select(MaterialUpdateState.getWarehouseItemDetail) item$: Observable<WarehouseItemDetailOutput>;
    @Select(MaterialUpdateState.getWarehouses) warehouses$: Observable<WarehouseAllOutput[]>;
    @Select(MaterialUpdateState.getItemCategories) itemCategories$: Observable<WarehouseItemCategoryAllOutput[]>;
    @Select(MaterialUpdateState.getPurchaseTypes) purchaseTypes$: Observable<PurchaseTypeAllOutput[]>;
    @Select(MaterialUpdateState.getItemUpdate) itemUpdate$: Observable<WarehouseItemUpdateOutput>;
    @Select(MaterialUpdateState.isLoading) isLoading$: Observable<boolean>;
    warehouses: WarehouseAllOutput[];
    // chosenWarehouse: WarehouseAllOutput;
    itemCategories: WarehouseItemCategoryAllOutput[];
    // chosenCategory: WarehouseItemCategoryAllOutput;
    purchaseTypes: PurchaseTypeAllOutput[];
    // chosenPurchaseType: PurchaseTypeAllOutput;
    itemUpdate: WarehouseItemUpdateOutput;
    item: WarehouseItemDetailOutput;
    mainExpanded: boolean;
    rentExpanded: boolean;
    purchaseExpanded: boolean;
    canBeRent: boolean;
    othersIsLoading: boolean;

    constructor(
        private router: Router,
        private route: ActivatedRoute,
        private routerExtensions: RouterExtensions,
        private store: Store,
        private modalService: ModalDialogService,
        private viewContainerRef: ViewContainerRef
    ) {
        this.mainExpanded = true;
        this.rentExpanded = false;
        this.purchaseExpanded = false;
        this.router.events.subscribe((val) => {
            if (val instanceof NavigationEnd) {
                if (RegExp('\/material\/materialUpdate\/[0-9]+\/[0-9]+\/[^/]+\/[^/]+').test(this.router.url)) {
                    this.othersIsLoading = false;
                }
            }
        });
    }

    ngOnInit(): void {
        this.othersIsLoading = false;
        this.store.dispatch(new LoadItemDetail(this.route.snapshot.params['id']))
            .pipe(withLatestFrom(this.item$))
            .subscribe(([_, item]) => {
                this.item = item;
                this.fillTextFields(this.item);

            }, err => {
                feedbackMessage(FeedbackType.Error, 'Načtení detailu položky', 'Nepodařilo se načíst detail položky.');
                console.log(err);
            });
        this.store.dispatch(new LoadWarehouseAll())
            .pipe(withLatestFrom(this.warehouses$))
            .subscribe(([_, warehouses]) => {
                this.warehouses = warehouses;
                this.warehouse.nativeElement.text = this.warehouses.find(obj => obj.ID === this.route.snapshot.params['idWarehouse']).DisplayName;

            }, err => {
                feedbackMessage(FeedbackType.Error, 'Načtení skladů', 'Nepodařilo se načíst sklady.');
                console.log(err);
            });
        this.store.dispatch(new LoadWarehouseItemCategoryAll())
            .pipe(withLatestFrom(this.itemCategories$))
            .subscribe(([_, categories]) => {
                this.itemCategories = categories;
                this.category.nativeElement.text = this.itemCategories.find(obj => obj.ID === this.route.snapshot.params['idCategory']).DisplayName;
            }, err => {
                feedbackMessage(FeedbackType.Error, 'Načtení categorií', 'Nepodařilo se načíst kategorie.');
                console.log(err);
            });
        this.store.dispatch(new LoadPurchaseTypeAll())
            .pipe(withLatestFrom(this.purchaseTypes$))
            .subscribe(([_, purchaseTypes]) => {
                this.purchaseTypes = purchaseTypes;

                if (purchaseTypes) {
                    this.purchaseType.nativeElement.text = this.route.snapshot.params['idPurchaseType']
                        ? this.purchaseTypes.find(obj => obj.ID === this.route.snapshot.params['idPurchaseType']).DisplayName
                        : '';
                }
            }, err => {
                feedbackMessage(FeedbackType.Error, 'Načtení typů pořízení', 'Nepodařilo se načíst typy pořízení.');
                console.log(err);
            });
        this.canBeRent = this.commercialRent.nativeElement.checked || this.unitRent.nativeElement.checked || this.eventRent.nativeElement.checked;

    }

    fillTextFields(item: WarehouseItemDetailOutput) {
        this.name.nativeElement.text = item.DisplayName ? item.DisplayName : '';
        this.inventoryNumber.nativeElement.text = item.InventoryNumber ? item.InventoryNumber : '';
        this.description.nativeElement.text = item.Description ? item.Description : '';
        this.actualPrice.nativeElement.text = item.ActualPrice ? +item.ActualPrice : '';
        this.note.nativeElement.text = item.Note ? item.Note : '';
        this.commercialRent.nativeElement.checked = item.CommercialRent;
        this.unitRent.nativeElement.checked = item.UnitRent;
        this.eventRent.nativeElement.checked = item.EventRent;
        this.rentPrice.nativeElement.text = item.RentPrice ? +item.RentPrice : '';
        this.rentNote.nativeElement.text = item.RentNote ? item.RentNote : '';
        this.purchaseDate.nativeElement.text = item.PurchaseDate ? czechStringfromDate(new Date(item.PurchaseDate)) : '';
        this.purchaseNote.nativeElement.text = item.PurchaseNote ? item.PurchaseNote : '';
        this.serialNumber.nativeElement.text = item.SerialNumber ? item.SerialNumber : '';
        this.accountNumber.nativeElement.text = item.AccountNumber ? item.AccountNumber : '';
        this.purchasePrice.nativeElement.text = item.PurchasePrice ? +item.PurchasePrice : '';
    }

    onRentExpandTap() {
        this.rentExpanded = !this.rentExpanded;
    }

    onMainExpandTap() {
        this.mainExpanded = !this.mainExpanded;
    }

    onPurchaseExpandTap() {
        this.purchaseExpanded = !this.purchaseExpanded;
    }

    switchClicked() {
        this.canBeRent = this.commercialRent.nativeElement.checked
            || this.unitRent.nativeElement.checked
            || this.eventRent.nativeElement.checked;
    }

    onTapWarehouseSelect(args: EventData) {
        const options = {
            message: 'Zvolte sklad',
            cancelButtonText: 'Zrušit',
            actions: this.warehouses.map(obj => obj.DisplayName)
        };

        action(options).then(async (result) => {
            (<TextField>args.object).text = this.warehouses.find(obj => obj.DisplayName === result).DisplayName;
        });
    }

    onTapCategorySelect(args: EventData) {
        const options = {
            message: 'Zvolte kategorii',
            cancelButtonText: 'Zrušit',
            actions: this.itemCategories.map(obj => obj.DisplayName)
        };

        action(options).then(async (result) => {
            (<TextField>args.object).text = this.itemCategories.find(obj => obj.DisplayName === result).DisplayName;
        });
    }

    onPurchaseTypeTap(args: EventData) {
        const options = {
            message: 'Zvolte způsob pořízení:',
            cancelButtonText: 'Zrušit',
            actions: this.purchaseTypes.map(obj => obj.DisplayName)
        };

        action(options).then(async (result) => {
            (<TextField>args.object).text = this.purchaseTypes.find(obj => obj.DisplayName === result).DisplayName;
        });
    }

    showDate(args: EventData) {
        this.othersIsLoading = true;
        const txtField = <TextField>args.object;
        const date = txtField.text.split('.');
        const options: ModalDialogOptions = {
            viewContainerRef: this.viewContainerRef,
            context: {
                day: date.length === 3 ? date[0].trim() : new Date().getDate(),
                month: date.length === 3 ? date[1].trim() : new Date().getMonth() + 1,
                year: date.length === 3 ? date[2].trim() : new Date().getFullYear(),
                minDate: null
            },
            fullscreen: false
        };
        this.othersIsLoading = false;
        this.modalService.showModal(ModalDatePickerComponent, options)
            .then((result: Date) => {
                if (result) {
                    txtField.text = czechStringfromDate(result);
                }
            });
    }

    /**
     * Takes photo of item.
     *
     * You need to add imports:
     *      import * as camera from "nativescript-camera";
     *      import { Image } from "@nativescript/core/ui/image";
     * You need to install plugin:
     *      tns plugin add nativescript-camera
     * You need to add permission in App_Resources\Android\src\main\AndroidManifest.xml:
     *      <uses-permission android:name="android.permission.CAMERA"/>
     *
     */
    // onTakePhotoTap(item: WarehouseItemAllOutput) {
    // camera.requestPermissions().then(
    //     (success) => {
    //         const options = {
    //             width: 300,
    //             height: 300,
    //             keepAspectRatio: false,
    //             saveToGallery: false
    //         };

    //         camera.takePicture(options)
    //         .then((imageAsset) => {
    //             item.image = new Image();
    //             item.image.src = imageAsset;
    //              //TODO load image on server
    //         }).catch((err) => {
    //             console.log("Error -> " + err.message);
    //         });
    //     },
    //     err => {
    //         // permission request rejected
    //         // ... tell the user ...
    //     }
    // );

    // }

    updateItem() {
        if (this.name.nativeElement.text !== '') {
            const purchDate = dateFromCzechString(this.purchaseDate.nativeElement.text);
            const purchType = this.purchaseTypes.find(obj => obj.DisplayName === this.purchaseType.nativeElement.text);
            this.store.dispatch(new CreateItemUpdate(
                this.item.ID,
                this.name.nativeElement.text,
                this.warehouses.find(obj => obj.DisplayName === this.warehouse.nativeElement.text).ID,
                this.itemCategories.find(obj => obj.DisplayName === this.category.nativeElement.text).ID,
                this.inventoryNumber.nativeElement.text,
                this.description.nativeElement.text,
                (purchDate ? purchDate.toISOString() : undefined),
                (purchType ? purchType.ID : undefined),
                this.purchaseNote.nativeElement.text,
                this.serialNumber.nativeElement.text,
                this.accountNumber.nativeElement.text,
                (this.purchasePrice.nativeElement.text !== '' ? this.purchasePrice.nativeElement.text : undefined),
                (this.actualPrice.nativeElement.text !== '' ? this.actualPrice.nativeElement.text : undefined),
                this.eventRent.nativeElement.checked,
                this.unitRent.nativeElement.checked,
                this.commercialRent.nativeElement.checked,
                (this.rentPrice.nativeElement.text !== '' ? this.rentPrice.nativeElement.text : undefined),
                this.rentNote.nativeElement.text,
                this.note.nativeElement.text))
                .pipe(withLatestFrom(this.itemUpdate$))
                .subscribe(([_, update]) => {
                    feedbackMessage(FeedbackType.Success, 'Úprava položky', `Položka byla úspěšně upravena.`);
                    this.routerExtensions.back();
                }, err => {
                    feedbackMessage(FeedbackType.Error, 'Úprava položky', `Při úpravě položky došlo k chybě. Zkontrolujte prosím zadané hodnoty.`);
                });

        } else {
            feedbackMessage(FeedbackType.Error, 'Úprava položky', `Vyplňte jméno položky.`);
        }
    }

    onBackButton(): void {
        this.routerExtensions.back();
    }

    get saveIcon() {
        return String.fromCharCode(0xf0c7);
    }

    get downIcon() {
        return String.fromCharCode(0xf107);
    }

    get rightIcon() {
        return String.fromCharCode(0xf105);
    }
}
