import { ApplicationSettings } from '@nativescript/core';
import { Action, Selector, State, StateContext } from '@ngxs/store';
import { catchError, tap } from 'rxjs/operators';
import { APP_ID, wsMaterial } from '~/constants/api.constants';
import { USER_ID, USER_TOKEN, USER_UNIT_ID } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import { WarehouseAll } from '../entities/input/warehouseAll';
import { WarehouseItemReservationInsert } from '../entities/input/warehouseItemReservationInsert';
import { WarehouseAllOutput } from '../entities/output/warehouseAllOutput';
import { WarehouseItemReservationInsertOutput } from '../entities/output/warehouseItemReservationInsertOutput';
import { CreateReservationInsert, LoadWarehouseAll } from './reservation-new.action';

export interface ReservationNewStateModel {
    loadingReservationInsert: boolean;
    loadingWarehouseAll: boolean;
    warehouseItemReservationInsert: WarehouseItemReservationInsertOutput;
    warehouseAll: WarehouseAllOutput[];
}

const initialStateModel: ReservationNewStateModel = {
    loadingReservationInsert: false,
    loadingWarehouseAll: false,
    warehouseItemReservationInsert: null,
    warehouseAll: []
};

@State<ReservationNewStateModel>({
    name: 'reservationNew',
    defaults: initialStateModel
})
export class ReservationNewState {
    @Selector()
    static getReservationInsert(state: ReservationNewStateModel) {
        return state.warehouseItemReservationInsert;
    }

    @Selector()
    static getWarehouseAll(state: ReservationNewStateModel) {
        return state.warehouseAll;
    }

    @Selector()
    static isLoading(state: ReservationNewStateModel) {
        return state.loadingReservationInsert
            || state.loadingWarehouseAll;
    }

    constructor(
        private webApiService: WebApiService
    ) { }

    /**
     * create reservation insert
     *
     * @param {StateContext<ReservationStateModel>} ctx
     * @param {CreateReservationInsert} action
     * @returns {Observable<any>}
     */
    @Action(CreateReservationInsert)
    createReservationInsert(ctx: StateContext<ReservationNewStateModel>, action: CreateReservationInsert) {
        ctx.patchState({
            loadingReservationInsert: true
        });

        if (action.id) {
            return this.webApiService.call(
                new WarehouseItemReservationInsert(
                    APP_ID,
                    ApplicationSettings.getString(USER_TOKEN),
                    ApplicationSettings.getNumber(USER_UNIT_ID),
                    ApplicationSettings.getNumber(USER_ID),
                    action.idWarehouse,
                    action.id,
                    action.idUnitOrig,
                    action.startDate,
                    action.endDate,
                    action.person,
                    action.phone,
                    action.email),
                () => new WarehouseItemReservationInsertOutput(),
                wsMaterial
            ).pipe(
                tap((response: WarehouseItemReservationInsertOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            loadingReservationInsert: false,
                            warehouseItemReservationInsert: response[0]
                        });
                    } else {
                        ctx.patchState({
                            loadingReservationInsert: false,
                            warehouseItemReservationInsert: initialStateModel.warehouseItemReservationInsert
                        });
                        throw new Error('Nepodařilo se provest rezervaci polozky');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingReservationInsert: false,
                        warehouseItemReservationInsert: initialStateModel.warehouseItemReservationInsert
                    });

                    throw e;
                })
            );
        } else {
            ctx.patchState({
                loadingReservationInsert: false
            });
        }
    }

    /**
     * Load warehouses
     *
     * @param {StateContext<ReservationNewStateModel>} ctx
     * @param {LoadWarehouseAll} action
     * @returns {Observable<any>}
     */
    @Action(LoadWarehouseAll)
    loadWarehouseAll(ctx: StateContext<ReservationNewStateModel>, action: LoadWarehouseAll) {
        ctx.patchState({
            loadingWarehouseAll: true
        });

        return this.webApiService.call(
            new WarehouseAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), ApplicationSettings.getNumber(USER_UNIT_ID)),
            () => new WarehouseAllOutput(),
            wsMaterial
        ).pipe(
            tap((response: WarehouseAllOutput[]) => {
                ctx.patchState({
                    loadingWarehouseAll: false,
                    warehouseAll: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingWarehouseAll: false,
                    warehouseAll: initialStateModel.warehouseAll
                });

                throw e;
            })
        );
    }
}
