import { Component, OnInit, ViewContainerRef } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Select, Store } from '@ngxs/store';
import { ModalDialogOptions, ModalDialogService, RouterExtensions } from '@nativescript/angular';
import { map, withLatestFrom } from 'rxjs/operators';
import { combineLatest, Observable } from 'rxjs';
import { ActionsExecuting, actionsExecuting } from '@ngxs-labs/actions-executing';
import { Person } from '~/pages/event/types/common.types';
import { CampEventDetailState } from '~/pages/event/state-mgmt/camp/camp-event-detail.state';
import { CampEventDetailOutput, CampEventFunctionAllOutput, CampEventParticipantAllOutput, CampEventStatisticDetail } from '~/pages/event/entities/camp-event-detail.types';
import { CampEventRemoveParticipant, LoadCampEventDetail, LoadCampEventLeaders, LoadCampEventParticipants, LoadCampEventStatisticDetail, LoadCampUnits, SetCampEventParticipantSortParams } from '~/pages/event/state-mgmt/camp/camp-event-detail.actions';
import { PhoneContactService } from '~/core/services/phone-contact.service';
import { UnitDetailOutput } from '~/pages/unit/entities/output/unitDetailOutput';
import { SortModalComponent } from '~/pages/event/components/common/sort-modal/sort-modal.component';
import { CampParticipantSortKey, formattedCampParticipantSortKeys, SortParams } from '~/pages/event/types/EventSorting';
import { groupByPersonId, sortItems } from '~/pages/event/util';
import { CampEventUpdateParticipant } from '~/pages/event/state-mgmt/camp/camp-event-participant.actions';
import { transitionOptions } from '~/constants/shared.constants';
import { editIcon } from '~/constants/icons';
import canEditEvent, { AuthEventType } from '~/pages/event/util/authorization';
import { mergePersonMap } from './../../../util/index';
import { CampParticipant } from '~/pages/event/types/camp';

export enum CampEventTabs {
    BASE_DETAIL = 0,
    TEAM = 1,
    PARTICIPANTS = 2,
    STATE = 3,
}

@Component({
    selector: 'CampEventDetailPage',
    moduleId: module.id,
    templateUrl: './camp-event-detail-page.component.html',
})
export class CampEventDetailPageComponent implements OnInit {
    @Select(actionsExecuting([
        LoadCampEventDetail, LoadCampEventLeaders,
        LoadCampEventParticipants, LoadCampUnits,
        LoadCampEventStatisticDetail, LoadCampEventDetail,
        CampEventRemoveParticipant, CampEventUpdateParticipant
    ]))
    isLoading$: Observable<ActionsExecuting>;

    @Select(CampEventDetailState.getEventDetail)
    eventDetail$: Observable<CampEventDetailOutput>;
    @Select(CampEventDetailState.getEventLeaderDetail)
    eventLeaders$: Observable<CampEventFunctionAllOutput[]>;
    @Select(CampEventDetailState.getParticipants)
    participants$: Observable<CampEventParticipantAllOutput[]>;
    @Select(CampEventDetailState.getStatisticDetail)
    statisticDetail$: Observable<CampEventStatisticDetail>;
    @Select(CampEventDetailState.getCampUnits)
    campUnits$: Observable<UnitDetailOutput[]>;
    @Select(CampEventDetailState.getCampParticipantsSortParams)
    sortParams$: Observable<SortParams>;

