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 } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import { FunctionAll } from '~/pages/unit/entities/input/functionAll';
import { UnitContactAll } from '~/pages/unit/entities/input/unitContactAll';
import { UnitDetail } from '~/pages/unit/entities/input/unitDetail';
import { FunctionAllOutput } from '~/pages/unit/entities/output/functionAllOutput';
import { UnitContactAllOutput } from '~/pages/unit/entities/output/unitContactAllOutput';
import { UnitDetailOutput } from '~/pages/unit/entities/output/unitDetailOutput';
import { LoadUnitContacts, LoadUnitDetail, LoadUnitFunctions } from '~/pages/unit/state-mgmt/unit-detail.actions';

export interface UnitDetailStateModel {
    loadingUnitDetail: boolean;
    loadingUnitContacts: boolean;
    loadingUnitFunctions: boolean;
    unitDetail: UnitDetailOutput;
    unitContacts: UnitContactAllOutput[];
    unitFunctions: FunctionAllOutput[];
}

const initialStateModel: UnitDetailStateModel = {
    loadingUnitDetail: false,
    loadingUnitContacts: false,
    loadingUnitFunctions: false,
    unitDetail: null,
    unitContacts: [],
    unitFunctions: []
};

@State<UnitDetailStateModel>({
    name: 'unitDetail',
    defaults: initialStateModel
})
export class UnitDetailState {

    @Selector()
    static getUnitDetail(state: UnitDetailStateModel) {
        return state.unitDetail;
    }

    @Selector()
    static getUnitFunctions(state: UnitDetailStateModel) {
        return state.unitFunctions;
    }

    @Selector()
    static getUnitContacts(state: UnitDetailStateModel) {
        return state.unitContacts;
    }

    @Selector()
    static isLoading(state: UnitDetailStateModel) {
        return state.loadingUnitDetail || state.loadingUnitFunctions || state.loadingUnitContacts;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }

    @Action(LoadUnitDetail)
    loadUnitDetail(ctx: StateContext<UnitDetailStateModel>, action: LoadUnitDetail) {
        ctx.patchState({
            loadingUnitDetail: true
        });

        if (action.unitId) {
            return this.webApiService.call(
                new UnitDetail(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.unitId),
                () => new UnitDetailOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: UnitDetailOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            loadingUnitDetail: false,
                            unitDetail: response[0]
                        });
                    } else {
                        ctx.patchState({
                            loadingUnitDetail: false,
                            unitDetail: initialStateModel.unitDetail
                        });
                        throw new Error('Nepodařilo se načíst detail jednotky');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingUnitDetail: false,
                        unitDetail: initialStateModel.unitDetail
                    });

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

    @Action(LoadUnitFunctions)
    loadUnitFunctions(ctx: StateContext<UnitDetailStateModel>, action: LoadUnitFunctions) {
        ctx.patchState({
            loadingUnitFunctions: true
        });

        if (action.unitId) {
            return this.webApiService.call(
                new FunctionAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.unitId),
                () => new FunctionAllOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: FunctionAllOutput[]) => {
                    ctx.patchState({
                        loadingUnitFunctions: false,
                        unitFunctions: response
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingUnitFunctions: false,
                        unitFunctions: initialStateModel.unitFunctions
                    });

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

    @Action(LoadUnitContacts)
    loadUnitContacts(ctx: StateContext<UnitDetailStateModel>, action: LoadUnitContacts) {
        ctx.patchState({
            loadingUnitContacts: true
        });

        if (action.unitId) {
            return this.webApiService.call(
                new UnitContactAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.unitId),
                () => new UnitContactAllOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: UnitContactAllOutput[]) => {
                    ctx.patchState({
                        loadingUnitContacts: false,
                        unitContacts: response
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingUnitContacts: false,
                        unitContacts: initialStateModel.unitContacts
                    });

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