import { Action, Selector, State, StateContext } from '@ngxs/store';
import { FeedbackType } from 'nativescript-feedback';
import { zip } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { ApplicationSettings as AppSettings, ImageSource } from '@nativescript/core';
import { APP_ID, wsEvents } from '~/constants/api.constants';
import { USER_TOKEN } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import {
    EventDetailLogoOutput, EduEventDetailOutput, EduEventCourseOutput,
    EduEventCoursesTermsOutput, EventEducationDetail,
    EventEducationCourseAll, EventEducationDetailLogo,
    EventEducationCourseTermAll, EventEducationCourseDetail,
    EventEducationCourseTermDetail, EduEventLocationDetailOutput,
    EventEducationLocationDetail
} from '~/pages/event/entities/edu-event-detail.types';
import { feedbackMessage } from '~/pages/material/utils/feedback-messages';
import {
    EventEducationUpdateLeader, EventFunctionDeleteEducationAssistant,
    EventFunctionInsertEducationAssistant, EventFunctionUpdateEducationAssistant
} from '../../entities/edu-event-people.types';
import { errorFeedback, errorFeedbackOperator } from '../gen/gen-event-new.state';
import {
    EduEventDeleteAssistant,
    EduEventInsertAssistant,
    EduEventUpdateAssistant,
    EduEventUpdateLeader,
    LoadEduEventCourseDetail, LoadEduEventCourses, LoadEduEventCoursesTerms,
    LoadEduEventCoursesTermsLocations,
    LoadEduEventCourseTermDetail, LoadEduEventDetail, LoadLogoContent
} from './edu-event-detail.action';

export interface EduEventDetailStateModel {
    photoContent: EduEventLogo;
    eventDetail: EduEventDetailOutput;
    courses: EduEventCourseOutput[];
    coursesTerms: EduEventCoursesTermsOutput[];
    selectedCourse: EduEventCourseOutput;
    selectedTerm: EduEventCoursesTermsOutput;
    termLocations: EduEventLocationDetailOutput[]
}
const EduEventLeaderNames = {
    "Vedoucí akce": "Leader",
    "Zastupce vedoucího": "Assistant",
    "Hospodář akce": "Economist",
    "Zdravotník": "Medic",
    "Tajemník akce": "Secretary",
}

const initialStateModel: EduEventDetailStateModel = {
    photoContent: null,
    eventDetail: null,
    courses: [],
    coursesTerms: [],
    selectedCourse: null,
    selectedTerm: null,
    termLocations: [],
};
export interface EduEventLogo {
    src: any;
    imageId: number;
    filename: string;
}

@State<EduEventDetailStateModel>({
    name: 'eduEventDetail',
    defaults: initialStateModel
})
export class EduEventDetailState {
    @Selector()
    static getEventDetail(state: EduEventDetailStateModel) {
        return state.eventDetail;
    }

    @Selector()
    static getPhotoContent(state: EduEventDetailStateModel) {
        return state.photoContent;
    }
    @Selector()
    static getEventCourses(state: EduEventDetailStateModel) {
        return state.courses;
    }
    @Selector()
    static getEventCoursesTerms(state: EduEventDetailStateModel) {
        return state.coursesTerms;
    }

    @Selector()
    static getEventCourseDetail(state: EduEventDetailStateModel) {
        return state.selectedCourse;
    }

    @Selector()
    static getEventTermsLocationDetails(state: EduEventDetailStateModel) {
        return state.termLocations;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }


