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 { FunctionAllPerson } from '~/pages/search-person/entities/input/functionAllPerson';
import { MembershipAllPerson } from '~/pages/search-person/entities/input/membershipAllPerson';
import { OfferAll } from '~/pages/search-person/entities/input/offerAll';
import { PersonContactAll } from '~/pages/search-person/entities/input/personContactAll';
import { PersonDetail } from '~/pages/search-person/entities/input/personDetail';
import { PersonOtherDetail } from '~/pages/search-person/entities/input/personOtherDetail';
import { PersonPhoto } from '~/pages/search-person/entities/input/personPhoto';
import { QualificationAll } from '~/pages/search-person/entities/input/qualificationAll';
import { FunctionAllPersonOutput } from '~/pages/search-person/entities/output/functionAllPersonOutput';
import { MembershipAllPersonOutput } from '~/pages/search-person/entities/output/membershipAllPersonOutput';
import { OfferAllOutput } from '~/pages/search-person/entities/output/offerAllOutput';
import { PersonContactAllOutput } from '~/pages/search-person/entities/output/personContactAllOutput';
import { PersonDetailOutput } from '~/pages/search-person/entities/output/personDetailOutput';
import { PersonOtherDetailOutput } from '~/pages/search-person/entities/output/personOtherDetailOutput';
import { PersonPhotoOutput } from '~/pages/search-person/entities/output/personPhotoOutput';
import { QualificationAllOutput } from '~/pages/search-person/entities/output/qualificationAllOutput';
import {
    ClearPersonDetailData,
    LoadPersonContacts,
    LoadPersonDetail,
    LoadPersonFunctions,
    LoadPersonMemberships,
    LoadPersonOffers,
    LoadPersonOtherDetail,
    LoadPersonPhoto,
    LoadPersonQualifications
} from '~/pages/search-person/state-mgmt/search-person-detail.actions';

export interface SearchPersonDetailStateModel {
    loadingPersonDetail: boolean;
    loadingPersonOtherDetail: boolean;
    loadingPersonPhoto: boolean;
    loadingPersonContacts: boolean;
    loadingPersonMemberships: boolean;
    loadingPersonFunctions: boolean;
    loadingPersonQualifications: boolean;
    loadingPersonOffers: boolean;
    personDetail: PersonDetailOutput;
    personOtherDetail: PersonOtherDetailOutput;
    personPhoto: PersonPhotoOutput;
    personContacts: PersonContactAllOutput[];
    personMemberships: MembershipAllPersonOutput[];
    personFunctions: FunctionAllPersonOutput[];
    personQualifications: QualificationAllOutput[];
    personOffers: OfferAllOutput[];
}

const initialStateModel: SearchPersonDetailStateModel = {
    loadingPersonDetail: false,
    loadingPersonOtherDetail: false,
    loadingPersonPhoto: false,
    loadingPersonContacts: false,
    loadingPersonMemberships: false,
    loadingPersonFunctions: false,
    loadingPersonQualifications: false,
    loadingPersonOffers: false,
    personDetail: null,
    personOtherDetail: null,
    personPhoto: null,
    personContacts: [],
    personMemberships: [],
    personFunctions: [],
    personQualifications: [],
    personOffers: []
};

@State<SearchPersonDetailStateModel>({
    name: 'searchPersonDetail',
    defaults: initialStateModel
})
export class SearchPersonDetailState {

    @Selector()
    static getPersonDetail(state: SearchPersonDetailStateModel) {
        return state.personDetail;
    }

    @Selector()
    static getPersonOtherDetail(state: SearchPersonDetailStateModel) {
        return state.personOtherDetail;
    }

    @Selector()
    static getPersonPhoto(state: SearchPersonDetailStateModel) {
        return state.personPhoto;
    }

    @Selector()
    static getPersonContacts(state: SearchPersonDetailStateModel) {
        return state.personContacts;
    }

    @Selector()
    static getPersonMemberships(state: SearchPersonDetailStateModel) {
        return state.personMemberships;
    }

    @Selector()
    static getPersonFunctions(state: SearchPersonDetailStateModel) {
        return state.personFunctions;
    }

    @Selector()
    static getPersonQualifications(state: SearchPersonDetailStateModel) {
        return state.personQualifications;
    }

    @Selector()
    static getPersonOffers(state: SearchPersonDetailStateModel) {
        return state.personOffers;
    }

    @Selector()
    static isLoading(state: SearchPersonDetailStateModel) {
        return state.loadingPersonDetail
            || state.loadingPersonOtherDetail
            || state.loadingPersonPhoto
            || state.loadingPersonContacts
            || state.loadingPersonMemberships
            || state.loadingPersonFunctions
            || state.loadingPersonQualifications
            || state.loadingPersonOffers;
    }

    constructor(
        private webApiService: WebApiService
    ) {
    }

