import { ApplicationSettings } from '@nativescript/core';
import { Action, Selector, State, StateContext } from '@ngxs/store';
import { catchError, tap } from 'rxjs/operators';
import { APP_ID, wsOrganizationUnit } from '~/constants/api.constants';
import { USER_TOKEN, USER_UNIT_ID } from '~/constants/login-constants';
import { BaseOutput } from '~/core/entities/output/baseOutput';
import { WebApiService } from '~/core/services/web-api.service';
import { AdvertisingCategoryDelete } from '../entities/input/advertisingCategoryDelete';
import { AdvertisingCategoryDetail } from '../entities/input/advertisingCategoryDetail';
import { AdvertisingCategoryInsert } from '../entities/input/advertisingCategoryInsert';
import { AdvertisingCategoryUpdate } from '../entities/input/advertisingCategoryUpdate';
import { AdvertisingCategoryDetailResponse } from '../entities/output/advertisingCategoryDetailResponse';
import {
    DeleteAdvertisingCategory,
    InsertAdvertisingCategory,
    LoadAdvertisingCategoryDetail,
    UpdateAdvertisingCategory
} from './advertising-category.actions';

export interface AdvertisingCategoryStateModel {
    loadingAdvertisingCategoryDetail: boolean;
    loadingAdvertisingCategoryInsert: boolean;
    loadingAdvertisingCategoryDelete: boolean;
    loadingAdvertisingCategoryUpdate: boolean;
    advertisingCategoryDetail: AdvertisingCategoryDetailResponse;
}

const initialStateModel: AdvertisingCategoryStateModel = {
    loadingAdvertisingCategoryDetail: false,
    loadingAdvertisingCategoryInsert: false,
    loadingAdvertisingCategoryDelete: false,
    loadingAdvertisingCategoryUpdate: false,
    advertisingCategoryDetail: new AdvertisingCategoryDetailResponse()
};

@State<AdvertisingCategoryStateModel>({
    name: 'advertisingCategory',
    defaults: initialStateModel
})
export class AdvertisingCategoryState {
    @Selector()
    static getAdvertisingCategoryDetail(state: AdvertisingCategoryStateModel) {
        return state.advertisingCategoryDetail;
    }

    @Selector()
    static isLoading(state: AdvertisingCategoryStateModel) {
        return state.loadingAdvertisingCategoryDetail ||
            state.loadingAdvertisingCategoryInsert ||
            state.loadingAdvertisingCategoryDelete ||
            state.loadingAdvertisingCategoryUpdate;
    }

    constructor(
        private webApiService: WebApiService) {
    }

    /**
     * Load advertising category detail
     *
     * @param {StateContext<AdvertisingCategoryStateModel>} ctx
     * @param {LoadAdvertisingCategoryDetail} action
     * @returns {Observable<any>}
     */
    @Action(LoadAdvertisingCategoryDetail)
    loadAdvertisingCategoryDetail(ctx: StateContext<AdvertisingCategoryStateModel>, action: LoadAdvertisingCategoryDetail) {
        ctx.patchState({
            loadingAdvertisingCategoryDetail: true
        });

        return this.webApiService.call(
            new AdvertisingCategoryDetail(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.id),
            () => new AdvertisingCategoryDetailResponse(),
            wsOrganizationUnit
        ).pipe(
            tap((response: AdvertisingCategoryDetailResponse[]) => {
                ctx.patchState({
                    loadingAdvertisingCategoryDetail: false,
                    advertisingCategoryDetail: response[0]
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingAdvertisingCategoryDetail: false,
                    advertisingCategoryDetail: initialStateModel.advertisingCategoryDetail
                });

                throw e;
            })
        );
    }

    /**
     * Insert new advertising category
     *
     * @param {StateContext<AdvertisingCategoryStateModel>} ctx
     * @param {InsertAdvertisingCategory} action
     * @returns {Observable<any>}
     */
    @Action(InsertAdvertisingCategory)
    insertAdvertisingCategory(ctx: StateContext<AdvertisingCategoryStateModel>, action: InsertAdvertisingCategory) {
        ctx.patchState({
            loadingAdvertisingCategoryInsert: true
        });

        return this.webApiService.call(
            new AdvertisingCategoryInsert(
                APP_ID,
                ApplicationSettings.getString(USER_TOKEN),
                ApplicationSettings.getNumber(USER_UNIT_ID),
                action.ageFrom,
                action.ageTo,
                action.sexId,
                action.sex,
                action.note,
                action.meetingDateId),
            () => new BaseOutput(),
            wsOrganizationUnit
        ).pipe(
            tap((response) => {
                ctx.patchState({
                    loadingAdvertisingCategoryInsert: false
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingAdvertisingCategoryInsert: false
                });

                throw e;
            })
        );
    }

    /**
     * Delete existing advertising category
     *
     * @param {StateContext<AdvertisingCategoryStateModel>} ctx
     * @param {DeleteAdvertisingCategory} action
     * @returns {Observable<any>}
     */
    @Action(DeleteAdvertisingCategory)
    deleteAdvertisingCategory(ctx: StateContext<AdvertisingCategoryStateModel>, action: DeleteAdvertisingCategory) {
        ctx.patchState({
            loadingAdvertisingCategoryDelete: true
        });

        return this.webApiService.call(
            new AdvertisingCategoryDelete(
                APP_ID,
                ApplicationSettings.getString(USER_TOKEN),
                action.id),
            () => new BaseOutput(),
            wsOrganizationUnit
        ).pipe(
            tap((response) => {
                ctx.patchState({
                    loadingAdvertisingCategoryDelete: false
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingAdvertisingCategoryDelete: false
                });

                throw e;
            })
        );
    }

    /**
     * Update existing advertising category
     *
     * @param {StateContext<AdvertisingCategoryStateModel>} ctx
     * @param {UpdateAdvertisingCategory} action
     * @returns {Observable<any>}
     */
    @Action(UpdateAdvertisingCategory)
    updateAdvertisingCategory(ctx: StateContext<AdvertisingCategoryStateModel>, action: UpdateAdvertisingCategory) {
        ctx.patchState({
            loadingAdvertisingCategoryUpdate: true
        });

        return this.webApiService.call(
            new AdvertisingCategoryUpdate(
                APP_ID,
                ApplicationSettings.getString(USER_TOKEN),
                ApplicationSettings.getNumber(USER_UNIT_ID),
                action.id,
                action.ageFrom,
                action.ageTo,
                action.sexId,
                action.sex,
                action.note,
                action.meetingDateId),
            () => new BaseOutput(),
            wsOrganizationUnit
        ).pipe(
            tap((response) => {
                ctx.patchState({
                    loadingAdvertisingCategoryUpdate: false
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingAdvertisingCategoryUpdate: false
                });

                throw e;
            })
        );
    }
}
