import { getPartnerEngineConfig, getVehicleOptionsConfigurations, getVehicleOptionsVin, getVinSelectionState, loadVin, } from "@boldpenguin/sdk-redux";
import { LoadingStates, VehicleVinOptions, YmmcUpdateType, } from "@boldpenguin/sdk-types";
import { hasRequiredError, hasValueChanged } from "@boldpenguin/sdk-utility";
import { h } from "@stencil/core";
import store from "../../services/redux-store.service";
import { VehicleVinService } from "../../services/vehicle-vin.service";
export class BpSdkVehicleVinContainer {
    constructor() {
        this.handleSubscriptions = () => {
            this.storeUnsubscribe && this.storeUnsubscribe();
            store.mapDispatchToProps(this, { loadVin });
            this.storeUnsubscribe = store.mapStateToProps(this, this.mapStateToProps);
        };
        this.mapStateToProps = (state) => {
            return {
                config: getPartnerEngineConfig(state),
                configurationOptions: getVehicleOptionsConfigurations(state, this.questionGroupId),
                vinOptions: getVehicleOptionsVin(state, this.questionGroupId),
                vinStatus: getVinSelectionState(state, this.questionGroupId),
                answeredBySource: this.getAnsweredBySource(state),
            };
        };
        this.onFocusOut = () => {
            this.touched = true;
            this.updateErrors(this.pristine, true, this.value);
        };
        this.answerId = undefined;
        this.code = undefined;
        this.vinOptions = Object.assign({}, VehicleVinOptions);
        this.configurationOptions = {};
        this.vinStatus = LoadingStates.NotLoaded;
        this.questionGroupId = undefined;
        this.canSave = false;
        this.value = '';
        this.config = undefined;
        this.lastResponse = undefined;
        this.canSearch = undefined;
        this.useExternal = false;
        this.touched = false;
        this.pristine = true;
        this.errorText = undefined;
        this.hasResult = false;
        this.isSearching = false;
        this.shouldSelectConfiguration = false;
        this.errors = [];
        this.vinResource = undefined;
        this.answeredBySource = undefined;
    }
    resetState() {
        this.touched = false;
        this.pristine = true;
        this.errors = [];
        this.errorText = undefined;
    }
    connectedCallback() {
        this.resetState();
        this.handleSubscriptions();
    }
    componentWillLoad() {
        this.useExternal = !!customElements.get('bp-sdk-external-vehicle-vin-container');
        customElements.whenDefined('bp-sdk-external-vehicle-vin-container').then(() => {
            this.useExternal = true;
        });
        this.onQuestionGroupIdChange();
    }
    onQuestionGroupIdChange() {
        this.handleSubscriptions();
    }
    onVinOptionsChange(vinOptions) {
        var _a;
        this.canSearch = (_a = vinOptions === null || vinOptions === void 0 ? void 0 : vinOptions.isAvailable) !== null && _a !== void 0 ? _a : true;
        this.lastResponse = vinOptions === null || vinOptions === void 0 ? void 0 : vinOptions.lastResponse;
    }
    onVinStatusChange(vinStatus) {
        this.vinResource = vinStatus !== null && vinStatus !== void 0 ? vinStatus : LoadingStates.NotLoaded;
        this.isSearching = this.vinResource === LoadingStates.Loading;
    }
    onConfigurationOptionsChange(configurationOptions) {
        const configs = configurationOptions !== null && configurationOptions !== void 0 ? configurationOptions : {};
        const keys = Object.keys(configs);
        this.hasResult = keys.length > 0;
        this.updateShouldSelectConfiguration(this.value, configurationOptions);
        if (keys.length === 1) {
            this.ymmcUpdate.emit({ type: YmmcUpdateType.Configuration, value: Object.keys(configurationOptions)[0] });
        }
    }
    loadFocusEvents() {
        if (!this.useExternal) {
            this.el.addEventListener('focusout', this.onFocusOut);
        }
    }
    unloadFocusEvents() {
        this.el.removeEventListener('focusout', this.onFocusOut);
    }
    componentDidLoad() {
        this.loadFocusEvents();
    }
    disconnectedCallback() {
        this.unloadFocusEvents();
        this.storeUnsubscribe && this.storeUnsubscribe();
    }
    onValueChange(value) {
        this.updateShouldSelectConfiguration(value, this.configurationOptions);
    }
    updateShouldSelectConfiguration(vin, configurations) {
        // spread operator on configurations guards against null/undefined
        this.shouldSelectConfiguration = !!vin && Object.keys(Object.assign({}, configurations)).length > 1;
    }
    setVin(vin) {
        this.pristine = false;
        this.value = vin;
        this.updateErrors(this.pristine, this.touched, vin);
        const hasErrors = this.errors.length > 0 || this.errorText;
        const hasValidLength = VehicleVinService.hasValidLength(vin);
        this.canSave = !hasErrors && hasValidLength;
        if (!hasErrors) {
            if (hasValidLength) {
                this.loadVin({
                    vin,
                    config: this.config,
                    questionGroupId: this.questionGroupId,
                });
            }
            this.vinUpdate.emit({ vin, answerId: this.answerId });
        }
    }
    onValueUpdate({ detail }) {
        if (this.useExternal) {
            return;
        }
        const vin = detail !== null && detail !== void 0 ? detail : '';
        if (hasValueChanged(this.value, vin)) {
            this.setVin(vin);
        }
    }
    updateErrors(pristine, touched, vin) {
        this.errors = hasRequiredError(pristine, touched, vin) ? ['required'] : [];
        this.errorText = VehicleVinService.getValidationErrorMessage(vin);
    }
    onMakeDirty() {
        this.touched = true;
        this.pristine = false;
    }
    render() {
        return [this.useExternal && this.renderExternal(), !this.useExternal && this.renderInternal()];
    }
    renderExternal() {
        return (h("bp-sdk-external-vehicle-vin-container", { answerId: this.answerId, code: this.code, canSave: this.canSave, canSearch: this.canSearch, config: this.config, configurationOptions: this.configurationOptions, questionGroupId: this.questionGroupId, value: this.value, vinOptions: this.vinOptions, vinStatus: this.vinStatus, answeredBySource: this.answeredBySource }));
    }
    renderInternal() {
        return (h("bp-sdk-vehicle-vin", { answerId: this.answerId, canSave: this.canSave, code: this.code, label: "Enter vehicle VIN", isSearching: this.isSearching, hasResult: this.hasResult, touched: this.touched, pristine: this.pristine, errors: this.errors, shouldSelectConfiguration: this.shouldSelectConfiguration, questionGroupId: this.questionGroupId, errorText: this.errorText, value: this.value, answeredBySource: this.answeredBySource }));
    }
    getAnsweredBySource(state) {
        const questionSet = state.application.questionSets.list.find((qs) => qs.question_set.code === 'vehicle_pool_master_question_set');
        const answer = questionSet === null || questionSet === void 0 ? void 0 : questionSet.answers.find((answer) => answer.id === this.answerId);
        if (answer === null || answer === void 0 ? void 0 : answer.answered_by_consumer) {
            return 'Consumer';
        }
        return answer === null || answer === void 0 ? void 0 : answer.answered_by_source;
    }
    static get is() { return "bp-sdk-vehicle-vin-container"; }
    static get originalStyleUrls() {
        return {
            "$": ["./bp-sdk-vehicle-vin-container.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["bp-sdk-vehicle-vin-container.css"]
        };
    }
    static get properties() {
        return {
            "answerId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The id of the answer associated with this field"
                },
                "attribute": "answer-id",
                "reflect": false
            },
            "code": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The question code associated with this field"
                },
                "attribute": "code",
                "reflect": false
            },
            "vinOptions": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "IVehicleVinOptions",
                    "resolved": "IVehicleVinOptions",
                    "references": {
                        "IVehicleVinOptions": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IVehicleVinOptions"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "VIN resource injected by redux"
                },
                "defaultValue": "{ ...VehicleVinOptions }"
            },
            "configurationOptions": {
                "type": "unknown",
                "mutable": true,
                "complexType": {
                    "original": "IVehicleConfigurationOptions",
                    "resolved": "IVehicleConfigurationOptions",
                    "references": {
                        "IVehicleConfigurationOptions": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IVehicleConfigurationOptions"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "VIN resource injected by redux"
                },
                "defaultValue": "{}"
            },
            "vinStatus": {
                "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": "Selection resource injected by redux"
                },
                "attribute": "vin-status",
                "reflect": false,
                "defaultValue": "LoadingStates.NotLoaded"
            },
            "questionGroupId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Vehicle question group ID"
                },
                "attribute": "question-group-id",
                "reflect": false
            },
            "canSave": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Can Save"
                },
                "attribute": "can-save",
                "reflect": false,
                "defaultValue": "false"
            },
            "value": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Current value of answer"
                },
                "attribute": "value",
                "reflect": false,
                "defaultValue": "''"
            }
        };
    }
    static get states() {
        return {
            "config": {},
            "lastResponse": {},
            "canSearch": {},
            "useExternal": {},
            "touched": {},
            "pristine": {},
            "errorText": {},
            "hasResult": {},
            "isSearching": {},
            "shouldSelectConfiguration": {},
            "errors": {},
            "vinResource": {},
            "answeredBySource": {}
        };
    }
    static get events() {
        return [{
                "method": "vinUpdate",
                "name": "vinUpdate",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "{ vin: string; answerId: string }",
                    "resolved": "{ vin: string; answerId: string; }",
                    "references": {}
                }
            }, {
                "method": "ymmcUpdate",
                "name": "ymmcUpdate",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "IYearMakeModelConfigurationUpdate",
                    "resolved": "IYearMakeModelConfigurationUpdate",
                    "references": {
                        "IYearMakeModelConfigurationUpdate": {
                            "location": "import",
                            "path": "@boldpenguin/sdk-types",
                            "id": "../sdk-types/dist/types.d.ts::IYearMakeModelConfigurationUpdate"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "questionGroupId",
                "methodName": "onQuestionGroupIdChange"
            }, {
                "propName": "vinOptions",
                "methodName": "onVinOptionsChange"
            }, {
                "propName": "vinStatus",
                "methodName": "onVinStatusChange"
            }, {
                "propName": "configurationOptions",
                "methodName": "onConfigurationOptionsChange"
            }, {
                "propName": "value",
                "methodName": "onValueChange"
            }];
    }
    static get listeners() {
        return [{
                "name": "valueUpdate",
                "method": "onValueUpdate",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "makeDirty",
                "method": "onMakeDirty",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
