import { Action, Selector, State, StateContext } from '@ngxs/store';
import { catchError, tap } from 'rxjs/operators';
import { ApplicationSettings as AppSettings } 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 EduEventSearch, { EduEventSortFilter } from '~/pages/event/types/EduEventSearch';
import { LoadEduEventGroups, LoadEduEvents, LoadEduEventTypes, SetEduEventSearchParams, SetEduEventSortFilterParams, SetEduEvents } from './edu-event-search.actions';
import { EduEventOutput, EduEventType, EduEventGroup, EventEducationTypeAll, EventEducationGroupAll, EventEducationAll } from '~/pages/event/entities/edu-event-search.types';
import { isEqualJson } from '../../util';
import { EduEventSortKey, SortDirection } from '../../types/EventSorting';
import { latinise } from '~/core/utils/functions';

export interface EduEventSearchListStateModel {
    events: EduEventOutput[];
    filteredSortedEvents: EduEventOutput[];
    eventSearchParams: EduEventSearch;
    eventTypes: EduEventType[];
    eventGroups: EduEventGroup[];
    sortParams: EduEventSortFilter;
}

const initialStateModel: EduEventSearchListStateModel = {
    events: [],
    filteredSortedEvents: [],
    eventSearchParams: {
        eventName: '', year: (new Date()).getFullYear().toString(),
        group: null, type: null,
    },
    sortParams: {
        sortByKey: EduEventSortKey.REGISTRATION.toString(),
        sortDirection: SortDirection.ASC.toString(),
        onlyQualification: false,
    },
    eventTypes: [],
    eventGroups: [],
};

@State<EduEventSearchListStateModel>({
    name: 'eduEventSearchList',
    defaults: initialStateModel
})

export class EduEventSearchListState {

    @Selector()
    static isSearchSortDirty(state: EduEventSearchListStateModel) {
        const sort = isEqualJson(initialStateModel.eventSearchParams, state.eventSearchParams)
        const search = isEqualJson(initialStateModel.sortParams, state.sortParams)
        return !sort || !search;
    }
    @Selector()
    static getEventGroups(state: EduEventSearchListStateModel) {
        return state.eventGroups;
    }

    @Selector()
    static getEvents(state: EduEventSearchListStateModel) {
        return state.events;
    }
    @Selector()
    static getSortFilterParams(state: EduEventSearchListStateModel) {
        return state.sortParams;
    }

    @Selector()
    static getSortedFilteredEvents(state: EduEventSearchListStateModel) {
        return state.filteredSortedEvents;
    }

    @Selector()
    static getEventTypes(state: EduEventSearchListStateModel) {
        return state.eventTypes;
    }

    @Selector()
    static getEventSearchParams(state: EduEventSearchListStateModel) {
        return state.eventSearchParams;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }

    @Action(LoadEduEvents)
    loadEvents(ctx: StateContext<EduEventSearchListStateModel>, { opts }) {
        const { year, eventName, group, type } = ctx.getState().eventSearchParams;
        const tk = AppSettings.getString(USER_TOKEN);
        return this.webApiService.call(
            new EventEducationAll(tk,
                parseInt(opts.yearOpts ? opts.yearOpts : year, 10),
                latinise(eventName),
                type ? type && parseInt(type.id, 10) : null, group ? group.id : null
            ),
            () => new EduEventOutput(),
            wsEvents
        ).pipe(
            tap((response: EduEventOutput[]) => {
                ctx.patchState({
                    events: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    events: initialStateModel.events
                });

                throw e;
            })
        );
    }

    @Action(SetEduEvents)
    setEvents(ctx: StateContext<EduEventSearchListStateModel>, { events }) {
        ctx.patchState({
            events
        })

    }

    @Action(LoadEduEventTypes)
    loadEventTypes(ctx: StateContext<EduEventSearchListStateModel>) {
        return this.webApiService.call(
            new EventEducationTypeAll(
                APP_ID,
                AppSettings.getString(USER_TOKEN)
            ),
            () => new EduEventType(),
            wsEvents
        ).pipe(
            tap((response: EduEventType[]) => {
                ctx.patchState({
                    eventTypes: response
                });

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

    }

    @Action(LoadEduEventGroups)
    loadEventGroups(ctx: StateContext<EduEventSearchListStateModel>) {
        return this.webApiService.call(
            new EventEducationGroupAll(
                APP_ID,
                AppSettings.getString(USER_TOKEN)
            ),
            () => new EduEventGroup(),
            wsEvents
        ).pipe(
            tap((response: EduEventGroup[]) => {
                ctx.patchState({
                    eventGroups: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    eventGroups: initialStateModel.eventGroups
                });
                throw e;
            })
        );

    }

    @Action(SetEduEventSearchParams)
    setEventSearchParams(ctx: StateContext<EduEventSearchListStateModel>, action: SetEduEventSearchParams) {
        ctx.patchState({
            eventSearchParams: action.payload || { ...initialStateModel.eventSearchParams }
        });
    }


    @Action(SetEduEventSortFilterParams)
    setEventSortFilterParams(ctx: StateContext<EduEventSearchListStateModel>, action: SetEduEventSortFilterParams) {
        ctx.patchState({ sortParams: action.payload || { ...initialStateModel.sortParams } })
    }

}
