import { Component, OnInit, ViewContainerRef } from '@angular/core';
import { actionsExecuting, ActionsExecuting } from '@ngxs-labs/actions-executing';
import { Select, Store } from '@ngxs/store';
import { RouterExtensions, ModalDialogService, ModalDialogOptions } from '@nativescript/angular';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs/operators';
import { transitionOptions } from '~/constants/shared.constants';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { LoadGenEvents, LoadGenEventScopes, LoadGenEventStates, LoadGenEventTypes, SetGenEventSearchParams, SetGenEventSortParams } from '~/pages/event/state-mgmt/gen/gen-event-search.actions';
import { GenEventOutput, GenEventScope, GenEventType, GenEventState } from '~/pages/event/entities/gen-event-search.types';
import { DeleteGenEvent } from '~/pages/event/state-mgmt/gen/gen-event-new.actions';
import { formattedGenEventSortKeys, GenEventSortKey, SortDirection, SortParams } from '~/pages/event/types/EventSorting';
import { GenEventSearchListState, GenEventSearch } from '~/pages/event/state-mgmt/gen/gen-event-search-list.state';
import { ActionBarAction, TOP_ACTION_BAR_HEIGHT } from '~/pages/event/components/common/disappearing-scroll-action-bar/disappearing-scroll-action-bar.component';
import { GenEventSearchModalComponent } from '~/pages/event/components/gen/gen-event-search-modal/gen-event-search-modal.component';
import { ScheduleType, EventRel } from '~/pages/event/types/GenEventSearch';
import { SortModalComponent } from '~/pages/event/components/common/sort-modal/sort-modal.component';
import { SortSearchTag, ModalType } from '~/pages/event/types/common.types';
import { sortGenEvents } from '~/pages/event/util/event';
import canEditEvent, { AuthEventType } from '~/pages/event/util/authorization';
import { sortIcon, searchIcon, addIcon } from '~/constants/icons';

@Component({
    selector: 'GenEventSearchList',
    moduleId: module.id,
    templateUrl: './gen-event-list-page.component.html',
})
export class GenEventListPageComponent implements OnInit {
    @Select(actionsExecuting([LoadGenEvents]))
    isLoading$: Observable<ActionsExecuting>;
    @Select(GenEventSearchListState.getEvents)
    eventList$: Observable<GenEventOutput[]>;
    @Select(GenEventSearchListState.getSortParams)
    sortParams$: Observable<SortParams>;
    @Select(GenEventSearchListState.getSearchParams)
    searchParams$: Observable<GenEventSearch>;
    @Select(GenEventSearchListState.getEventScopes)
    eventScopes$: Observable<GenEventScope[]>;
    scopes: GenEventScope[];
    @Select(GenEventSearchListState.getEventTypes)
    eventTypes$: Observable<GenEventType[]>;
    types: GenEventType[];
    @Select(GenEventSearchListState.getEventStates)
    eventStates$: Observable<GenEventState[]>;
    @Select(GenEventSearchListState.isSearchSortDirty)
    isSearchSortDirty$: Observable<boolean>;
    states: GenEventState[];


    topBarHeight = TOP_ACTION_BAR_HEIGHT;

    eventList: GenEventOutput[];
    _sortParams: SortParams;
    searchParams: GenEventSearch;
    isTopBarVisible: boolean = true;
    pageLoading: boolean;

    actionBarActions: ActionBarAction[] = [
        { type: 'sort', icon: sortIcon },
        { type: 'search', icon: searchIcon },
        { type: 'new', icon: addIcon, disabled: !canEditEvent(null, AuthEventType.CAMP) },
    ]
    constructor(
        private routerExtensions: RouterExtensions,
        private store: Store,
        private _vcRef: ViewContainerRef,
        private _modalService: ModalDialogService,
        private route: ActivatedRoute,
        private router: Router,
    ) {
    }

    tags: Array<SortSearchTag> = []
    paramLabels = {
        [GenEventSortKey.NAME]: "Jméno",
        [GenEventSortKey.START]: "Začátek",
        [GenEventSortKey.END]: "Konec",
        [GenEventSortKey.UNIT]: "Pořádající jednotka",
        [GenEventSortKey.REGISTRATION_NUMBER]: "Evidenční číslo",
        [GenEventSortKey.TYPE]: 'Typ',
        [GenEventSortKey.SCOPE]: 'Rozsah',
        [GenEventSortKey.STATE]: 'Stav',
        [SortDirection.ASC]: 'Vzestupně',
        [SortDirection.DESC]: 'Sestupně',
        [ScheduleType.FUTURE]: 'Teprve proběhne',
        [ScheduleType.PAST]: 'Již proběhla',
        [EventRel.ME_AND_MY_UNIT]: 'Týkající se mě a mého střediska',
        [EventRel.UNIT_PLACE]: 'Střediska přímo podřízené mé jednotce',
        [EventRel.ALL_UNIT_PLACE]: 'Všechna střediska pod mou jednotkou ',
    }