    @Action(LoadEduEventDetail)
    loadEventDetail(ctx: StateContext<EduEventDetailStateModel>, action: LoadEduEventDetail) {
        if (action.id) {
            return this.webApiService.call(
                new EventEducationDetail(AppSettings.getString(USER_TOKEN), action.id),
                () => new EduEventDetailOutput(),
                wsEvents
            ).pipe(
                tap((response: EduEventDetailOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            eventDetail: response[0]
                        });
                    } else {
                        ctx.patchState({
                            eventDetail: initialStateModel.eventDetail
                        });
                        throw new Error('Nepodařilo se nalézt detail akce');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        eventDetail: initialStateModel.eventDetail
                    });

                    throw e;
                })
            );
        }
    }
    @Action(LoadEduEventCourses)
    loadEventCourses(ctx: StateContext<EduEventDetailStateModel>, action: LoadEduEventCourses) {
        if (action.id) {
            return this.webApiService.call(
                new EventEducationCourseAll(APP_ID, AppSettings.getString(USER_TOKEN), action.id),
                () => new EduEventCourseOutput(),
                wsEvents
            ).pipe(
                tap((response: EduEventCourseOutput[]) => {
                    ctx.patchState({
                        courses: response
                    });

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

                    throw e;
                })
            );
        }
    }

    @Action(LoadLogoContent)
    loadEventDetailLogo(ctx: StateContext<EduEventDetailStateModel>, action: LoadLogoContent) {

        if (action.id) {
            return this.webApiService.call(
                new EventEducationDetailLogo(APP_ID, AppSettings.getString(USER_TOKEN), action.id, 'normal'),
                () => new EventDetailLogoOutput(),
                wsEvents
            ).pipe(
                tap(async (res: EventDetailLogoOutput[]) => {
                    if (res.length === 1) {
                        const img = res[0];
                        if (img.LogoContent) {
                            const content = await ImageSource.fromBase64(img.LogoContent)
                            ctx.patchState({
                                photoContent: {
                                    src: content,
                                    imageId: img.ID,
                                    filename: img.LogoFileName,
                                }
                            });


                        } else {
                            ctx.patchState({
                                photoContent: {
                                    src: null,
                                    imageId: img.ID,
                                    filename: img.LogoFileName,
                                }
                            });
                        }
                    } else {
                        ctx.patchState({
                            photoContent: initialStateModel.photoContent
                        });
                        throw new Error('Nepodařilo se nalézt detail osoby');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        photoContent: initialStateModel.photoContent
                    });

                    throw e;
                })
            );
        }
    }
    @Action(LoadEduEventCoursesTerms)
    loadEventCoursesTerms(ctx: StateContext<EduEventDetailStateModel>, action: LoadEduEventCoursesTerms) {

        if (action.id) {
            return this.webApiService.call(
                new EventEducationCourseTermAll(AppSettings.getString(USER_TOKEN), action.id),
                () => new EduEventCoursesTermsOutput(),
                wsEvents
            ).pipe(
                tap((res: EduEventCoursesTermsOutput[]) => {
                    ctx.patchState({
                        coursesTerms: res
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        coursesTerms: initialStateModel.coursesTerms
                    });

                    throw e;
                })
            );
        }
    }

    @Action(LoadEduEventCourseDetail)
    loadEventCourseDetail(ctx: StateContext<EduEventDetailStateModel>, action: LoadEduEventCourseDetail) {
        if (action.id) {
            return this.webApiService.call(
                new EventEducationCourseDetail(AppSettings.getString(USER_TOKEN), action.id, action.eventEducationId),
                () => new EduEventCourseOutput(),
                wsEvents
            ).pipe(
                tap((response: EduEventCourseOutput) => {
                    ctx.patchState({
                        selectedCourse: response
                    });

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

                    throw e;
                })
            );
        }
    }

    @Action(LoadEduEventCourseTermDetail)
    loadEduEventCourseTermDetail(ctx: StateContext<EduEventDetailStateModel>,
        action: LoadEduEventCourseTermDetail) {
        return this.webApiService.call(
            new EventEducationCourseTermDetail(
                AppSettings.getString(USER_TOKEN), action.id),
            () => new EduEventCoursesTermsOutput(),
            wsEvents
        ).pipe(
            tap((response: EduEventCoursesTermsOutput) => {
                ctx.patchState({
                    selectedTerm: response
                });

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

    @Action(LoadEduEventCoursesTermsLocations)
    loadEduEventCourseTermsLocationsDetail(ctx: StateContext<EduEventDetailStateModel>,
        action: LoadEduEventCoursesTermsLocations) {
        const tk = AppSettings.getString(USER_TOKEN)
        const ids = Array.from(new Set(action.termIds))

        const reqs = ids.map(id => this.webApiService.call(
            new EventEducationLocationDetail(tk, id),
            () => new EduEventLocationDetailOutput(),
            wsEvents
        ))
        return zip(...reqs).pipe(
            tap((response: EduEventLocationDetailOutput[][]) => {
                ctx.patchState({
                    termLocations: response.map(v => {
                        if (v.length !== 1) {
                            ctx.patchState({
                                termLocations: initialStateModel.termLocations
                            });
                            throw new Error('Nepodařilo se nalézt místo');
                        }
                        return v[0];
                    })
                });
            }),
            catchError(e => {
                ctx.patchState({
                    termLocations: initialStateModel.termLocations
                });
                throw e;
            })
        );
    }

    @Action(EduEventUpdateLeader)
    updateEduEventFunctions(ctx: StateContext<EduEventDetailStateModel>,
        { eventId, members }: EduEventUpdateLeader) {
        const input = new EventEducationUpdateLeader(
            AppSettings.getString(USER_TOKEN),
            eventId,
        )
        members.forEach(m => {
            const roleName = EduEventLeaderNames[m.EventFunctionType]
            input['ID_Person' + roleName] = m.ID_Person || undefined;
            input[roleName + 'Note'] = m.Note || undefined;
        })
        if (eventId) {
            return this.webApiService.call(input,
                () => ({}),
                wsEvents
            ).pipe(
                tap((response: any) => {
                    feedbackMessage(FeedbackType.Success, "Vedení vzdělávací akce",
                        "Vedení vzdělávací akce bylo upraveno")
                }),
                catchError(e => {
                    if (e.error.includes('LeaderHasNoInstructorQualification'))
                        errorFeedback('EduEventUpdateFunctionsNoInstructorQualification')
                    else if (e.error.includes('PermissionDenied'))
                        errorFeedback('EduEventUpdateFunctionsPermissionDenied');
                    else
                        errorFeedback('EduEventUpdateFunctions');
                    throw e;
                })

            );

        }
    }

    @Action(EduEventInsertAssistant)
    insertEduEventAssistant(ctx: StateContext<EduEventDetailStateModel>,
        { eventId, member }: EduEventInsertAssistant) {
        const input = new EventFunctionInsertEducationAssistant(
            AppSettings.getString(USER_TOKEN),
            eventId, member.memberId, member.note
        )
        if (eventId) {
            return this.webApiService.call(input,
                () => ({}),
                wsEvents
            ).pipe(
                tap((response: any) => {
                    feedbackMessage(FeedbackType.Success, "Zastupce vedení vzdělávací akce",
                        "Zastupce vedení vzdělávací akce byl přidán.")
                }),
                errorFeedbackOperator('EduEventInsertAssistant')
            );

        }
    }
    @Action(EduEventUpdateAssistant)
    updateEduEventAssistant(ctx: StateContext<EduEventDetailStateModel>,
        { eventId, member }: EduEventUpdateAssistant) {
        const input = new EventFunctionUpdateEducationAssistant(
            AppSettings.getString(USER_TOKEN),
            member.roleId, eventId, member.memberId,
            member.note
        )
        const s = JSON.stringify(input)
        if (eventId) {
            return this.webApiService.call(input,
                () => ({}),
                wsEvents
            ).pipe(
                tap((response: any) => {
                    feedbackMessage(FeedbackType.Success, "Zastupce vedení vzdělávací akce",
                        "Zastupce vedení vzdělávací akce byl upraven.")
                }),
                errorFeedbackOperator('EduEventUpdateAssistant')
            );

        }
    }
    @Action(EduEventDeleteAssistant)
    deleteEduEventAssistant(ctx: StateContext<EduEventDetailStateModel>,
        { eventId, memberId }: EduEventDeleteAssistant) {
        const input = new EventFunctionDeleteEducationAssistant(
            AppSettings.getString(USER_TOKEN),
            memberId
        )
        if (eventId) {
            return this.webApiService.call(input,
                () => ({}),
                wsEvents
            ).pipe(
                tap((response: any) => {
                    feedbackMessage(FeedbackType.Success, "Zastupce vedení vzdělávací akce",
                        "Zastupce vedení vzdělávací akce byl přidán.")
                }),
                errorFeedbackOperator('EduEventInsertAssistant')

            );

        }
    }

}
