import { getAnswersState, getPartnerEngineConfig, removeActiveAnswerId, resetAddressValidation, resetAddressValidationAttempt, saveAddressValidationMissingAnswers, saveValidatedAddressAnswers, selectAddressValidationAddressComponents, selectAddressValidationAttemptNumber, selectAddressValidationOriginalAddress, selectAddressValidationStagedAnswers, selectAddressValidationTriggerWasOverridden, selectAddressValidationVerdict, selectHasAddressValidationError, selectLatestAddressMapToValidate, selectShouldTriggerAddressValidation, setAddressValidationStatus, stageAddressValidationAnswer, switchActiveQuestionSet, updateAnswer, validateAddress, } from "@boldpenguin/sdk-redux";
import { AddressValidationConfirmationLevel, AddressValidationVerdict, AnalyticsTrackingEventName, GoogleComponentTypes, LoadingStates, ValidationCTA, ValidationStatus, } from "@boldpenguin/sdk-types";
import { isAddressValidationMissingInfoButtonDisabled, mapAddressGroupValues, mapGoogleComponentTypeToFieldType, mapToComponentTypeText, shortenGoogleFormattedAddress, } from "@boldpenguin/sdk-utility";
import { h } from "@stencil/core";
import store from "../../services/redux-store.service";
export class BpSdkGoogleAddressValidation {
    constructor() {
        this.isContinueDisabled = true;
        this.isLatest = { verdict: false, validationAttempt: false };
        this.mapStateToProps = (state) => {
            return {
                address: selectAddressValidationAddressComponents(state, this.addressValidationId),
                answersResourceState: getAnswersState(state),
                config: getPartnerEngineConfig(state),
                googleApiToken: state.config.googleApiToken,
                stagedAnswers: selectAddressValidationStagedAnswers(state, this.addressValidationId),
                triggerValidation: selectShouldTriggerAddressValidation(state, this.addressValidationId),
                hasValidationError: selectHasAddressValidationError(state, this.addressValidationId),
                verdict: selectAddressValidationVerdict(state, this.addressValidationId),
                latestAddress: selectLatestAddressMapToValidate(state, this.answerMap),
                validationAttempt: selectAddressValidationAttemptNumber(state, this.addressValidationId),
                isValidationTriggerOverridden: selectAddressValidationTriggerWasOverridden(state),
                originalAddress: selectAddressValidationOriginalAddress(state, this.addressValidationId),
            };
        };
        this.continueWithConfirm = () => {
            this.removeActiveAnswerId();
            this.saveValidatedAddressAnswers({
                addressComponents: this.address.addressComponents,
                answerMap: this.answerMap,
                config: this.config,
            });
            this.resetAddressValidation(this.addressValidationId);
            this.shouldProceedNext = true;
        };
        this.continueWithMissingInputFix = () => {
            const answersToSave = this.stagedAnswers.map((answerDetails) => (Object.assign(Object.assign({}, answerDetails.answer), { value: answerDetails.new_value })));
            this.removeActiveAnswerId();
            this.saveAddressValidationMissingAnswers({
                answersToSave,
                addressValidationId: this.addressValidationId,
                config: this.config,
            });
        };
        this.editAddress = () => {
            this.resetAddressValidation(this.addressValidationId);
            this.resetAddressValidationAttempt(this.addressValidationId);
            this.setAddressValidationStatus({
                validationStatus: ValidationStatus.REQUIRED,
                addressValidationId: this.addressValidationId,
            });
        };
        this.continueAsEntered = () => {
            this.resetAddressValidation(this.addressValidationId);
            this.shouldProceedNext = true;
        };
        this.resetIsLatest = () => {
            this.isLatest.validationAttempt = false;
            this.isLatest.verdict = false;
        };
        this.address = undefined;
        this.addressValidationId = undefined;
        this.answerMap = undefined;
        this.answersResourceState = undefined;
        this.config = undefined;
        this.googleApiToken = undefined;
        this.stagedAnswers = [];
        this.triggerValidation = undefined;
        this.hasValidationError = undefined;
        this.verdict = undefined;
        this.latestAddress = undefined;
        this.validationAttempt = undefined;
        this.isValidationTriggerOverridden = undefined;
        this.originalAddress = undefined;
        this.useExternal = false;
        this.shouldProceedNext = false;
    }
    onStageAddressValidationAnswerForUpdate(event) {
        this.stageAddressValidationAnswer({ answerToStage: event.detail, addressValidationId: this.addressValidationId });
    }
    onIsReadyToProceedNext() {
        if (this.shouldProceedNext && this.answersResourceState !== LoadingStates.Loading) {
            !this.hasValidationError &&
                this.setAddressValidationStatus({
                    validationStatus: this.isValidationTriggerOverridden ? ValidationStatus.COMPLETED : ValidationStatus.PROCEED_NEXT,
                    addressValidationId: this.addressValidationId,
                });
            this.resetAddressValidation(this.addressValidationId);
            this.shouldProceedNext = false;
        }
    }
    onValidationError() {
        if (this.hasValidationError) {
            this.bpAnalyticsTrack.emit({
                eventName: AnalyticsTrackingEventName.AddressValidation_ValidationError,
            });
        }
    }
    onTriggerValidation() {
        var _a;
        if (this.triggerValidation) {
            if (this.validationAttempt < 2) {
                this.validateAddress(Object.assign({ googleApiKey: this.googleApiToken, addressValidationId: this.addressValidationId }, mapAddressGroupValues((_a = this.latestAddress) !== null && _a !== void 0 ? _a : this.answerMap)));
            }
            else {
                this.shouldProceedNext = true;
            }
        }
    }
    onValidationAttempt() {
        if (this.validationAttempt) {
            this.isLatest.validationAttempt = true;
        }
    }
    onVerdict() {
        if (this.verdict) {
            this.isLatest.verdict = true;
        }
    }
    onValidation() {
        if (this.isLatest.verdict && this.isLatest.validationAttempt) {
            if (this.validationAttempt === 1) {
                this.bpAnalyticsTrack.emit({
                    eventName: AnalyticsTrackingEventName.AddressValidation_ValidatedOnFirstAttempt,
                    eventPayload: { isValidated: this.verdict === AddressValidationVerdict.ACCEPT },
                });
            }
            this.bpAnalyticsTrack.emit({
                eventName: AnalyticsTrackingEventName.AddressValidation_Verdict,
                eventPayload: { verdict: this.verdict, attempt: this.validationAttempt },
            });
            this.resetIsLatest();
        }
    }
    onAddressValidation() {
        if (this.address) {
            this.validatedAddressView = {
                address: this.address,
                displayAddress: shortenGoogleFormattedAddress(this.address.formattedAddress),
                answersWithMissingPieces: this.address.missingComponentTypes
                    ? this.address.missingComponentTypes
                        .filter((type) => type !== GoogleComponentTypes.ROUTE)
                        .map((type) => this.latestAddress
                        ? this.latestAddress[mapGoogleComponentTypeToFieldType(type)]
                        : this.answerMap[mapGoogleComponentTypeToFieldType(type)])
                    : null,
                unconfirmedAddressComponents: this.address.addressComponents.filter((component) => component.confirmationLevel !== AddressValidationConfirmationLevel.CONFIRMED),
            };
        }
    }
    onValidationCallToAction(event) {
        this.onCTAClick(event.detail);
    }
    resetState() {
        this.shouldProceedNext = false;
    }
    connectedCallback() {
        this.resetState();
        this.handleSubscriptions();
    }
    componentWillLoad() {
        this.useExternal = !!customElements.get('bp-sdk-external-google-address-validation');
        customElements.whenDefined('bp-sdk-external-google-address-validation').then(() => {
            this.useExternal = true;
        });
        this.onIsReadyToProceedNext();
    }
    disconnectedCallback() {
        this.storeUnsubscribe && this.storeUnsubscribe();
    }
    handleSubscriptions() {
        this.storeUnsubscribe && this.storeUnsubscribe();
        store.mapDispatchToProps(this, {
            setAddressValidationStatus,
            resetAddressValidation,
            resetAddressValidationAttempt,
            saveValidatedAddressAnswers,
            saveAddressValidationMissingAnswers,
            stageAddressValidationAnswer,
            switchActiveQuestionSet,
            updateAnswer,
            validateAddress,
            removeActiveAnswerId,
        });
        this.storeUnsubscribe = store.mapStateToProps(this, this.mapStateToProps);
    }
    onCTAClick(action) {
        this.bpAnalyticsTrack.emit({
            eventName: AnalyticsTrackingEventName.AddressValidation_CTAClicked,
            eventPayload: { ctaType: action, verdict: this.verdict, attempt: this.validationAttempt },
        });
        switch (action) {
            case ValidationCTA.EDIT:
                return this.editAddress();
            case ValidationCTA.AS_ENTERED:
                return this.continueAsEntered();
            case ValidationCTA.MISSING_FIX:
                return this.continueWithMissingInputFix();
            case ValidationCTA.CONFIRM:
                return this.continueWithConfirm();
        }
    }
    render() {
        return [this.useExternal && this.renderExternal(), !this.useExternal && this.renderInternal()];
    }
    renderExternal() {
        return (h("bp-sdk-external-google-address-validation", { answerMap: this.answerMap, addressValidationId: this.addressValidationId, config: this.config, googleApiToken: this.googleApiToken, originalAddress: this.originalAddress, stagedAnswers: this.stagedAnswers, validatedAddressView: this.validatedAddressView, verdict: this.verdict }));
    }
    renderInternal() {
        return (h("div", { class: "bp-sdk-google-address-validation__container" }, this.verdict == AddressValidationVerdict.CONFIRM && this.renderConfirm(), this.verdict == AddressValidationVerdict.TYPO && this.renderTypo(), this.verdict == AddressValidationVerdict.FIX && this.renderFix()));
    }
    renderConfirm() {
        return (h("div", { class: "bp-sdk-google-address-validation__confirm" }, h("h2", null, "Address confirmation"), h("h3", null, "Suggested address:"), h("p", null, this.validatedAddressView.displayAddress), h("h3", null, "Original address:"), h("p", null, this.originalAddress), h("bp-sdk-button", { text: "Continue with suggested address", onClick: () => this.onCTAClick(ValidationCTA.CONFIRM) }), h("bp-sdk-button", { text: "Use original address", onClick: () => this.onCTAClick(ValidationCTA.AS_ENTERED) }), h("p", null, "Address confirmation helps ensure quoting accuracy.")));
    }
    renderTypo() {
        return (h("div", { class: "bp-sdk-google-address-validation__spelling-suggestion" }, h("h2", null, "Address confirmation"), h("h3", null, "Did you mean?"), h("p", null, this.validatedAddressView.displayAddress), h("h3", null, "Address entered:"), h("p", null, this.originalAddress), h("bp-sdk-button", { text: "Yes, continue with suggested address", onClick: () => this.onCTAClick(ValidationCTA.CONFIRM) }), h("bp-sdk-button", { text: "No, continue with address entered", onClick: () => this.onCTAClick(ValidationCTA.AS_ENTERED) }), h("p", null, "Address confirmation helps ensure quoting accuracy.")));
    }
    renderFix() {
        return (h("div", { class: "bp-sdk-google-address-validation__fix" }, h("h2", null, "Address not verified"), h("h3", null, "Original address:"), h("p", null, this.originalAddress), (this.validatedAddressView.answersWithMissingPieces && (h("div", null, h("h3", null, "Missing information"), h("bp-sdk-address-group", { answers: this.validatedAddressView.answersWithMissingPieces, useAddressValidation: false, disableAutoSave: true })))) ||
            this.validatedAddressView.unconfirmedAddressComponents.map((component) => (h("div", null, h("h3", null, mapToComponentTypeText(component.componentType), " not confirmed:"), h("p", null, component.componentName.text)))), (this.validatedAddressView.answersWithMissingPieces && (h("bp-sdk-button", { text: "Continue", onClick: () => this.onCTAClick(ValidationCTA.MISSING_FIX), buttonDisabled: isAddressValidationMissingInfoButtonDisabled(this.stagedAnswers) }))) || h("bp-sdk-button", { text: "Edit address", onClick: () => this.onCTAClick(ValidationCTA.EDIT) }), h("bp-sdk-button", { text: "Continue with original address", onClick: () => this.onCTAClick(ValidationCTA.AS_ENTERED) }), h("p", null, "Note: By using a non-verified address, you may not receive an accurate quote.")));
    }
    static get is() { return "bp-sdk-google-address-validation"; }
    static get originalStyleUrls() {
        return {
            "$": ["bp-sdk-google-address-validation.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["bp-sdk-google-address-validation.css"]
        };
    }
    static get properties() {
        return {
            "address": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "IResultAddress",
                    "resolved": "IResultAddress",
                    "references": {
                        "IResultAddress": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IResultAddress"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Google validation address information and components"
                }
            },
            "addressValidationId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "AddressValidationId",
                    "resolved": "string",
                    "references": {
                        "AddressValidationId": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::AddressValidationId"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Group ID from the question set, used for address validation state lookup"
                },
                "attribute": "address-validation-id",
                "reflect": false
            },
            "answerMap": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "{ [key: string]: IAnswer }",
                    "resolved": "{ [key: string]: IAnswer; }",
                    "references": {
                        "IAnswer": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IAnswer"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Address group answer set mapped by field type"
                }
            },
            "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
            },
            "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"
                }
            },
            "googleApiToken": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Google api key, if no key library is not loaded"
                },
                "attribute": "google-api-token",
                "reflect": false
            },
            "stagedAnswers": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "IAnswerUpdatedEvent[]",
                    "resolved": "IAnswerUpdatedEvent[]",
                    "references": {
                        "IAnswerUpdatedEvent": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IAnswerUpdatedEvent"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Unsaved answers from \"fix\" template missing field input"
                },
                "defaultValue": "[]"
            },
            "triggerValidation": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Is true when next button has been clicked"
                },
                "attribute": "trigger-validation",
                "reflect": false
            },
            "hasValidationError": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Is true when validation could not be completed"
                },
                "attribute": "has-validation-error",
                "reflect": false
            },
            "verdict": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "AddressValidationVerdict",
                    "resolved": "AddressValidationVerdict.ACCEPT | AddressValidationVerdict.CONFIRM | AddressValidationVerdict.FIX | AddressValidationVerdict.TYPO",
                    "references": {
                        "AddressValidationVerdict": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::AddressValidationVerdict"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Action to be taken per google address validation response"
                },
                "attribute": "verdict",
                "reflect": false
            },
            "latestAddress": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "{ [key: string]: IAnswer }",
                    "resolved": "{ [key: string]: IAnswer; }",
                    "references": {
                        "IAnswer": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IAnswer"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Address to validate with the latest pending answer"
                }
            },
            "validationAttempt": {
                "type": "number",
                "mutable": true,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The number of validations performed on an address, injected from redux"
                },
                "attribute": "validation-attempt",
                "reflect": false
            },
            "isValidationTriggerOverridden": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Is true when validation has been triggered by something other than clicking the next button, injected from redux"
                },
                "attribute": "is-validation-trigger-overridden",
                "reflect": false
            },
            "originalAddress": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The user entered address formatted, injected from redux"
                },
                "attribute": "original-address",
                "reflect": false
            }
        };
    }
    static get states() {
        return {
            "useExternal": {},
            "shouldProceedNext": {}
        };
    }
    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 watchers() {
        return [{
                "propName": "answersResourceState",
                "methodName": "onIsReadyToProceedNext"
            }, {
                "propName": "shouldProceedNext",
                "methodName": "onIsReadyToProceedNext"
            }, {
                "propName": "hasValidationError",
                "methodName": "onValidationError"
            }, {
                "propName": "triggerValidation",
                "methodName": "onTriggerValidation"
            }, {
                "propName": "validationAttempt",
                "methodName": "onValidationAttempt"
            }, {
                "propName": "verdict",
                "methodName": "onVerdict"
            }, {
                "propName": "validationAttempt",
                "methodName": "onValidation"
            }, {
                "propName": "verdict",
                "methodName": "onValidation"
            }, {
                "propName": "address",
                "methodName": "onAddressValidation"
            }];
    }
    static get listeners() {
        return [{
                "name": "stageAddressValidationAnswerForUpdate",
                "method": "onStageAddressValidationAnswerForUpdate",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "validationCTAEvent",
                "method": "onValidationCallToAction",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
