import { Action, Selector, State, StateContext } from '@ngxs/store';
import { WebApiService } from '~/core/services/web-api.service';
import { ApplicationSettings as AppSettings } from '@nativescript/core';

import { USER_TOKEN } from '~/constants/login-constants';
import { wsEvents } from '~/constants/api.constants';
import { catchError, tap } from 'rxjs/operators';
import { EduEventLoadInstructor, LoadEventAssistantDetail, LoadEventInstructors, LoadEventInstructorTypes, LoadEventLeaderDetail } from './edu-event-people.actions';
import {
    EduEventInstructorTypeAllOutput, EduEventAssistantOutput, EduEventInstructorsOutput,
    EduEventLeaderDetailOutput, EventFunctionAllEducationLeader,
    EventFunctionAllEducationAssistant, InstructorAll, InstructorDetail, InstructorTypeAll, InstructorInsert, InstructorUpdate
} from '~/pages/event/entities/edu-event-people.types';
import { EduEventInsertInstructor, EduEventUpdateInstructor } from './edu-event-detail.action';
import { FeedbackType } from 'nativescript-feedback';
import { feedbackMessage } from '~/pages/material/utils/feedback-messages';
import { errorFeedback } from '../gen/gen-event-new.state';
import { EduEventDeleteInstructor } from '~/pages/event/state-mgmt/edu/edu-event-detail.action';
import { InstructorDelete } from './../../entities/edu-event-people.types';



export interface EduEventPeopleDetailStateModel {
    eventLeaderDetail: EduEventLeaderDetailOutput[];
    eventAssistantDetail: EduEventAssistantOutput[];
    eventInstructors: EduEventInstructorsOutput[];
    selectedInstructor: EduEventInstructorsOutput;
    instructorTypes: EduEventInstructorTypeAllOutput[];
}

const initialStateModel: EduEventPeopleDetailStateModel = {
    eventLeaderDetail: [],
    eventAssistantDetail: [],
    eventInstructors: [],
    selectedInstructor: null,
    instructorTypes: [],

};
@State<EduEventPeopleDetailStateModel>({
    name: 'eduEventLeaderDetail',
    defaults: initialStateModel
})
export class EduEventPeopleDetailState {

    constructor(
        private webApiService: WebApiService
    ) {
    }
    @Selector()
    static getEventLeaderDetail(state: EduEventPeopleDetailStateModel) {
        return state.eventLeaderDetail
    }
    @Selector()
    static getInstructorTypes(state: EduEventPeopleDetailStateModel) {
        return state.instructorTypes
    }

    @Selector()
    static getEventAssistantsDetail(state: EduEventPeopleDetailStateModel) {
        return state.eventAssistantDetail
    }

    @Selector()
    static getEventInstructors(state: EduEventPeopleDetailStateModel) {
        return state.eventInstructors
    }
    @Selector()
    static getEventSelectedInstructor(state: EduEventPeopleDetailStateModel) {
        return state.selectedInstructor
    }