    @Action(LoadPersonDetail)
    loadPersonDetail(ctx: StateContext<SearchPersonDetailStateModel>, action: LoadPersonDetail) {
        ctx.patchState({
            loadingPersonDetail: true
        });
        if (action.personId) {
            return this.webApiService.call(
                new PersonDetail(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId),
                () => new PersonDetailOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: PersonDetailOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            loadingPersonDetail: false,
                            personDetail: response[0]
                        });
                    } else {
                        ctx.patchState({
                            loadingPersonDetail: false,
                            personDetail: initialStateModel.personDetail
                        });
                        throw new Error('Nepodařilo se nalézt detail osoby');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingPersonDetail: false,
                        personDetail: initialStateModel.personDetail
                    });

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

    @Action(LoadPersonOtherDetail)
    loadPersonOtherDetail(ctx: StateContext<SearchPersonDetailStateModel>, action: LoadPersonOtherDetail) {
        ctx.patchState({
            loadingPersonOtherDetail: true
        });
        if (action.personId) {
            return this.webApiService.call(
                new PersonOtherDetail(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId),
                () => new PersonOtherDetailOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: PersonOtherDetailOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            loadingPersonOtherDetail: false,
                            personOtherDetail: response[0]
                        });
                    } else {
                        ctx.patchState({
                            loadingPersonOtherDetail: false,
                            personOtherDetail: initialStateModel.personOtherDetail
                        });
                        throw new Error('Nepodařilo se nalézt informace o osobě');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingPersonOtherDetail: false,
                        personOtherDetail: initialStateModel.personOtherDetail
                    });

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

    @Action(LoadPersonPhoto)
    loadPersonPhoto(ctx: StateContext<SearchPersonDetailStateModel>, action: LoadPersonPhoto) {
        ctx.patchState({
            loadingPersonPhoto: true
        });
        if (action.personId) {
            return this.webApiService.call(
                new PersonPhoto(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId, 'normal'),
                () => new PersonPhotoOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: PersonPhotoOutput[]) => {
                    if (response.length === 1) {
                        ctx.patchState({
                            loadingPersonPhoto: false,
                            personPhoto: response[0]
                        });
                    } else {
                        ctx.patchState({
                            loadingPersonPhoto: false,
                            personPhoto: initialStateModel.personPhoto
                        });
                        throw new Error('Nepodařilo se nalézt foto osoby');
                    }
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingPersonPhoto: false,
                        personPhoto: initialStateModel.personPhoto
                    });

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

    @Action(LoadPersonContacts)
    loadPersonContacts(ctx: StateContext<SearchPersonDetailStateModel>, action: LoadPersonContacts) {
        ctx.patchState({
            loadingPersonContacts: true
        });

        if (action.personId) {
            return this.webApiService.call(
                new PersonContactAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId),
                () => new PersonContactAllOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: PersonContactAllOutput[]) => {
                    ctx.patchState({
                        loadingPersonContacts: false,
                        personContacts: response
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingPersonContacts: false,
                        personContacts: initialStateModel.personContacts
                    });

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

    @Action(LoadPersonMemberships)
    loadPersonMemberships(ctx: StateContext<SearchPersonDetailStateModel>, action: LoadPersonMemberships) {
        ctx.patchState({
            loadingPersonMemberships: true
        });

        if (action.personId) {
            return this.webApiService.call(
                new MembershipAllPerson(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId),
                () => new MembershipAllPersonOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: MembershipAllPersonOutput[]) => {
                    ctx.patchState({
                        loadingPersonMemberships: false,
                        personMemberships: response
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingPersonMemberships: false,
                        personMemberships: initialStateModel.personMemberships
                    });

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

    @Action(LoadPersonFunctions)
    loadPersonFunctions(ctx: StateContext<SearchPersonDetailStateModel>, action: LoadPersonFunctions) {
        ctx.patchState({
            loadingPersonFunctions: true
        });

        if (action.personId) {
            return this.webApiService.call(
                new FunctionAllPerson(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId),
                () => new FunctionAllPersonOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: FunctionAllPersonOutput[]) => {
                    ctx.patchState({
                        loadingPersonFunctions: false,
                        personFunctions: response
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingPersonFunctions: false,
                        personFunctions: initialStateModel.personFunctions
                    });

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

        }
    }

    @Action(LoadPersonQualifications)
    loadPersonQualifications(ctx: StateContext<SearchPersonDetailStateModel>, action: LoadPersonQualifications) {
        ctx.patchState({
            loadingPersonQualifications: true
        });
        if (action.personId) {
            return this.webApiService.call(
                new QualificationAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId),
                () => new QualificationAllOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: QualificationAllOutput[]) => {
                    ctx.patchState({
                        loadingPersonQualifications: false,
                        personQualifications: response
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingPersonQualifications: false,
                        personQualifications: initialStateModel.personQualifications
                    });

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

    @Action(LoadPersonOffers)
    loadPersonOffers(ctx: StateContext<SearchPersonDetailStateModel>, action: LoadPersonOffers) {
        ctx.patchState({
            loadingPersonOffers: true
        });

        if (action.personId) {
            return this.webApiService.call(
                new OfferAll(APP_ID, ApplicationSettings.getString(USER_TOKEN), action.personId),
                () => new OfferAllOutput(),
                wsOrganizationUnit
            ).pipe(
                tap((response: OfferAllOutput[]) => {
                    ctx.patchState({
                        loadingPersonOffers: false,
                        personOffers: response
                    });
                }),
                catchError(e => {
                    ctx.patchState({
                        loadingPersonOffers: false,
                        personOffers: initialStateModel.personOffers
                    });

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

    @Action(ClearPersonDetailData)
    clearPersonDetailData(ctx: StateContext<SearchPersonDetailStateModel>) {
        ctx.patchState(initialStateModel);
    }

}
