import { ApplicationSettings, ImageSource } from '@nativescript/core';
import { Action, Selector, State, StateContext } from '@ngxs/store';
import { catchError, tap } from 'rxjs/operators';
import { APP_ID, wsMessage, wsOrganizationUnit, wsUserManagement } from '~/constants/api.constants';
import { USER_ID, USER_TOKEN } from '~/constants/login-constants';
import { MessageAllWeb } from '~/core/entities/input/messageAllWeb';
import { MessageAllWebOutput } from '~/core/entities/output/messageAllWebOutput';
import { WebApiService } from '~/core/services/web-api.service';
import {
    LoadMessageAllWebUnread,
    LoadPersonPhoto,
    LoadUserRoleAll,
    StartRoleLoading,
    StopRoleLoading
} from '~/core/state-mgmt/app.actions';
import { PersonPhoto } from '~/pages/search-person/entities/input/personPhoto';
import { PersonPhotoOutput } from '~/pages/search-person/entities/output/personPhotoOutput';
import { UserRoleAll } from '../entities/input/userRoleAll';
import { UserRoleAllOutput } from '../entities/output/userRoleAllOutput';

export interface AppStateModel {
    loadingPersonPhoto: boolean;
    loadingRole: boolean;
    loadingMessageAllWebUnread: boolean;
    loadingUserRoleAll: boolean;
    personPhotoResource: ImageSource;
    messageAllWebUnread: MessageAllWebOutput[];
    userRoleAll: UserRoleAllOutput[];
}

const initialStateModel: AppStateModel = {
    loadingPersonPhoto: false,
    loadingRole: false,
    loadingMessageAllWebUnread: false,
    loadingUserRoleAll: false,
    personPhotoResource: null,
    messageAllWebUnread: [],
    userRoleAll: []
};

@State<AppStateModel>({
    name: 'app',
    defaults: initialStateModel
})

export class AppState {

    @Selector()
    static getPersonPhotoResource(state: AppStateModel) {
        return state.personPhotoResource;
    }

    @Selector()
    static getMessageAllWebUnread(state: AppStateModel) {
        return state.messageAllWebUnread;
    }

    @Selector()
    static getUserRoleAll(state: AppStateModel) {
        return state.userRoleAll;
    }

    @Selector()
    static isLoading(state: AppStateModel) {
        return state.loadingPersonPhoto
            || state.loadingMessageAllWebUnread;
    }

    @Selector()
    static isRoleLoading(state: AppStateModel) {
        return state.loadingRole;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }

    @Action(LoadPersonPhoto)
    loadPersonPhoto(ctx: StateContext<AppStateModel>, action: LoadPersonPhoto) {
        ctx.patchState({
            loadingPersonPhoto: true
        });

        return this.webApiService.call(
            new PersonPhoto(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId, 'small'),
            () => new PersonPhotoOutput(),
            wsOrganizationUnit
        ).pipe(
            tap((response: PersonPhotoOutput[]) => {
                if (response.length === 1) {
                    ctx.patchState({
                        loadingPersonPhoto: false,
                        personPhotoResource: ImageSource.fromBase64Sync(response[0].PhotoContent)
                    });
                } else {
                    ctx.patchState({
                        loadingPersonPhoto: false,
                        personPhotoResource: initialStateModel.personPhotoResource
                    });
                    throw new Error('Vyskytla se chyba při získání fotky profilu');
                }
            }),
            catchError(e => {
                ctx.patchState({
                    loadingPersonPhoto: false,
                    personPhotoResource: initialStateModel.personPhotoResource
                });

                throw e;
            })
        );
    }

    @Action(StartRoleLoading)
    startRoleLoading(ctx: StateContext<AppStateModel>, action: StartRoleLoading) {
        ctx.patchState({
            loadingRole: true
        });
    }

    @Action(StopRoleLoading)
    stopRoleLoading(ctx: StateContext<AppStateModel>, action: StopRoleLoading) {
        ctx.patchState({
            loadingRole: false
        });
    }

    /**
     * Load messages unread
     *
     * @param {StateContext<AppStateModel>} ctx
     * @param {LoadMessageAllWebUnread} action
     * @returns {Observable<any>}
     */
    @Action(LoadMessageAllWebUnread)
    loadMessageAllWeb(ctx: StateContext<AppStateModel>, action: LoadMessageAllWebUnread) {
        ctx.patchState({
            loadingMessageAllWebUnread: true
        });

        return this.webApiService.call(
            new MessageAllWeb(APP_ID, ApplicationSettings.getString(USER_TOKEN), false, true),
            () => new MessageAllWebOutput(),
            wsMessage
        ).pipe(
            tap((response: MessageAllWebOutput[]) => {
                ctx.patchState({
                    loadingMessageAllWebUnread: false,
                    messageAllWebUnread: response.slice(0, 3)
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingMessageAllWebUnread: false,
                    messageAllWebUnread: initialStateModel.messageAllWebUnread
                });

                throw e;
            })
        );
    }

    /**
     * Load messages unread
     *
     * @param {StateContext<AppStateModel>} ctx
     * @param {LoadUserRoleAll} action
     * @returns {Observable<any>}
     */
    @Action(LoadUserRoleAll)
    loadUserRoleAll(ctx: StateContext<AppStateModel>, action: LoadUserRoleAll) {
        ctx.patchState({
            loadingUserRoleAll: true
        });

        return this.webApiService.call(
            new UserRoleAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), ApplicationSettings.getNumber(USER_ID)),
            () => new UserRoleAllOutput(),
            wsUserManagement
        ).pipe(
            tap((response: UserRoleAllOutput[]) => {
                ctx.patchState({
                    loadingUserRoleAll: false,
                    userRoleAll: response
                });
            }),
            catchError(e => {
                ctx.patchState({
                    loadingUserRoleAll: false,
                    userRoleAll: initialStateModel.userRoleAll
                });

                throw e;
            })
        );
    }
}