    selectedIndex = CampEventTabs.BASE_DETAIL;
    eventId: number;
    team$: Observable<Person[]>;
    campParticipants$: Observable<CampParticipant[]>;
    constructor(
        private routerExtensions: RouterExtensions,
        private route: ActivatedRoute,
        private store: Store,
        private phoneContactSrv: PhoneContactService,
        private _vcRef: ViewContainerRef,
        private _modalService: ModalDialogService,
    ) {
    }
    ngOnInit(): void {
        this.route.params.subscribe(params => {
            this.eventId = parseInt(params['id'], 10);
            this.selectedIndex = parseInt(params['section'], 10) || CampEventTabs.BASE_DETAIL;
        })
        this.team$ = this.eventLeaders$
            .pipe(map<CampEventFunctionAllOutput[], Person[]>(
                (leaders: CampEventFunctionAllOutput[]) => {
                    const leadersList = leaders.map(({ ID_Person, Person,
                        EventFunctionType, Note, HasQualification }) =>
                    ({
                        id: ID_Person, name: Person,
                        roles: [EventFunctionType], otherInfo: '',
                        extendedInfo: [
                            { title: EventFunctionType, value: "" },
                            { title: 'Poznámka', value: Note },
                            { title: 'Kvalifikace', value: HasQualification, type: 'boolean' }
                        ]
                    })
                    ).filter(l => l.id);
                    const groups = groupByPersonId(leadersList)

                    return mergePersonMap(groups)
                        .map(p => ({ ...p, roles: [], otherInfo: p.roles.join(', ') }));
                }));

        this.campParticipants$ = combineLatest([this.participants$, this.sortParams$])
            .pipe(map(([particips, sortParams]) => {
                const sorted = sortItems(particips, sortParams,
                    sortParams.sortByKey === CampParticipantSortKey.BIRTHDAY);
                return this.refreshParticipants(sorted);
            }));
    }

    loadEventDetailWithUnits() {
        this.store.dispatch(new LoadCampEventDetail(this.eventId))
            .pipe(withLatestFrom(this.eventDetail$)).subscribe(([_, detail]) => {
                if (detail.ID_UnitArray.length) {
                    this.store.dispatch(new LoadCampUnits(detail.ID_UnitArray))
                }
            })
    }
    loadEventDetail() {
        this.store.dispatch(new LoadCampEventDetail(this.eventId));
    }
    refreshParticipants(particips: CampEventParticipantAllOutput[]): CampParticipant[] {
        return particips.map(
            ({ ID_Person, ID, Person, Birthday, Street, Category, Days, Age,
                UnitRegistrationNumber, Estimate, Real, Note }) =>
            ({
                ID, PersonId: ID_Person, Name: Person, Category,
                Address: Street, Days, Age, UnitNumber: UnitRegistrationNumber,
                Estimate: !!Estimate, Real: !!Real, Birthday, Note
            })
        ).filter(l => l.ID);
    }

    loadParticipants() {
        this.store.dispatch([
            new LoadCampEventParticipants(this.eventId),
            new LoadCampEventStatisticDetail(this.eventId),
            new LoadCampEventDetail(this.eventId)]);
    }

    loadLeadersData() {
        this.store.dispatch(new LoadCampEventLeaders(this.eventId));
    }
    isEditable(item) {
        return canEditEvent(item.ID_Unit, AuthEventType.CAMP) &&
            ['approvedLeader', 'approvedParent'].indexOf(item.ID_EventCampState) === -1
    }

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

    openSortModal() {
        const sortParams = this.store.selectSnapshot(CampEventDetailState.getCampParticipantsSortParams)
        const options: ModalDialogOptions = {
            viewContainerRef: this._vcRef,
            context: { sortParams: sortParams, formattedSortByKeys: formattedCampParticipantSortKeys },
            fullscreen: false,
        };
        this._modalService.showModal(SortModalComponent, options)
            .then((formResult: SortParams) => {
                if (formResult) {
                    this.store.dispatch(new SetCampEventParticipantSortParams(formResult))
                }
            });
    }

    removeParticipant(participId: number) {
        this.store.dispatch(new CampEventRemoveParticipant(participId))
    }

    updateParticipant(particip: CampParticipant) {
        this.store.dispatch(new CampEventUpdateParticipant({ particip }))
    }
    onEditTeam() {
        setTimeout(() => {
            this.routerExtensions.navigate(['/event/campUpdateFunctions/', this.eventId], { transition: transitionOptions });
        }, 10);
    }

    setIndex(i) {
        this.selectedIndex = i.newIndex;
    }
    onCreateCall(phoneNumber: string) {
        this.phoneContactSrv.createCall(phoneNumber);
    }

    get editIcon() { return editIcon; }
}
