import { Action, Selector, State, StateContext } from '@ngxs/store';
import { catchError, tap } from 'rxjs/operators';
import { ApplicationSettings as AppSettings } from '@nativescript/core';

import { wsEvents } from '~/constants/api.constants';
import { USER_TOKEN } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import { CandidateAll, CongEventCandidateOutput, CongEventDetailOutput, CongEventFunctionAllMaxOutput, EventCongressDecisionAll, EventCongressDetail, EventCongressFunctionAll, EventCongressFunctionAllMax } from '../../entities/cong-event-detail.types';
import { LoadCongEventCandidates, LoadCongEventDecisions, LoadCongEventDetail, LoadCongEventFunctions, LoadCongEventFunctionsMax } from './cong-event-detail.actions';
import { CongEventFunctionOutput, CongEventDecisionOutput } from './../../entities/cong-event-detail.types';

export interface CongEventDetailStateModel {
    eventDetail: CongEventDetailOutput;
    candidates: CongEventCandidateOutput[];
    functions: CongEventFunctionOutput[];
    maxFunctions: CongEventFunctionAllMaxOutput[];
    decisions: CongEventDecisionOutput[];
}

const initialStateModel: CongEventDetailStateModel = {
    candidates: [],
    eventDetail: null,
    functions: [],
    maxFunctions: [],
    decisions: [],
};

@State<CongEventDetailStateModel>({
    name: 'congEventDetail',
    defaults: initialStateModel
})
export class CongEventDetailState {
    @Selector()
    static getEventDetail(state: CongEventDetailStateModel) {
        return state.eventDetail;
    }
    @Selector()
    static getCandidates(state: CongEventDetailStateModel) {
        return state.candidates;
    }
    @Selector()
    static getFunctions(state: CongEventDetailStateModel) {
        return state.functions;
    }
    @Selector()
    static getFunctionsMax(state: CongEventDetailStateModel) {
        return state.maxFunctions;
    }
    @Selector()
    static getDecisions(state: CongEventDetailStateModel) {
        return state.decisions;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }
    @Action(LoadCongEventCandidates)
    loadEventCandidates(ctx: StateContext<CongEventDetailStateModel>, action: LoadCongEventCandidates) {
        const tk = AppSettings.getString(USER_TOKEN)
        if (action.eventId) {
            return this.webApiService.call(
                new CandidateAll(tk, action.eventId),
                () => new CongEventCandidateOutput(),
                wsEvents
            ).pipe(
                tap((response: CongEventCandidateOutput[]) => {
                    ctx.patchState({
                        candidates: response
                    });

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

                    throw e;
                })
            );
        }
    }


    @Action(LoadCongEventDetail)
    loadEventDetail(ctx: StateContext<CongEventDetailStateModel>, action: LoadCongEventDetail) {
        const tk = AppSettings.getString(USER_TOKEN)
        if (action.id) {
            return this.webApiService.call(
                new EventCongressDetail(tk, action.id),
                () => new CongEventDetailOutput(),
                wsEvents
            ).pipe(
                tap((response: CongEventDetailOutput[]) => {
                    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(LoadCongEventFunctions)
    loadEventFunctions(ctx: StateContext<CongEventDetailStateModel>, action: LoadCongEventFunctions) {
        const tk = AppSettings.getString(USER_TOKEN)
        if (action.id) {
            return this.webApiService.call(
                new EventCongressFunctionAll(tk, action.id),
                () => new CongEventFunctionOutput(),
                wsEvents
            ).pipe(
                tap((response: CongEventFunctionOutput[]) => {
                    ctx.patchState({
                        functions: response
                    });

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

                    throw e;
                })
            );
        }
    }
    @Action(LoadCongEventFunctionsMax)
    loadCongEventFunctionsMax(ctx: StateContext<CongEventDetailStateModel>, action: LoadCongEventFunctionsMax) {
        const tk = AppSettings.getString(USER_TOKEN)
        if (action.id) {
            return this.webApiService.call(
                new EventCongressFunctionAllMax(tk, action.id),
                () => new CongEventFunctionAllMaxOutput(),
                wsEvents
            ).pipe(
                tap((response: CongEventFunctionAllMaxOutput[]) => {
                    ctx.patchState({
                        maxFunctions: response
                    });

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

                    throw e;
                })
            );
        }
    }

    @Action(LoadCongEventDecisions)
    loadCongEventDecisions(ctx: StateContext<CongEventDetailStateModel>, action: LoadCongEventDecisions) {
        const tk = AppSettings.getString(USER_TOKEN);

        if (action.id) {
            return this.webApiService.call(
                new EventCongressDecisionAll(tk, action.id),
                () => new CongEventDecisionOutput(),
                wsEvents
            ).pipe(
                tap((response: CongEventDecisionOutput[]) => {
                    ctx.patchState({
                        decisions: response
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        decisions: initialStateModel.decisions
                    });

                    throw e;
                })
            );
        }
    }
}
