import { Injectable } from '@angular/core';
import { ApplicationSettings } from '@nativescript/core';
import { Feedback, FeedbackType } from 'nativescript-feedback';
import { BehaviorSubject, Observable, OperatorFunction } from 'rxjs';
import { catchError, finalize, map } from 'rxjs/operators';
import { erroredActions } from '~/constants/action-errored-catch.constants';
import { APP_ID, wsOrganizationUnit } from '~/constants/api.constants';
import { USER_TOKEN } from '~/constants/login-constants';
import { WebApiService } from '~/core/services/web-api.service';
import { UnitContactAll } from '~/pages/unit/entities/input/unitContactAll';
import { UnitDetail } from '~/pages/unit/entities/input/unitDetail';
import { UnitTreeAll } from '~/pages/unit/entities/input/unitTreeAll';
import { UnitContactAllOutput } from '~/pages/unit/entities/output/unitContactAllOutput';
import { UnitDetailOutput } from '~/pages/unit/entities/output/unitDetailOutput';
import { UnitTreeAllOutput } from '~/pages/unit/entities/output/unitTreeAllOutput';

/**
 * Services that takes care of communication with the skautIs web services for Unit page
 */
@Injectable()
export class UnitService {
    loading: Observable<boolean>;
    private loadingSource = new BehaviorSubject<boolean>(false);
    private feedback: Feedback;

    constructor(
        private webApiService: WebApiService
    ) {
        this.loading = this.loadingSource.asObservable();
        this.feedback = new Feedback();
    }

    getUnitDetail(id: number) {
        this.loadingSource.next(true);

        return this.webApiService.call(
            new UnitDetail(APP_ID, ApplicationSettings.getString(USER_TOKEN), id),
            () => new UnitDetailOutput(),
            wsOrganizationUnit
        ).pipe(
            map((response: UnitDetailOutput[]) => {
                return response.length === 1 ? response[0] : null;
            }),
            this.errorFeedbackOperator('LoadUnitDetail'),
            finalize(() => this.loadingSource.next(false))
        );
    }

    getParentUnitName(id: number) {
        this.loadingSource.next(true);

        return this.webApiService.call(
            new UnitDetail(APP_ID, ApplicationSettings.getString(USER_TOKEN), id),
            () => new UnitDetailOutput(),
            wsOrganizationUnit
        ).pipe(
            map((response: UnitDetailOutput[]) => response.length === 1 ? response[0].DisplayName : ''),
            this.errorFeedbackOperator('LoadParentUnitName'),
            finalize(() => this.loadingSource.next(false))
        );
    }

    getUnitTree(id: number): Observable<UnitTreeAllOutput[]> {
        this.loadingSource.next(true);

        return this.webApiService.call(
            new UnitTreeAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), id),
            () => new UnitTreeAllOutput(),
            wsOrganizationUnit
        ).pipe(
            this.errorFeedbackOperator('LoadUnitTree'),
            finalize(() => this.loadingSource.next(false))
        );
    }

    getUnitContacts(id: number): Observable<UnitContactAllOutput[]> {
        this.loadingSource.next(true);

        return this.webApiService.call(
            new UnitContactAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), id),
            () => new UnitContactAllOutput(),
            wsOrganizationUnit
        ).pipe(
            this.errorFeedbackOperator('LoadUnitContacts'),
            finalize(() => this.loadingSource.next(false))
        );
    }

    errorFeedbackOperator<T>(actionName: string): OperatorFunction<T, T> {
        return catchError(e => {
            const selectedAction = erroredActions.find((eA) => eA.name === actionName);
            this.feedback.show({
                title: 'ERROR',
                type: FeedbackType.Error,
                message: selectedAction ? selectedAction.message : 'Vyskytla se chyba při komunikaci se službou skautIS. Zkontrolujte připojení nebo to zkuste později.'
            });
            throw e;
        });
    }
}