    @Action(LoadEventLeaderDetail)
    loadEventLeaderDetail(ctx: StateContext<EduEventPeopleDetailStateModel>,
        action: LoadEventLeaderDetail) {

        if (action.eventEducationId) {
            return this.webApiService.call(
                new EventFunctionAllEducationLeader(
                    AppSettings.getString(USER_TOKEN),
                    action.eventEducationId),
                () => new EduEventLeaderDetailOutput(),
                wsEvents
            ).pipe(
                tap((response: EduEventLeaderDetailOutput[]) => {
                    ctx.patchState({
                        eventLeaderDetail: response
                    });

                }),
                catchError(e => {
                    ctx.patchState({
                        eventLeaderDetail: initialStateModel.eventLeaderDetail
                    });

                    throw e;
                })
            );
        }
    }
    @Action(LoadEventAssistantDetail)
    loadEventAssistantsDetail(ctx: StateContext<EduEventPeopleDetailStateModel>,
        action: LoadEventAssistantDetail) {

        if (action.eventEducationId) {
            return this.webApiService.call(
                new EventFunctionAllEducationAssistant(
                    AppSettings.getString(USER_TOKEN),
                    action.eventEducationId),
                () => new EduEventAssistantOutput(),
                wsEvents
            ).pipe(
                tap((response: EduEventAssistantOutput[]) => {
                    ctx.patchState({
                        eventAssistantDetail: response
                    });

                }),
                catchError(e => {
                    ctx.patchState({
                        eventAssistantDetail: initialStateModel.eventAssistantDetail
                    });

                    throw e;
                })
            );
        }
    }
    @Action(LoadEventInstructors)
    loadEventInstructors(ctx: StateContext<EduEventPeopleDetailStateModel>,
        action: LoadEventInstructors) {

        if (action.eventEducationId) {
            return this.webApiService.call(
                new InstructorAll(
                    AppSettings.getString(USER_TOKEN),
                    action.eventEducationId),
                () => new EduEventInstructorsOutput(),
                wsEvents
            ).pipe(
                tap((response: EduEventInstructorsOutput[]) => {
                    ctx.patchState({
                        eventInstructors: response
                    });

                }),
                catchError(e => {
                    ctx.patchState({
                        eventInstructors: initialStateModel.eventInstructors
                    });

                    throw e;
                })
            );
        }
    }
    @Action(EduEventLoadInstructor)
    loadEventInstructor(ctx: StateContext<EduEventPeopleDetailStateModel>,
        action: EduEventLoadInstructor) {
        if (action.eventId) {
            return this.webApiService.call(
                new InstructorDetail(
                    AppSettings.getString(USER_TOKEN),
                    action.instructorId),
                () => new EduEventInstructorsOutput(),
                wsEvents
            ).pipe(
                tap((response: EduEventInstructorsOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            selectedInstructor: response[0]
                        });
                    } else {
                        ctx.patchState({
                            selectedInstructor: initialStateModel.selectedInstructor
                        });
                        throw 'Something went wrong.';
                    }

                }),
                catchError(e => {
                    ctx.patchState({
                        selectedInstructor: initialStateModel.selectedInstructor
                    });

                    throw e;
                })
            );
        }
    }
    @Action(LoadEventInstructorTypes)
    loadEventInstructorTypes(ctx: StateContext<EduEventPeopleDetailStateModel>) {
        return this.webApiService.call(
            new InstructorTypeAll(
                AppSettings.getString(USER_TOKEN)),
            () => new EduEventInstructorTypeAllOutput(),
            wsEvents
        ).pipe(
            tap((response: EduEventInstructorTypeAllOutput[]) => {
                ctx.patchState({
                    instructorTypes: response
                });

            }),
            catchError(e => {
                ctx.patchState({
                    instructorTypes: initialStateModel.instructorTypes
                });

                throw e;
            })
        );
    }

    @Action(EduEventInsertInstructor)
    insertInstructor(ctx: StateContext<EduEventPeopleDetailStateModel>,
        { eventId, instructor: inst }: EduEventInsertInstructor) {
        return this.webApiService.call(
            new InstructorInsert(
                AppSettings.getString(USER_TOKEN),
                eventId, inst.personId, inst.type, inst.scoutExp,
                inst.focus, inst.profExp
            ),
            () => new EduEventInstructorsOutput(),
            wsEvents
        ).pipe(
            tap((response: EduEventInstructorsOutput[]) => {
                feedbackMessage(FeedbackType.Success, "Instruktor vzdělávací akce",
                    "Instruktor vzdělávací akce byl přidán.")
            }), catchError(e => {

                if (e.error.includes('Instructor_DuplicateGarant')) {
                    feedbackMessage(FeedbackType.Error, "Instruktor vzdělávací akce",
                        "Pro každou akci může být jen jeden garant ZZA.");
                    throw e;
                }

                errorFeedback('EduEventInsertInstructorPermissionDenied');

                throw e;
            })

        );
    }

    @Action(EduEventUpdateInstructor)
    updateInstructor(ctx: StateContext<EduEventPeopleDetailStateModel>,
        { eventId, instructor: inst }: EduEventUpdateInstructor) {
        return this.webApiService.call(
            new InstructorUpdate(
                AppSettings.getString(USER_TOKEN),
                eventId, inst.personId, inst.type, inst.scoutExp,
                inst.focus, inst.profExp
            ),
            () => new EduEventInstructorsOutput(),
            wsEvents
        ).pipe(
            tap((response: EduEventInstructorsOutput[]) => {
                feedbackMessage(FeedbackType.Success, "Instruktor vzdělávací akce",
                    "Instruktor vzdělávací akce byl upraven.")
            }), catchError(e => {

                if (e.error.includes('Instructor_DuplicateGarant')) {
                    // API BUG when trying to update Garant 
                    feedbackMessage(FeedbackType.Error, "Instruktor vzdělávací akce",
                        "Pro každou akci může být jen jeden garant ZZA.");
                    throw e;
                }

                errorFeedback('EduEventUpdateInstructorPermissionDenied');

                throw e;
            })

        );
    }

    @Action(EduEventDeleteInstructor)
    removeInstructor(ctx: StateContext<EduEventPeopleDetailStateModel>,
        { instructorId }: EduEventDeleteInstructor) {
        return this.webApiService.call(
            new InstructorDelete(
                AppSettings.getString(USER_TOKEN),
                instructorId
            ),
            () => ({}),
            wsEvents
        ).pipe(
            tap((response: any) => {
                feedbackMessage(FeedbackType.Success, "Instruktor vzdělávací akce",
                    "Instruktor vzdělávací akce byl odstraněn.")
            }), catchError(e => {

                feedbackMessage(FeedbackType.Error, "Instruktor vzdělávací akce",
                    "Instruktor vzdělávací akce nebyl odstraněn.")

                errorFeedback('EduEventDeleteInstructorPermissionDenied');

                throw e;
            })

        );
    }
}



