import { Action, Selector, State, StateContext } from '@ngxs/store';
import { tap, catchError } from 'rxjs/operators';
import { wsEvents } from '~/constants/api.constants';
import { USER_TOKEN } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import { ApplicationSettings as AppSettings } from '@nativescript/core';

import { CampEventOutput, CampEventStateOutput, EventCampAll, EventCampStateAll } from '../../entities/camp-event-search.types';
import { LoadCampEvents, LoadCampEventStates, SetCampEventSearchParams, SetCampEventSortParams } from './camp-event-search-list.actions';
import { CampEventSortKey, SortDirection, SortParams } from '../../types/EventSorting';
import { isEqualJson } from '../../util';
import { ScheduleType, EventRel } from '../../types/GenEventSearch';



export interface CampEventSearchListStateModel {
    sortParams: SortParams;
    events: CampEventOutput[];
    eventStates: CampEventStateOutput[];
    searchParams: CampEventSearch;
}
export interface CampEventSearch {
    year: string;
    state: string;
    schedule: string;
    relation: string;
    name: string;
    location: string;
    registrationNumber: string;
    // forEvaluation: boolean;
}

const initialStateModel: CampEventSearchListStateModel = {
    events: [],
    eventStates: [],
    searchParams: {
        year: (new Date()).getFullYear().toString(),
        state: null,
        schedule: 'year',
        relation: EventRel.ME_AND_MY_UNIT,
        name: '',
        location: '',
        // forEvaluation: null,
        registrationNumber: '',
    },
    sortParams: {
        sortByKey: CampEventSortKey.NAME,
        sortDirection: SortDirection.ASC,
    }
};


@State<CampEventSearchListStateModel>({
    name: 'CampEventSearchList',
    defaults: initialStateModel
})

export class CampEventSearchListState {
    constructor(
        private webApiService: WebApiService
    ) {
    }
    @Selector()
    static getEvents(state: CampEventSearchListStateModel) {
        return state.events;
    }

    @Selector()
    static getEventStates(state: CampEventSearchListStateModel) {
        return state.eventStates;
    }
    @Selector()
    static getSearchParams(state: CampEventSearchListStateModel) {
        return state.searchParams;
    }
    @Selector()
    static getSortParams(state: CampEventSearchListStateModel) {
        return state.sortParams;
    }
    @Selector()
    static isSearchSortDirty(state: CampEventSearchListStateModel) {
        const search = isEqualJson(initialStateModel.searchParams, state.searchParams)
        const sort = isEqualJson(initialStateModel.sortParams, state.sortParams)
        return !sort || !search;
    }


    @Action(LoadCampEvents)
    loadEvents(ctx: StateContext<CampEventSearchListStateModel>) {
        const { year, state, schedule, relation, name,
            registrationNumber, location } = ctx.getState().searchParams;
        //TODO forEvaluation
        const tk = AppSettings.getString(USER_TOKEN)
        const model = new EventCampAll(tk, name, state,
            schedule === ScheduleType.YEAR ? parseInt(year, 10) : null,
            schedule === ScheduleType.FUTURE ? true :
                schedule === ScheduleType.PAST ? false : null,
            relation === EventRel.ME_AND_MY_UNIT || null,
            relation === EventRel.UNIT_PLACE || null,
            relation === EventRel.ALL_UNIT_PLACE || null,
            registrationNumber, location
        );
        return this.webApiService.call(model,
            () => new CampEventOutput(),
            wsEvents
        ).pipe(
            tap((response: CampEventOutput[]) => {
                ctx.patchState({
                    events: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    events: initialStateModel.events
                });

                throw e;
            })
        );
    }

    @Action(SetCampEventSortParams)
    setSortParams(ctx: StateContext<CampEventSearchListStateModel>, { payload }: SetCampEventSortParams) {
        ctx.patchState({
            sortParams: payload || initialStateModel.sortParams
        })
    }
    @Action(SetCampEventSearchParams)
    setSearchParams(ctx: StateContext<CampEventSearchListStateModel>, { payload }: SetCampEventSearchParams) {
        ctx.patchState({
            searchParams: payload || initialStateModel.searchParams
        })
    }

    @Action(LoadCampEventStates)
    loadStates(ctx: StateContext<CampEventSearchListStateModel>) {
        const tk = AppSettings.getString(USER_TOKEN)
        return this.webApiService.call(
            new EventCampStateAll(tk),
            () => new CampEventStateOutput(),
            wsEvents
        ).pipe(
            tap((response: CampEventStateOutput[]) => {
                ctx.patchState({
                    eventStates: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    eventStates: initialStateModel.eventStates
                });

                throw e;
            })
        );
    }

}
