import { doesUserOwnApplicationForm, getAnswersState, getApplicationFormState, getPartnerEngineConfig, getQuestionPoolState, getQuestionSetState, pushAnswer, removeActiveAnswerId, saveQuestionSet, updateActiveAnswerId, updateErrors, userHasPermission, } from "@boldpenguin/sdk-redux";
import { AnalyticsTrackingEventName, ApplicationFormProcessState, BpSdkPermissionAction, BpSdkPermissions, LoadingStates, } from "@boldpenguin/sdk-types";
import { focusErrors, getErrors, getQuestionGroupWithParentQuestionAnswerIdAsKey, getQuestionGroupsWithParentQuestionIdAsKey, hasAnswer, hasAnswerChanged, isValidAnswer, updateAnswerValue, } from "@boldpenguin/sdk-utility";
import { Fragment, h } from "@stencil/core";
import store from "../../services/redux-store.service";
export class BpSdkQuestionSetContainer {
    constructor() {
        this.handleSubscriptions = () => {
            this.storeUnsubscribe && this.storeUnsubscribe();
            store.mapDispatchToProps(this, {
                saveQuestionSet,
                updateErrors,
                pushAnswer,
                removeActiveAnswerId,
                updateActiveAnswerId,
            });
            this.storeUnsubscribe = store.mapStateToProps(this, this.mapStateToProps);
        };
        this.mapStateToProps = (state) => {
            return {
                questionSets: state.application.questionSets,
                config: getPartnerEngineConfig(state),
                enableUserApplicationGuard: !!state.config.options.enableUserApplicationGuard,
                locked: state.application.form.locked,
                isOwner: doesUserOwnApplicationForm(state),
                hasPermissionToEdit: userHasPermission(state, {
                    permission: BpSdkPermissions.ApplicationForms,
                    action: BpSdkPermissionAction.Update,
                }),
                pendingProcesses: state.application.pendingProcesses,
                queue: state.queues.answers.queue,
                answersResourceState: getAnswersState(state),
                applicationFormResourceState: getApplicationFormState(state),
                questionPoolResourceState: getQuestionPoolState(state),
                questionSetResourceState: getQuestionSetState(state),
            };
        };
        this.handleSaveQuestionSet = (questionSet) => {
            const invalidAnswers = questionSet.answers.filter((answer) => !isValidAnswer(answer));
            if (!invalidAnswers.length) {
                this.removeActiveAnswerId();
                this.saveQuestionSet({
                    config: this.config,
                    appFormQuestionSet: questionSet,
                    navigationDirection: 'forward',
                });
                this.bpAnalyticsTrack.emit({
                    eventName: AnalyticsTrackingEventName.QuestionSetSaved,
                    eventPayload: {
                        applicationFormQuestionSetId: questionSet.id,
                        questionSetId: questionSet.question_set_id,
                        questionSetCode: questionSet.question_set.code,
                    },
                });
            }
            else {
                invalidAnswers.forEach((answer) => {
                    this.updateErrors({ answer, errors: getErrors(answer) });
                });
                focusErrors();
            }
        };
        this.questionSets = {
            list: [],
            active: '',
            activeAnswerId: '',
            completedQuestionSetAnswerHasChanged: false,
            idOfNextActiveQuestionSetNotInState: undefined,
            parentQuestionSets: [],
        };
        this.config = undefined;
        this.answersResourceState = undefined;
        this.applicationFormResourceState = undefined;
        this.questionPoolResourceState = undefined;
        this.questionSetResourceState = undefined;
        this.locked = undefined;
        this.pendingProcesses = undefined;
        this.queue = undefined;
        this.isOwner = undefined;
        this.hasPermissionToEdit = undefined;
        this.enableUserApplicationGuard = undefined;
        this.areResourcesReady = true;
        this.useExternal = false;
        this.canSave = true;
        this.isLocked = false;
        this.isReady = true;
        this.isFirstRun = true;
        this.isLoadingApplication = false;
    }
    resetState() {
        this.isReady = true;
        this.isFirstRun = true;
        this.isLoadingApplication = false;
    }
    connectedCallback() {
        this.resetState();
        this.handleSubscriptions();
    }
    componentWillLoad() {
        this.useExternal = !!customElements.get('bp-sdk-external-question-set-container');
        customElements.whenDefined('bp-sdk-external-question-set-container').then(() => {
            this.useExternal = true;
        });
        this.handleSubscriptions();
        this.onAnswersResourcesStateChange(this.answersResourceState);
        this.onApplicationFormResourceStateChange(this.applicationFormResourceState);
        this.onHasPermissionToEdit(this.hasPermissionToEdit);
        this.onEnableUserApplicationGuard(this.enableUserApplicationGuard);
        this.onIsFirstRun(this.isFirstRun);
        this.onIsOwner(this.isOwner);
        this.onIsReady(this.isReady);
        this.onLocked(this.locked);
        this.onQuestionPoolResourcesStateChange(this.questionPoolResourceState);
        this.onQuestionSetResourcesStateChange(this.questionSetResourceState);
        this.onQueueChange(this.queue);
    }
    onQueueChange(queue) {
        this.canSave = !(queue === null || queue === void 0 ? void 0 : queue.length) && !this.doesCurrentQuestionSetHaveAPendingProcess();
    }
    onEnableUserApplicationGuard(enableUserApplicationGuard) {
        this.updateIsLocked(this.locked, this.isOwner, this.hasPermissionToEdit, enableUserApplicationGuard);
    }
    onHasPermissionToEdit(hasPermission) {
        this.updateIsLocked(this.locked, this.isOwner, hasPermission, this.enableUserApplicationGuard);
    }
    onIsOwner(isOwner) {
        this.updateIsLocked(this.locked, isOwner, this.hasPermissionToEdit, this.enableUserApplicationGuard);
    }
    onLocked(locked) {
        this.updateIsLocked(locked, this.isOwner, this.hasPermissionToEdit, this.enableUserApplicationGuard);
    }
    onPendingProcessesChange(processes) {
        this.canSave = !this.doesCurrentQuestionSetHaveAPendingProcess(processes);
    }
    updateIsLocked(locked, isOwner, hasPermission, enableUserApplicationGuard) {
        this.isLocked = locked || (enableUserApplicationGuard && (!isOwner || !hasPermission));
    }
    onIsFirstRun(isFirstRun) {
        this.updateAreResourcesReady(isFirstRun, this.isReady);
    }
    onIsReady(isReady) {
        this.updateAreResourcesReady(this.isFirstRun, isReady);
    }
    updateAreResourcesReady(isFirstRun, isReady) {
        this.areResourcesReady = isFirstRun || isReady;
    }
    disconnectedCallback() {
        this.storeUnsubscribe && this.storeUnsubscribe();
    }
    onRemoveActiveAnswerRequest() {
        this.removeActiveAnswerId();
    }
    onUpdateActiveAnswerRequest({ detail }) {
        const answer = this.questionSets.list.reduce((acc, list) => acc || list.answers.find((answer) => answer.id === detail), null);
        if (answer) {
            this.updateActiveAnswerId(answer.id);
        }
    }
    onAnswersResourcesStateChange(state) {
        this.isReady = this.calculateResourcesReady({
            answers: state,
            applicationForm: this.applicationFormResourceState,
            questionPools: this.questionPoolResourceState,
            questionSets: this.questionSetResourceState,
        });
    }
    onApplicationFormResourceStateChange(state) {
        if (this.isFirstRun && state === LoadingStates.Loaded) {
            this.isFirstRun = false;
        }
        if (state === LoadingStates.Loading) {
            this.isLoadingApplication = true;
        }
        else {
            this.isLoadingApplication = false;
        }
        this.isReady = this.calculateResourcesReady({
            answers: this.answersResourceState,
            applicationForm: state,
            questionPools: this.questionPoolResourceState,
            questionSets: this.questionSetResourceState,
        });
    }
    onQuestionPoolResourcesStateChange(state) {
        this.isReady = this.calculateResourcesReady({
            answers: this.answersResourceState,
            applicationForm: this.applicationFormResourceState,
            questionPools: state,
            questionSets: this.questionSetResourceState,
        });
    }
    onQuestionSetResourcesStateChange(state) {
        this.isReady = this.calculateResourcesReady({
            answers: this.answersResourceState,
            applicationForm: this.applicationFormResourceState,
            questionPools: this.questionPoolResourceState,
            questionSets: state,
        });
    }
    calculateResourcesReady(resources = {}) {
        if (!resources ||
            resources.applicationForm !== LoadingStates.Loaded ||
            resources.answers === LoadingStates.Loading ||
            resources.questionPools === LoadingStates.Loading ||
            resources.questionSets === LoadingStates.Loading) {
            return false;
        }
        return true;
    }
    handleSaveAnswer(event) {
        if (this.useExternal) {
            return;
        }
        const pendingUpdate = this.questionSets.pendingActiveAnswerUpdate;
        const { answer, new_value } = event.detail;
        const updatedAnswer = updateAnswerValue(answer, new_value);
        if (hasAnswerChanged(answer, new_value) ||
            (hasAnswer(updatedAnswer) && !answer.is_completed) ||
            ((pendingUpdate === null || pendingUpdate === void 0 ? void 0 : pendingUpdate.id) === answer.id && hasAnswerChanged(pendingUpdate, new_value))) {
            this.pushAnswer(updatedAnswer);
        }
    }
    componentWillUpdate() {
        this.handleSubscriptions();
    }
    render() {
        return [this.useExternal && this.renderExternal(), !this.useExternal && this.renderInternal()];
    }
    renderExternal() {
        return (h("bp-sdk-external-question-set-container", { answersResourceState: this.answersResourceState, applicationFormResourceState: this.applicationFormResourceState, config: this.config, enableUserApplicationGuard: this.enableUserApplicationGuard, hasPermissionToEdit: this.hasPermissionToEdit, isOwner: this.isOwner, locked: this.locked, pendingProcesses: this.pendingProcesses, questionPoolResourceState: this.questionPoolResourceState, questionSetResourceState: this.questionSetResourceState, questionSets: this.questionSets, queue: this.queue }));
    }
    renderQuestionSetHeader(set) {
        var _a, _b, _c, _d;
        return (h("bp-sdk-question-set-header", { applicationId: set.application_form_id, code: (_a = set.question_set) === null || _a === void 0 ? void 0 : _a.code, isActive: set.is_active, isCompleted: set.is_completed, name: (_b = set.question_set) === null || _b === void 0 ? void 0 : _b.name, setId: set.question_set_id, setTitle: (_c = set.question_set) === null || _c === void 0 ? void 0 : _c.title, tenantId: (_d = set.question_set) === null || _d === void 0 ? void 0 : _d.tenant_id }));
    }
    shouldRenderQuestionGroup(questionGroupsWithAnswersAsKey, answer) {
        return questionGroupsWithAnswersAsKey.has(answer.id);
    }
    renderQuestionSet(set) {
        // Gets multiple separate groups/nested groups
        const questionGroupsWithAnswersAsKey = getQuestionGroupWithParentQuestionAnswerIdAsKey(set, getQuestionGroupsWithParentQuestionIdAsKey(set));
        if (set.is_blank) {
            return h("bp-sdk-question-set-empty", { questionSet: set.question_set });
        }
        return (h("bp-sdk-question-set", { areResourcesReady: this.areResourcesReady, canSave: this.canSave, locked: this.isLocked, questionSet: set, saveHandler: this.handleSaveQuestionSet, questionGroupsWithAnswersAsKey: questionGroupsWithAnswersAsKey, shouldRenderQuestionGroup: this.shouldRenderQuestionGroup }));
    }
    renderPendingProcessesContainer() {
        return h("bp-sdk-pending-process-container", { pendingProcesses: this.pendingProcesses });
    }
    renderInternal() {
        let activeQuestionSet = this.questionSets.list[this.questionSets.list.length - 1];
        if (this.isFirstRun && this.isLoadingApplication) {
            return h("bp-sdk-application-load", null);
        }
        if (this.questionSets.active && this.questionSets.active !== '') {
            activeQuestionSet = this.questionSets.list.find((qs) => qs.question_set_id === this.questionSets.active);
        }
        if (activeQuestionSet) {
            return (h(Fragment, null, this.renderQuestionSetHeader(activeQuestionSet), this.renderQuestionSet(activeQuestionSet), this.renderPendingProcessesContainer()));
        }
    }
    doesCurrentQuestionSetHaveAPendingProcess(processes) {
        const currentProcesses = processes ? processes : this.pendingProcesses;
        if (!(currentProcesses === null || currentProcesses === void 0 ? void 0 : currentProcesses.length)) {
            return false;
        }
        return currentProcesses.some((process) => process.state !== ApplicationFormProcessState.Completed && process.question_set_id === this.questionSets.active);
    }
    static get is() { return "bp-sdk-question-set-container"; }
    static get properties() {
        return {
            "questionSets": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "IQuestionSetState",
                    "resolved": "IQuestionSetState",
                    "references": {
                        "IQuestionSetState": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IQuestionSetState"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Question sets injected from redux"
                },
                "defaultValue": "{\n    list: [],\n    active: '',\n    activeAnswerId: '',\n    completedQuestionSetAnswerHasChanged: false,\n    idOfNextActiveQuestionSetNotInState: undefined,\n    parentQuestionSets: [],\n  }"
            },
            "config": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "IPartnerEngineConfig",
                    "resolved": "IPartnerEngineConfig",
                    "references": {
                        "IPartnerEngineConfig": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IPartnerEngineConfig"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "IPartnerEngineConfig injected from redux"
                }
            },
            "answersResourceState": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "LoadingStates",
                    "resolved": "LoadingStates.Error | LoadingStates.Loaded | LoadingStates.Loading | LoadingStates.NotLoaded",
                    "references": {
                        "LoadingStates": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::LoadingStates"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Answer resource states injected from redux"
                },
                "attribute": "answers-resource-state",
                "reflect": false
            },
            "applicationFormResourceState": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "LoadingStates",
                    "resolved": "LoadingStates.Error | LoadingStates.Loaded | LoadingStates.Loading | LoadingStates.NotLoaded",
                    "references": {
                        "LoadingStates": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::LoadingStates"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Application form resource states injected from redux"
                },
                "attribute": "application-form-resource-state",
                "reflect": false
            },
            "questionPoolResourceState": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "LoadingStates",
                    "resolved": "LoadingStates.Error | LoadingStates.Loaded | LoadingStates.Loading | LoadingStates.NotLoaded",
                    "references": {
                        "LoadingStates": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::LoadingStates"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Question pool resource states injected from redux"
                },
                "attribute": "question-pool-resource-state",
                "reflect": false
            },
            "questionSetResourceState": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "LoadingStates",
                    "resolved": "LoadingStates.Error | LoadingStates.Loaded | LoadingStates.Loading | LoadingStates.NotLoaded",
                    "references": {
                        "LoadingStates": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::LoadingStates"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Question set resource states injected from redux"
                },
                "attribute": "question-set-resource-state",
                "reflect": false
            },
            "locked": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Application form state injected from redux"
                },
                "attribute": "locked",
                "reflect": false
            },
            "pendingProcesses": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "IApplicationFormProcesses[]",
                    "resolved": "IApplicationFormProcesses[]",
                    "references": {
                        "IApplicationFormProcesses": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IApplicationFormProcesses"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Pending processes of application form state injected from redux"
                }
            },
            "queue": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "IAnswer[]",
                    "resolved": "IAnswer[]",
                    "references": {
                        "IAnswer": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IAnswer"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Answer queue injected from redux"
                }
            },
            "isOwner": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Is owner of application"
                },
                "attribute": "is-owner",
                "reflect": false
            },
            "hasPermissionToEdit": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Has permission to edit application"
                },
                "attribute": "has-permission-to-edit",
                "reflect": false
            },
            "enableUserApplicationGuard": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Enabled user check for application"
                },
                "attribute": "enable-user-application-guard",
                "reflect": false
            }
        };
    }
    static get states() {
        return {
            "areResourcesReady": {},
            "useExternal": {},
            "canSave": {},
            "isLocked": {},
            "isReady": {},
            "isFirstRun": {},
            "isLoadingApplication": {}
        };
    }
    static get events() {
        return [{
                "method": "bpAnalyticsTrack",
                "name": "bpAnalyticsTrack",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emits an analytics tracking event, see `AnalyticsTrackingEventName` (sdk-types) for event names"
                },
                "complexType": {
                    "original": "IAnalyticsTrackEventDetail",
                    "resolved": "IAnalyticsTrackEventDetail",
                    "references": {
                        "IAnalyticsTrackEventDetail": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IAnalyticsTrackEventDetail"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "queue",
                "methodName": "onQueueChange"
            }, {
                "propName": "enableUserApplicationGuard",
                "methodName": "onEnableUserApplicationGuard"
            }, {
                "propName": "hasPermissionToEdit",
                "methodName": "onHasPermissionToEdit"
            }, {
                "propName": "isOwner",
                "methodName": "onIsOwner"
            }, {
                "propName": "locked",
                "methodName": "onLocked"
            }, {
                "propName": "pendingProcesses",
                "methodName": "onPendingProcessesChange"
            }, {
                "propName": "isFirstRun",
                "methodName": "onIsFirstRun"
            }, {
                "propName": "isReady",
                "methodName": "onIsReady"
            }, {
                "propName": "answersResourceState",
                "methodName": "onAnswersResourcesStateChange"
            }, {
                "propName": "applicationFormResourceState",
                "methodName": "onApplicationFormResourceStateChange"
            }, {
                "propName": "questionPoolResourceState",
                "methodName": "onQuestionPoolResourcesStateChange"
            }, {
                "propName": "questionSetResourceState",
                "methodName": "onQuestionSetResourcesStateChange"
            }];
    }
    static get listeners() {
        return [{
                "name": "removeActiveAnswer",
                "method": "onRemoveActiveAnswerRequest",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "updateActiveAnswer",
                "method": "onUpdateActiveAnswerRequest",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "saveAnswer",
                "method": "handleSaveAnswer",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