    refreshEvents(forceRefresh: boolean = false) {
        if (forceRefresh || this.store.selectSnapshot(GenEventSearchListState.isSearchSortDirty)) {
            this.eventList = []
            this.store.dispatch(new LoadGenEvents())
                .pipe(withLatestFrom(this.eventList$, this.sortParams$, this.searchParams$,
                    this.eventScopes$, this.eventTypes$, this.eventStates$))
                .subscribe(([_, evs, sortParams, searchParams, scopes, types, states]) => {
                    this.searchParams = searchParams;
                    this.eventList = sortGenEvents(evs, sortParams);
                    const { year, type, scope, state, relation, schedule } = this.searchParams;
                    this.tags = [
                        { text: `Seřaděno dle: ${this.paramLabels[sortParams.sortByKey]}`, modalType: ModalType.Sort },
                        { text: `Směr: ${this.paramLabels[sortParams.sortDirection]}`, modalType: ModalType.Sort },
                        year && schedule == ScheduleType.YEAR && { text: `Rok: ${year}`, modalType: ModalType.Search },
                        type && { text: `Typ: ${types.find(t => t.ID === parseInt(type, 10)).DisplayName}`, modalType: ModalType.Search },
                        scope && { text: `Rozsah: ${scopes.find(t => t.ID === parseInt(scope, 10)).DisplayName}`, modalType: ModalType.Search },
                        state && { text: `Stav: ${states.find(t => t.ID === state).DisplayName}`, modalType: ModalType.Search },
                        schedule && schedule !== ScheduleType.YEAR && { text: `Termín: ${this.paramLabels[schedule]}`, modalType: ModalType.Search },
                        relation && { text: `Vztah k akci: ${this.paramLabels[relation]}`, modalType: ModalType.Search },
                    ].filter(s => s)
                })
        }
    }

    ngOnInit(): void {
        this.route.queryParams.subscribe(res => {
            if (res && res.eventId) {
                setTimeout(() => {
                    this.routerExtensions.navigate(['event/generalDetail', res.eventId], { transition: transitionOptions });
                }, 10);
            }
        })
        this.router.events.subscribe((val) => {
            if (val instanceof NavigationEnd) {
                if (this.router.url === '/event/general') {
                    this.pageLoading = false;
                }
            }
        });
        this.store.dispatch([new LoadGenEventTypes(), new LoadGenEventScopes(), new LoadGenEventStates()])
            .pipe(withLatestFrom(this.eventScopes$, this.eventTypes$, this.eventStates$))
            .subscribe(([_, scopes, types, states]) => {
                this.scopes = scopes;
                this.types = types;
                this.states = states;
            })
        this.refreshEvents(true);
    }

    onShowUnit(unitId: number) {
        setTimeout(() => {
            this.routerExtensions.navigate(['unit',
                unitId], { transition: transitionOptions });
        }, 10);
    }

    resetSortSearch() {
        this.store.dispatch([new SetGenEventSortParams(), new SetGenEventSearchParams()])
            .subscribe(() => {
                this.refreshEvents(true);
            })
    }

    onNewEvent() {
        this.pageLoading = true;
        setTimeout(() => {
            this.routerExtensions.navigate(['event/generalNew/'], { transition: transitionOptions });
        }, 10);
    }

    onUpdateEvent(eventId: number) {
        this.pageLoading = true;
        setTimeout(() => {
            this.routerExtensions.navigate(['event/generalUpdate/', eventId], { transition: transitionOptions });
        }, 10);
    }

    onShowEvent(event: GenEventOutput) {
        setTimeout(() => {
            this.routerExtensions.navigate(['event/generalDetail/',
                event.ID], { transition: transitionOptions });
        }, 10);
    }

    onDeleteEvent(eventId: number) {
        this.store.dispatch(new DeleteGenEvent(eventId))
            .pipe(withLatestFrom(this.eventList$)).subscribe(([_, res]) => {
                this.eventList = res
            })
    }

    openSortingModal() {
        this._sortParams = this.store.selectSnapshot(GenEventSearchListState.getSortParams)
        const options: ModalDialogOptions = {
            viewContainerRef: this._vcRef,
            context: { sortParams: this._sortParams, formattedSortByKeys: formattedGenEventSortKeys },
            fullscreen: false,
        };
        this._modalService.showModal(SortModalComponent, options)
            .then((formResult: SortParams) => {
                if (formResult) {
                    this.store.dispatch(new SetGenEventSortParams(formResult))
                        .pipe(withLatestFrom(this.eventList$, this.sortParams$))
                        .subscribe(([_, events, sortParams]) => {
                            this._sortParams = sortParams
                            this.tags = [
                                { text: `Seřaděno dle: ${this.paramLabels[sortParams.sortByKey]}`, modalType: ModalType.Sort },
                                { text: `Směr: ${this.paramLabels[sortParams.sortDirection]}`, modalType: ModalType.Sort },
                                , ...this.tags.filter(t => t.modalType === ModalType.Search)]
                            this.eventList = sortGenEvents(events, sortParams);
                        })
                }
            });
    }

    onAction(action: ActionBarAction) {
        if (action.type === "sort") {
            this.openSortingModal();
        } else if (action.type === "search") {
            this.openSearchModal();
        } else if (action.type === "new") {
            this.onNewEvent();
        }
    }

    openSearchModal() {
        this.searchParams = this.store.selectSnapshot(GenEventSearchListState.getSearchParams)
        const { searchParams, types, states, scopes } = this;
        const options: ModalDialogOptions = {
            viewContainerRef: this._vcRef,
            context: { searchParams, types, states, scopes },
            fullscreen: false,
        };

        this._modalService.showModal(GenEventSearchModalComponent, options)
            .then((formResult: GenEventSearch) => {
                if (formResult) {
                    this.store.dispatch(new SetGenEventSearchParams(formResult))
                        .subscribe((_) => {
                            this.refreshEvents();
                        })
                }

            });
    }

}
