import { Component, ElementRef, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { actionsExecuting, ActionsExecuting } from '@ngxs-labs/actions-executing';
import { Select, Store } from '@ngxs/store';
import { RouterExtensions } from '@nativescript/angular';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs/operators';
import { LoadRegions, NewGenEvent } from '~/pages/event/state-mgmt/gen/gen-event-new.actions';
import { GenEventNewState } from '~/pages/event/state-mgmt/gen/gen-event-new.state';
import { GenEventSearchListState } from '~/pages/event/state-mgmt/gen/gen-event-search-list.state';
import { LoadGenEventTypes, LoadGenEventScopes } from '~/pages/event/state-mgmt/gen/gen-event-search.actions';
import { SearchUnits } from '~/pages/event/state-mgmt/gen/gen-event-new.actions';
import { action, alert } from '@nativescript/core/ui/dialogs';
import { transitionOptions } from '~/constants/shared.constants';
import { Feedback, FeedbackType } from 'nativescript-feedback';
import { RegionOutput, UnitOutput } from '~/pages/event/entities/gen-event-new.types';
import { GenEventScope, GenEventType } from '~/pages/event/entities/gen-event-search.types';
import { LoadGenEventDetail } from '~/pages/event/state-mgmt/gen/gen-event-detail.actions';
import { GenEventDetailOutput } from '~/pages/event/entities/gen-event-detail.types';
import { GenEventDetailState } from '~/pages/event/state-mgmt/gen/gen-event-detail.state';
import { UpdateGenEvent } from './../../../state-mgmt/gen/gen-event-new.actions';
import { UnitSearchCriteria, UnitSearchOptions } from '~/pages/event/types/UnitSearch';
import { Picker, formatPickerValues } from '~/pages/event/util';
import { CoordinateType, dec2deg, deg2dec, LATITUDE_REGEX, validateCoordinates } from '~/shared/pipes/gps-coordinate.pipe';
import { RadDataFormComponent } from 'nativescript-ui-dataform/angular';
import { GpsFormComponent } from '~/pages/event/components/common/gps-form/gps-form.component';

export interface GenEventNewForm {
    name: string;
    type: string;
    scope: string;
    note: string;
    startDate: string;
    startTime: string;
    endDate: string;
    endTime: string;
}
interface LocationForm {
    street: string;
    city: string;
    postCode: string;
    region: string;
    state: string;
}
const defState: GenEventNewForm = {
    type: null,
    scope: null,
    name: '',
    startDate: '',
    startTime: '',
    endDate: '',
    endTime: '',
    note: '',
}

const defLocation: LocationForm = {
    state: '',
    street: '',
    region: null,
    city: '',
    postCode: '',

}
@Component({
    selector: 'GenEventNewPage',
    moduleId: module.id,
    templateUrl: './gen-event-new-page.component.html',
    styleUrls: ['../../../event.scss']
})
export class GenEventNewPageComponent implements OnInit, AfterViewInit {
    @ViewChild("genEventForm", { static: true })
    form: RadDataFormComponent;
    // @ViewChild("estate", { static: true })
    // estate: ElementRef;
    // @ViewChild("group", { static: true })
    // group: ElementRef;
    @ViewChild("gpsForm", { static: true })
    gpsForm: GpsFormComponent;
    @Select(actionsExecuting([
        LoadGenEventTypes, LoadGenEventScopes, LoadRegions, SearchUnits,
        LoadGenEventDetail, UpdateGenEvent, NewGenEvent, LoadGenEventDetail,
    ]))
    isLoading$: Observable<ActionsExecuting>;
    @Select(GenEventSearchListState.getEventScopes)
    eventScopes$: Observable<GenEventScope[]>;
    scopes: GenEventScope[];
    @Select(GenEventSearchListState.getEventTypes)
    eventTypes$: Observable<GenEventType[]>;
    types: GenEventType[];
    @Select(GenEventNewState.getRegions)
    regions$: Observable<RegionOutput[]>;
    regions: RegionOutput[];
    @Select(GenEventNewState.getUnits)
    units$: Observable<UnitOutput[]>;
    units: UnitOutput[];
    @Select(GenEventNewState.getNewEventId)
    newEventId$: Observable<number>;

    updateEventId: number;

    newGenEvent: GenEventNewForm;
    locationForm: LocationForm;
    formattedRegions: Picker[] = [{ key: '', label: 'Nezadáno' }];
    formattedUnits: Picker[] = [];
    noData = { key: '', label: 'Pořadatelé nenalezeni' }
    formattedTypes: Picker[] = [{ key: '', label: 'Žádná data' }]
    formattedScopes: Picker[] = [{ key: '', label: 'Žádná data' }]
    unitSearchForm = { text: '' }
    unitForm: { unit: string };

    selEstate: UnitOutput;
    selGroup: UnitOutput;
    selUnit: UnitOutput;
    feedback: Feedback;
    @Select(GenEventDetailState.getEventDetail)
    baseEventState$: Observable<GenEventDetailOutput>;

    constructor(
        private routerExtensions: RouterExtensions,
        private route: ActivatedRoute,
        private store: Store,
    ) {
        this.feedback = new Feedback();
    }
    ngAfterViewInit(): void {
        // setInputDateFormat(this.form, ['startDate', 'endDate']);// TODO Bugged
    }
    ngOnInit(): void {
        this.newGenEvent = { ...defState };
        this.locationForm = { ...defLocation };
        this.unitForm = { unit: null }
        this.route.params.subscribe(params => {
            if (params['id']) {
                this.updateEventId = parseInt(params['id'], 10);
            }
        });

        this.store.dispatch([new LoadGenEventTypes(), new LoadGenEventScopes(), new LoadRegions()])
            .pipe(withLatestFrom(this.eventScopes$, this.eventTypes$, this.regions$))
            .subscribe(([_, scopes, types, regions]) => {
                this.scopes = scopes;
                this.types = types;
                this.regions = regions
                this.formattedTypes = formatPickerValues(types, '');
                this.formattedScopes = formatPickerValues(scopes, '');
                this.formattedRegions = formatPickerValues(regions, 'Nezadáno');
                if (this.updateEventId) {
                    this.store.dispatch(new LoadGenEventDetail(this.updateEventId))
                        .pipe(withLatestFrom(this.baseEventState$)).subscribe(([_, det]) => {
                            const { DisplayName: name, ID_EventGeneralType: type,
                                ID_EventGeneralScope: scope, Region: region,
                                Street: street, State: state, Postcode: postCode,
                                Note: note, ID_Unit: unitId, StartDate, EndDate,
                                GpsLatitude, GpsLongitude, Unit: unitName,
                                RegistrationNumber: unitRegNum, Location
                            } = det;
                            this.formattedUnits =
                                [{ label: `${unitRegNum} - ${unitName}`, key: unitId.toString() }]
                            this.unitForm = { unit: unitId.toString() };
                            const sDate = new Date(StartDate);
                            const eDate = new Date(EndDate);
                            this.newGenEvent = {
                                name, scope: scope.toString(),
                                type: type.toString(), note,
                                startDate: sDate.toISOString(),
                                endDate: eDate.toISOString(),
                                startTime: `${sDate.getHours()}:${sDate.getMinutes()}`,
                                endTime: `${eDate.getHours()}:${eDate.getMinutes()}`,
                            };
                            this.locationForm = { street, state, postCode, region, city: Location };
                            this.gpsForm.formData = {
                                gpsLatitude: GpsLatitude ? dec2deg(GpsLatitude, CoordinateType.LATITUDE) : '',
                                gpsLongitude: GpsLongitude ? dec2deg(GpsLongitude, CoordinateType.LONGITUDE) : '',
                            };
                        })
                } else {
                    this.newGenEvent = {
                        ...defState,
                        type: types[0].ID.toString(),
                        scope: scopes[0].ID.toString(),
                    }
                }
            })
    }

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

    onSearchClick() {
        let options = {
            title: "Vyhledat podle",
            message: "Vyber",
            cancelButtonText: "Storno",
            actions: UnitSearchCriteria.map(v => v.label)
        };

        action(options).then((result) => {
            const selectedCrit = UnitSearchCriteria.find(c => c.label === result)
            this.store.dispatch(new SearchUnits({
                criteria: UnitSearchOptions[selectedCrit.key],
                text: this.unitSearchForm.text
            }))
                .pipe(withLatestFrom(this.units$))
                .subscribe(([_, units]) => {
                    this.units = units;
                    if (units.length === 0) {
                        this.formattedUnits = [this.noData]
                        alert('Pořadatelé nebyly nalezeni')
                    } else {
                        this.formattedUnits = units.map(({ ID, SortName }) =>
                            ({ label: SortName, key: ID.toString() }))

                        action({
                            title: 'Vyberte pořadatele',
                            message: "Vyberte z nalezených pořadatelů",
                            cancelButtonText: "Zrušit",
                            actions: units.map(p => p.SortName)
                        }).then((result) => {
                            const { ID } = units.find(u => u.SortName === result);
                            this.unitForm = { unit: ID.toString() };
                        });
                    }
                })
        });

    }
    async validate() {
        const isValid = await this.form.dataForm.validateAndCommitAll()
        if (!isValid) return false
        const { type, scope, name, startDate, endDate, } = this.newGenEvent;
        const { gpsLatitude, gpsLongitude, } = this.gpsForm.formData;
        const required = [type, scope, name, startDate, endDate, this.unitForm.unit]
        const requiredNames = ['Typ', 'Rozsah', 'Název', 'Datum začátku', 'Datum konce', 'Pořadatele']
            .map((val, i) => ({ name: val, value: required[i] }))
        const res = requiredNames.every(a => a.value);
        let errMessage = null
        if (!res)
            errMessage = 'Zadejte ' + requiredNames.filter(f => !f.value).map(f => f.name).join(', ')
        else if ((gpsLatitude || gpsLongitude) && !validateCoordinates(deg2dec(gpsLatitude), deg2dec(gpsLongitude)))
            errMessage = `GPS souřadnice jsou špatně (${!LATITUDE_REGEX.test(deg2dec(gpsLatitude)) ? 'šířka' : 'délka'})`

        if (errMessage) {
            this.feedback.show({
                title: 'ERROR',
                type: FeedbackType.Error,
                message: errMessage
            });
            return false
        }
        return true;

    }

    async submit() {
        const res = await this.validate();
        if (!res) return;
        let type = parseInt(this.newGenEvent.type)
        let scope: number = parseInt(this.newGenEvent.scope)
        if (!scope) {
            scope = parseInt(this.formattedScopes.find(s => s.label === this.newGenEvent.scope).key)
        }
        if (!type) {
            type = parseInt(this.formattedTypes.find(s => s.label === this.newGenEvent.type).key)
        }
        const gpsForm = this.gpsForm.formData
        const gpsLatitude = gpsForm.gpsLatitude && deg2dec(gpsForm.gpsLatitude).toString()
        const gpsLongitude = gpsForm.gpsLongitude && deg2dec(gpsForm.gpsLongitude).toString()
        if (this.updateEventId) {
            this.store.dispatch(new UpdateGenEvent({
                ...this.newGenEvent, unitId: parseInt(this.unitForm.unit, 10),
                startDate: new Date(this.newGenEvent.startDate),
                endDate: new Date(this.newGenEvent.endDate),
                type, scope, gpsLatitude, gpsLongitude, ...this.locationForm
            }, this.updateEventId)).subscribe(() => {
                setTimeout(() => {
                    this.routerExtensions.navigate(['event/general'],
                        { transition: transitionOptions, clearHistory: true, queryParams: { eventId: this.updateEventId } });
                }, 10);
            })
        } else {
            this.store.dispatch(new NewGenEvent({
                ...this.newGenEvent, unitId: parseInt(this.unitForm.unit, 10),
                startDate: new Date(this.newGenEvent.startDate),
                endDate: new Date(this.newGenEvent.endDate),
                scope, type, gpsLatitude, gpsLongitude, ...this.locationForm

            })).pipe(withLatestFrom(this.newEventId$)).subscribe(([_, newId]) => {
                setTimeout(() => {
                    this.routerExtensions.navigate(['event/general'],
                        { transition: transitionOptions, clearHistory: true, queryParams: { eventId: newId } });
                }, 10);
            })
        }

    }
}