/*!
 * Copyright (c) what3words http://what3words.com
 */
import { DEFAULTS, SELECTORS, W3W_REGEX, } from "../../lib/constants";
import { sdk, what3wordsClients } from "../../lib/sdk";
import { resolveLanguageCode, t } from "../../lib/translation";
import utilisation, { SessionType, } from "../../lib/utilisation";
import { convertToCoordinates, isEmpty, parseCoordinates, } from "../../lib/utils";
import { h, Host, } from "@stencil/core";
import { ApiVersion, fetchTransport } from "@what3words/api";
import { version } from "../../../package.json";
import { ErrorMessage } from "./components/error-message";
import { Status } from "./components/status";
import { Suggestions } from "./components/suggestions";
/**
 * @slot { HTMLInputElement } - Optional input to override the default slot content
 */
export class What3wordsAutosuggest {
    constructor() {
        var _a;
        // API configuration
        this.callback = DEFAULTS.emptyString;
        this.api_key = DEFAULTS.emptyString;
        this.headers = DEFAULTS.headers;
        this.base_url =
            // TODO: _config is a protected property, new access method should be created to reflect this value reference
            (_a = sdk.api.clients.autosuggest["_config"].host) !== null && _a !== void 0 ? _a : DEFAULTS.base_url;
        this.api_version = ApiVersion.Version3;
        // Input properties
        this.name = DEFAULTS.name;
        this.initial_value = DEFAULTS.emptyString;
        this.variant = DEFAULTS.variant;
        this.typeahead_delay = DEFAULTS.typeaheadDelay;
        this.invalid_address_error_message = DEFAULTS.null;
        this.strict = DEFAULTS.true;
        this.autosuggest_focus = DEFAULTS.emptyString;
        this.clip_to_country = DEFAULTS.emptyString;
        this.clip_to_bounding_box = DEFAULTS.emptyString;
        this.clip_to_circle = DEFAULTS.emptyString;
        this.clip_to_polygon = DEFAULTS.emptyString;
        this.return_coordinates = DEFAULTS.returnCoordinates;
        this.options = [];
        // Internal component state
        this.rawValue = this.initial_value;
        this.value = this.initial_value;
        this.input = DEFAULTS.null;
        this.latInput = DEFAULTS.null;
        this.lngInput = DEFAULTS.null;
        this.suggestions = DEFAULTS.options;
        this.selectedSuggestion = DEFAULTS.null;
        this.showSuggestions = DEFAULTS.false;
        this.hasFocus = DEFAULTS.false;
        this.latitude = DEFAULTS.null;
        this.longitude = DEFAULTS.null;
        this.loading = DEFAULTS.false;
        this.hoverIndex = -1;
        this.error = DEFAULTS.null;
        this.onClick = (suggestion) => () => {
            this.selected_suggestion.emit({ suggestion });
        };
        this.onCustomClick = (opt) => {
            const inputElement = this.getInputElement();
            if (!inputElement) {
                const error = new Error("Input element not found");
                this.emitError(error);
                return;
            }
            inputElement.value = opt.value;
            this.selected_custom_option.emit(opt);
        };
        this.onMouseOver = (suggestion) => () => {
            var _a;
            const previousSuggestion = (_a = this.getSuggestions()[this.hoverIndex]) !== null && _a !== void 0 ? _a : null;
            if (!previousSuggestion || previousSuggestion.words !== suggestion.words) {
                this.__hover.emit({ suggestion });
            }
        };
        this.onMouseOut = () => {
            this.setHoverIndex(-1);
        };
    }
    /**
     * Watches for changes to the api_key property
     * @param key The api key
     */
    setApiKey(key) {
        Object.values(this.clients).forEach((client) => client.apiKey(key));
    }
    /**
     * Watches for changes to the base_url property
     * @param base_url The base url
     */
    setBaseUrl(host) {
        Object.values(this.clients).forEach((client) => client.config({ host }));
    }
    /**
     * Watches for changes to the api_version property
     * @param apiVersion The version
     */
    setApiVersion(api_version) {
        Object.values(this.clients).forEach((client) => client.config({ apiVersion: api_version }));
    }
    /**
     * Watches for changes to the headers property
     * @param value The headers value
     */
    setHeaders(value) {
        const componentHeaders = this.getComponentHeaders();
        const injectedHeaders = (typeof value === "string" ? JSON.parse(value) : value);
        Object.values(this.clients).forEach((client) => client.config({
            headers: Object.assign(Object.assign({}, injectedHeaders), componentHeaders),
        }));
    }
    setCustomOptions(options) {
        this.setShowSuggestions(options.length > 0);
    }
    getComponentHeaders() {
        const { return_coordinates, typeahead_delay, variant } = this;
        const component_session_id = window.what3words_session_id;
        const meta = JSON.stringify({
            return_coordinates,
            typeahead_delay,
            variant,
            component_session_id,
            origin: window.location.origin,
        });
        return {
            "X-Correlation-ID": component_session_id,
            "X-W3W-AS-Component": `what3words-Autosuggest-JS/${version} (${meta})`,
        };
    }
    getRequestOptions(input) {
        const { autosuggest_focus, n_focus_results, clip_to_country, clip_to_bounding_box, clip_to_circle, clip_to_polygon, language, } = this;
        const options = { input, language };
        // validates the language
        options.language = resolveLanguageCode(language);
        if (!isEmpty(autosuggest_focus)) {
            const [lat, lng] = autosuggest_focus.split(",");
            if (lat && lng)
                options.focus = parseCoordinates(lat, lng);
        }
        if (!isEmpty(n_focus_results === null || n_focus_results === void 0 ? void 0 : n_focus_results.toString()))
            options.nFocusResults = n_focus_results;
        if (!isEmpty(clip_to_country))
            options.clipToCountry = clip_to_country.split(",");
        if (!isEmpty(clip_to_bounding_box)) {
            const [southLat, westLng, northLat, eastLng] = clip_to_bounding_box.split(",");
            if (northLat && eastLng && southLat && westLng)
                options.clipToBoundingBox = {
                    northeast: parseCoordinates(northLat, eastLng),
                    southwest: parseCoordinates(southLat, westLng),
                };
        }
        if (!isEmpty(clip_to_circle)) {
            const [lat, lng, radius] = clip_to_circle.split(",");
            if (lat && lng && radius)
                options.clipToCircle = {
                    center: parseCoordinates(lat, lng),
                    radius: parseFloat(radius),
                };
        }
        if (!isEmpty(clip_to_polygon)) {
            options.clipToPolygon = convertToCoordinates(clip_to_polygon);
        }
        return options;
    }
    /**
     * Gets/sets the input element
     * @param { HTMLInputElement } input
     */
    setInputElement(input) {
        this.input = input;
    }
    /** @returns { HTMLInputElement | null } */
    getInputElement() {
        return this.input;
    }
    /**
     * Sets the input value
     * @param { string } value
     */
    setInputValue(value) {
        const input = this.getInputElement();
        if (input)
            input.value = value;
    }
    /**
     * Gets/sets the value state for the input element
     * @param { string } value The value to set
     */
    setValue(value) {
        this.value = value;
    }
    /** @returns { string } */
    getValue() {
        return this.value;
    }
    /**
     * Gets/sets the raw input search value
     * @param { string } rawValue The value to set
     */
    setRawValue(rawValue) {
        this.rawValue = rawValue;
    }
    /**
     * @returns { string }
     */
    getRawValue() {
        return this.rawValue;
    }
    /**
     * Get/set the autosuggestions state value
     * @param { AutosuggestOption[] } suggestions The suggestions to set
     */
    setSuggestions(suggestions = []) {
        this.suggestions = suggestions;
    }
    /** @return { AutosuggestOption[] } */
    getSuggestions() {
        return this.suggestions;
    }
    /**
     * Get/set the selected suggestion state value
     * @param { AutosuggestOption | null } selectedSuggestion The suggestions to set
     */
    setSelectedSuggestion(selectedSuggestion = null) {
        this.selectedSuggestion = selectedSuggestion;
    }
    /** @return { AutosuggestOption | null } */
    getSelectedSuggestion() {
        return this.selectedSuggestion;
    }
    /**
     * Gets/sets the loading state value
     * @param { boolean } loading The state to set
     */
    setLoading(loading) {
        if (this.loading && !loading)
            setTimeout(() => (this.loading = loading), 200);
        else
            this.loading = loading;
    }
    /** @return { boolean } */
    getLoading() {
        return this.loading;
    }
    /**
     * Gets/sets the hasFocus state value
     * @param { boolean } hasFocus The state to set
     */
    setHasFocus(hasFocus) {
        this.hasFocus = hasFocus;
    }
    /** @return { boolean } */
    getHasFocus() {
        return this.hasFocus;
    }
    /**
     * Gets/sets the showSuggestions state value
     * @param { boolean } showSuggestions The state to set
     */
    setShowSuggestions(showSuggestions) {
        this.showSuggestions = showSuggestions;
    }
    /** @return { boolean } */
    getShowSuggestions() {
        return this.showSuggestions;
    }
    /**
     * Gets/sets the latitude state value
     * @param { number | null } lat The latitude value to set
     */
    setLat(lat) {
        this.latitude = lat;
    }
    /** @returns { number | null } */
    getLat() {
        return this.latitude;
    }
    /**
     * Gets/sets the longitude value
     * @param { number | null } lng The longitude value to set
     */
    setLng(lng) {
        this.longitude = lng;
    }
    /** @returns { number | null } */
    getLng() {
        return this.longitude;
    }
    /**
     * Gets/sets the latitude input state value
     * @param { HTMLInputElement } lat The latitude input value to set
     */
    setLatInput(lat) {
        this.latInput = lat;
    }
    /** @returns { HTMLInputElement | null } */
    getLatInput() {
        return this.latInput;
    }
    /**
     * Gets/sets the longitude input state value
     * @param { HTMLInputElement } lng The longitude input value to set
     */
    setLngInput(lng) {
        this.lngInput = lng;
    }
    /** @returns { HTMLInputElement | null } */
    getLngInput() {
        return this.lngInput;
    }
    /**
     * Gets/sets the hover index value
     * @param { number } hoverIndex The hover index value to set
     */
    setHoverIndex(hoverIndex) {
        this.hoverIndex = hoverIndex;
    }
    /** @returns { number } */
    getHoverIndex() {
        return this.hoverIndex;
    }
    /**
     * Gets/sets the hover index value
     * @param { Error | null } error The hover index value to set
     */
    setError(error) {
        this.error = error;
    }
    /** @returns { Error | null } */
    getError() {
        return this.error;
    }
    /**
     * Gets/sets the hover index value
     * @param { NodeJS.Timeout } errorTimeout The hover index value to set
     */
    setErrorTimeout(errorTimeout) {
        this.errorTimeout = errorTimeout;
    }
    /** @returns { NodeJS.Timeout | undefined } */
    getErrorTimeout() {
        return this.errorTimeout;
    }
    /**
     * Emit an error and pass
     * @param {Error} error
     */
    emitError(error) {
        this.__error.emit({ error });
    }
    /**
     * Emits the no suggestions found error
     */
    emitNoSuggestionsFoundError() {
        /**
         * NOTE: Ideally this should be using `no_suggestions_found` key from Phrase Strings
         * however, given that it'll cost us to have any new key translated to all the available languages,
         * we'll settle with a generic `invalid_address_message` for now.
         */
        const localisedErrorMessage = t("invalid_address_message");
        this.__error.emit({ error: new Error(localisedErrorMessage) });
    }
    /**
     * Emits the invalid three word address error
     */
    emitInvalidAddressError() {
        var _a;
        const localisedInvalidAddressErrorMessage = (_a = this.invalid_address_error_message) !== null && _a !== void 0 ? _a : t("invalid_address_message");
        this.__error.emit({
            error: new Error(localisedInvalidAddressErrorMessage),
        });
    }
    /**
     * Emits the could not retrieve co-ordinates error
     */
    emitFatalError() {
        const localisedErrorMessage = t("error_message");
        this.__error.emit({
            error: new Error(localisedErrorMessage),
        });
    }
    clearErrorMessage() {
        const errorTimeout = this.getErrorTimeout();
        clearTimeout(errorTimeout);
        this.setError(null);
    }
    /**
     * Asynchronously retrieves autosuggestion results for a given search string and sets the results against the
     * component state. This method is idempotent and has a timeout delay to throttle requests, waiting for the user to
     * stop typing.
     * @param value The search string to retrieve autosuggestions for.
     */
    async getAutosuggestions(value) {
        clearTimeout(this.apiRequestTimeout);
        const options = this.getRequestOptions(value);
        return this.clients.autosuggest.run(options).finally(() => {
            const componentHeaders = this.getComponentHeaders();
            const { return_coordinates, typeahead_delay, variant, headers, base_url, api_key, } = this;
            utilisation
                .send({
                key: api_key,
                baseUrl: base_url,
                type: SessionType.Updated,
                headers: Object.assign(Object.assign({}, componentHeaders), (typeof this.headers === "string"
                    ? JSON.parse(this.headers)
                    : this.headers)),
                data: {
                    return_coordinates,
                    typeahead_delay,
                    variant,
                    component_version: version,
                },
            })
                .catch(() => {
                // TODO: Should log utilisation request failures
            });
        });
    }
    onValueChanged({ detail: { value } }) {
        var _a;
        if (this.selectedSuggestion)
            this.deselected_suggestion.emit({
                suggestion: this.selectedSuggestion,
            });
        this.setSelectedSuggestion(DEFAULTS.null);
        this.setRawValue(value);
        const valid = W3W_REGEX.test(value);
        if (valid) {
            const [, words] = (_a = W3W_REGEX.exec(value)) !== null && _a !== void 0 ? _a : ["", ""];
            this.setValue(words);
            this.value_valid.emit({
                value: DEFAULTS.prefix + words,
            });
        }
        else {
            this.setValue(value);
            this.value_invalid.emit({ value });
        }
    }
    onValueValid({ detail: { value } }) {
        clearTimeout(this.apiRequestTimeout);
        this.clearErrorMessage();
        this.setLoading(true);
        this.apiRequestTimeout = setTimeout(() => {
            this.getAutosuggestions(value)
                .then(({ suggestions }) => {
                this.setLoading(false);
                this.setHasFocus(true);
                this.suggestions_changed.emit({ suggestions });
            })
                .catch(() => {
                this.setLoading(false);
                this.setSuggestions();
                this.emitFatalError();
            });
        }, this.typeahead_delay);
    }
    onValueInvalid() {
        clearTimeout(this.apiRequestTimeout);
        this.setLoading(false);
        this.setSuggestions();
        this.setSelectedSuggestion(null);
        this.setShowSuggestions(false);
        this.setLat(null);
        this.setLng(null);
    }
    onSuggestionsChanged({ detail: { suggestions }, }) {
        this.setHoverIndex(-1);
        if (suggestions.length === 0) {
            this.suggestions_not_found.emit();
            return;
        }
        this.setSuggestions(suggestions);
        this.setShowSuggestions(true);
    }
    onSuggestionsNotFound() {
        this.setSuggestions([]);
        this.setShowSuggestions(false);
        this.emitNoSuggestionsFoundError();
    }
    onSelectedSuggestion({ detail: { suggestion }, }) {
        if (this.getInputElement()) {
            this.setInputValue(DEFAULTS.prefix + suggestion.words);
        }
        this.setSelectedSuggestion(suggestion);
        this.setValue(suggestion.words);
        this.setShowSuggestions(false);
        this.setHoverIndex(-1);
        this.clearErrorMessage();
        const componentHeaders = this.getComponentHeaders();
        this.clients.autosuggest
            .onSelected(suggestion)
            .catch((error) => this.emitError(error))
            .finally(() => {
            const { return_coordinates, typeahead_delay, variant, headers, base_url, api_key, } = this;
            utilisation
                .send({
                key: api_key,
                baseUrl: base_url,
                type: SessionType.Updated,
                headers: Object.assign(Object.assign({}, componentHeaders), (typeof this.headers === "string"
                    ? JSON.parse(this.headers)
                    : this.headers)),
                data: {
                    return_coordinates,
                    typeahead_delay,
                    variant,
                    component_version: version,
                },
            })
                .catch(() => {
                // TODO: Emit utilisation send error
            });
        });
        if (this.return_coordinates) {
            clearTimeout(this.apiRequestTimeout);
            this.apiRequestTimeout = setTimeout(() => {
                this.clients.convertToCoordinates
                    .run({
                    words: suggestion.words,
                })
                    .then(({ coordinates }) => {
                    return this.coordinates_changed.emit({ coordinates });
                })
                    .catch((error) => {
                    if (error.status === 402) {
                        const { details } = error;
                        // TT-9494 - Display error on the console log
                        console.error(details.message || error.message);
                        return;
                    }
                    return this.emitError(error);
                });
            }, 0);
        }
        else {
            this.setLat(null);
            this.setLng(null);
        }
    }
    _onSelectedCustomOption({ detail: { value }, }) {
        if (this.getInputElement()) {
            this.setInputValue(value);
        }
        this.options = [];
        this.setValue(value);
        this.setShowSuggestions(false);
        this.setHoverIndex(-1);
        this.clearErrorMessage();
    }
    _onCoordinatesChanged({ detail: { coordinates }, }) {
        this.setLat(coordinates.lat);
        this.setLng(coordinates.lng);
        const latInput = this.getLatInput();
        const lngInput = this.getLngInput();
        if (latInput) {
            latInput.value = `${this.getLat()}`;
        }
        if (lngInput) {
            lngInput.value = `${this.getLng()}`;
        }
    }
    _onHover({ detail: { suggestion }, }) {
        const suggestionsHoverIndex = this.getSuggestions().findIndex((s) => s.words === suggestion.words);
        const optionsHoverIndex = this.options.findIndex((s) => s.value === suggestion.value);
        if (suggestionsHoverIndex > -1) {
            this.setHoverIndex(suggestionsHoverIndex);
        }
        else if (optionsHoverIndex > -1) {
            this.setHoverIndex(optionsHoverIndex);
        }
    }
    _onFocus() {
        this.setHasFocus(true);
        this.setShowSuggestions((this.suggestions.length > 0 || this.options.length > 0) &&
            this.selectedSuggestion === null);
    }
    _onBlur() {
        const inputElement = this.getInputElement();
        if (!inputElement) {
            const error = new Error("Input element not found");
            this.emitError(error);
            return;
        }
        const isInputChanged = inputElement.value !== this.initial_value;
        if (isInputChanged && !this.getSelectedSuggestion() && this.strict) {
            this.setInputValue(DEFAULTS.emptyString);
            this.setValue(DEFAULTS.emptyString);
            this.emitInvalidAddressError();
        }
        else if (!this.strict && inputElement.value === DEFAULTS.prefix) {
            this.setInputValue(DEFAULTS.emptyString);
            this.setValue(DEFAULTS.emptyString);
        }
        this.setHasFocus(false);
        this.setShowSuggestions(false);
        this.setSuggestions([]);
    }
    _onError({ detail: { error } }) {
        const errTimeout = this.getErrorTimeout();
        clearTimeout(errTimeout);
        this.setError(error);
        this.setErrorTimeout(setTimeout(() => this.setError(null), 5000));
    }
    // Event listeners
    onInput(e) {
        const value = e.target.value;
        this.value_changed.emit({ value });
    }
    onPaste(event) {
        var _a, _b, _c;
        event.preventDefault();
        const pastedText = (_b = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData("text")) !== null && _b !== void 0 ? _b : "";
        const isValid3wa = W3W_REGEX.test(pastedText);
        let value;
        if (isValid3wa) {
            const [, words] = (_c = W3W_REGEX.exec(pastedText)) !== null && _c !== void 0 ? _c : ["", ""];
            value = DEFAULTS.prefix + words;
        }
        else {
            const startingPoint = 0;
            const { target: { selectionStart, selectionEnd, value: v }, } = event;
            value =
                v.replace(/$\/*/, "").substring(startingPoint, selectionStart) +
                    pastedText +
                    v.substring(selectionEnd);
        }
        event.target.value = value;
        this.value_changed.emit({ value });
    }
    onBlur() {
        this.__blur.emit();
    }
    onFocus(e) {
        const inputElement = this.getInputElement();
        const target = e.target;
        if (!inputElement) {
            const error = new Error("Input element not found");
            this.emitError(error);
            return;
        }
        if (target.value === "" || target.value === DEFAULTS.prefix) {
            target.value = DEFAULTS.prefix;
        }
        setTimeout(() => (inputElement.selectionStart = inputElement.selectionEnd =
            target.value.length), 0);
        this.__focus.emit();
    }
    onKeyUp(e) {
        var _a, _b;
        const { key } = e;
        const keys = ["Escape", "ArrowDown", "ArrowUp", "Enter"];
        if (!keys.includes(key))
            return;
        const suggestions = this.getSuggestions();
        const value = this.getValue();
        const suggestion = suggestions.find((s) => s.words === value.replace(/$\/*/, ""));
        const option = this.options.find((s) => s.value === value.replace(/$\/*/, ""));
        switch (key) {
            case "Escape":
                this.__blur.emit();
                this.setHoverIndex(-1);
                break;
            case "ArrowUp":
                if (this.options.length > 0) {
                    e.preventDefault();
                    this.setShowSuggestions(true);
                    if (this.options[this.hoverIndex - 1]) {
                        this.setHoverIndex(this.hoverIndex - 1);
                    }
                    else
                        this.setHoverIndex(this.options.length - 1);
                }
                else if (this.getSuggestions().length > 0) {
                    e.preventDefault();
                    this.setShowSuggestions(true);
                    if (suggestions[this.hoverIndex - 1]) {
                        this.setHoverIndex(this.hoverIndex - 1);
                    }
                    else
                        this.setHoverIndex(suggestions.length - 1);
                }
                break;
            case "ArrowDown":
                if (this.options.length > 0) {
                    e.preventDefault();
                    this.setShowSuggestions(true);
                    if (this.options[this.hoverIndex + 1]) {
                        this.setHoverIndex(this.hoverIndex + 1);
                    }
                    else
                        this.setHoverIndex(0);
                }
                else if (this.getSuggestions().length > 0) {
                    e.preventDefault();
                    this.setShowSuggestions(true);
                    if (suggestions[this.hoverIndex + 1]) {
                        this.setHoverIndex(this.hoverIndex + 1);
                    }
                    else
                        this.setHoverIndex(0);
                }
                break;
            case "Enter": {
                const currentOption = (_a = this.options[this.hoverIndex]) !== null && _a !== void 0 ? _a : option;
                const currentSuggestion = (_b = suggestions[this.hoverIndex]) !== null && _b !== void 0 ? _b : suggestion;
                if (currentOption) {
                    this.selected_custom_option.emit({
                        id: currentOption.id,
                        value: currentOption.value,
                    });
                }
                else if (currentSuggestion) {
                    this.selected_suggestion.emit({
                        suggestion: currentSuggestion,
                    });
                }
                this.setHoverIndex(-1);
                break;
            }
        }
    }
    connectedCallback() {
        // Setup form and input
        const { el, name, return_coordinates, typeahead_delay, variant, api_key, base_url, api_version, } = this;
        const form = el.closest("form");
        const inputElement = el.querySelector(SELECTORS.input);
        if (!inputElement) {
            const error = new Error("Input element not found");
            this.emitError(error);
            return;
        }
        this.setInputElement(inputElement);
        if (!this.initial_value) {
            this.initial_value = inputElement.value || inputElement.defaultValue;
        }
        if (this.initial_value) {
            this.setValue(this.initial_value);
        }
        if (form) {
            if (return_coordinates) {
                if (!form.querySelector(`#${name}_lat`)) {
                    const lat = window.document.createElement("input");
                    lat.type = "hidden";
                    lat.id = name + "_lat";
                    lat.name = name + "_lat";
                    lat.setAttribute("data-testid", "autosuggest-input-lat");
                    this.setLatInput(lat);
                    form.append(lat);
                }
                if (!form.querySelector(`#${name}_lng`)) {
                    const lng = window.document.createElement("input");
                    lng.type = "hidden";
                    lng.id = name + "_lng";
                    lng.name = name + "_lng";
                    lng.setAttribute("data-testid", "autosuggest-input-lng");
                    this.setLngInput(lng);
                    form.append(lng);
                }
            }
            form.addEventListener("reset", () => {
                this.value_changed.emit({ value: "" });
            }, { capture: true, passive: true });
        }
        // Configure service clients
        const componentHeaders = this.getComponentHeaders();
        const headers = Object.assign(Object.assign({}, componentHeaders), (typeof this.headers === "string"
            ? JSON.parse(this.headers)
            : this.headers));
        const config = {
            apiVersion: api_version,
            headers,
            host: base_url,
        };
        const transport = fetchTransport();
        this.clients = {
            autosuggest: what3wordsClients.autosuggest(this.api_key, config, transport),
            convertToCoordinates: what3wordsClients.convertToCoordinates(this.api_key, config, transport),
        };
        utilisation
            .send({
            key: api_key,
            baseUrl: base_url,
            type: SessionType.Started,
            headers,
            data: {
                return_coordinates,
                typeahead_delay,
                variant,
                component_version: version,
            },
        })
            .catch(() => {
            // TODO: Emit utilisation send error
        });
    }
    disconnectedCallback() {
        clearTimeout(this.apiRequestTimeout);
        clearTimeout(this.errorTimeout);
    }
    async componentWillLoad() {
        const { initial_value, callback, name } = this;
        const inputElement = this.getInputElement();
        const callbackFn = window[callback];
        if (typeof callbackFn === "function") {
            callbackFn();
        }
        if (W3W_REGEX.test(initial_value)) {
            const { suggestions } = await this.getAutosuggestions(initial_value);
            return this.suggestions_changed.emit({ suggestions });
        }
        if (!inputElement)
            return;
        if (!inputElement.placeholder) {
            inputElement.placeholder = t("input_hint");
        }
        if (!inputElement.value ||
            (inputElement.value.length === 0 && initial_value)) {
            inputElement.value = initial_value;
        }
        if (!inputElement.name) {
            inputElement.name = name;
        }
    }
    render() {
        var _a, _b, _c;
        const { input, variant, options, onClick, onCustomClick, onMouseOver, onMouseOut, } = this;
        const c = "what3words-autosuggest";
        const loading = this.getLoading();
        const selectedSuggestion = this.getSelectedSuggestion();
        const suggestions = this.getSuggestions();
        const error = this.getError();
        const state = [
            `${c}-state`,
            loading ? "loading" : "",
            selectedSuggestion ? "valid" : "",
        ].join(" ");
        const showSuggestions = this.getHasFocus() && this.getShowSuggestions();
        const visible = [
            `${c}-suggestions`,
            showSuggestions ? "visible" : "hidden",
        ].join(" ");
        return (h(Host, { key: '8cc49b1dfca57ed379bb4400448e03ef29b454f5', class: variant }, h("div", { key: '9c85b4b065268a22b9bf54925c9b0161b45de0d9', class: c + " " + variant }, h("div", { key: '35135ec4be4cd79f3c3eab6a0ab02c3c0c7bd200', class: `${c}-input-wrapper`, "data-testid": "input-wrapper" }, h("slot", { key: '959a5facac715e809f356ebb6b76aeb2306b7f9a' }), h(Status, { key: '561720192be9dd634d5457b1a2c3a98275d9feb5', class: state, offsetHeight: (_a = input === null || input === void 0 ? void 0 : input.offsetHeight) !== null && _a !== void 0 ? _a : null })), h(Suggestions, { key: '9496448b5ac901828ec954f2c2d937dd6d5583bd', class: visible, value: this.getValue(), hoverIndex: this.getHoverIndex(), suggestions: suggestions, options: options, offsetWidth: (_b = input === null || input === void 0 ? void 0 : input.offsetWidth) !== null && _b !== void 0 ? _b : null, onW3wSuggestionSelected: onClick.bind(this), onCustomOptionSelected: onCustomClick.bind(this), onMouseOver: onMouseOver.bind(this), onMouseOut: onMouseOut.bind(this) }), h(ErrorMessage, { key: '1bcce52c3e24bf522f1688fff6210ca4679f6ae6', error: error, offsetWidth: (_c = input === null || input === void 0 ? void 0 : input.offsetWidth) !== null && _c !== void 0 ? _c : null }))));
    }
    static get is() { return "what3words-autosuggest"; }
    static get originalStyleUrls() {
        return {
            "$": ["what3words-autosuggest.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["what3words-autosuggest.css"]
        };
    }
    static get properties() {
        return {
            "callback": {
                "type": "string",
                "attribute": "callback",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.emptyString"
            },
            "api_key": {
                "type": "string",
                "attribute": "api_key",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.emptyString"
            },
            "headers": {
                "type": "string",
                "attribute": "headers",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.headers"
            },
            "base_url": {
                "type": "string",
                "attribute": "base_url",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "sdk.api.clients.autosuggest[\"_config\"].host ?? DEFAULTS.base_url"
            },
            "api_version": {
                "type": "string",
                "attribute": "api_version",
                "mutable": false,
                "complexType": {
                    "original": "ApiVersion",
                    "resolved": "ApiVersion.Version1 | ApiVersion.Version2 | ApiVersion.Version3",
                    "references": {
                        "ApiVersion": {
                            "location": "import",
                            "path": "@what3words/api",
                            "id": "../../../node_modules/@what3words/api/dist/index.d.ts::ApiVersion"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "ApiVersion.Version3"
            },
            "name": {
                "type": "string",
                "attribute": "name",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.name"
            },
            "initial_value": {
                "type": "string",
                "attribute": "initial_value",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.emptyString"
            },
            "variant": {
                "type": "string",
                "attribute": "variant",
                "mutable": false,
                "complexType": {
                    "original": "Variant",
                    "resolved": "Variant.DEFAULT | Variant.INHERIT",
                    "references": {
                        "Variant": {
                            "location": "import",
                            "path": "@javascript-components/lib/constants",
                            "id": "src/lib/constants.ts::Variant"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.variant"
            },
            "typeahead_delay": {
                "type": "number",
                "attribute": "typeahead_delay",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.typeaheadDelay"
            },
            "invalid_address_error_message": {
                "type": "string",
                "attribute": "invalid_address_error_message",
                "mutable": true,
                "complexType": {
                    "original": "string | null",
                    "resolved": "null | string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.null"
            },
            "strict": {
                "type": "boolean",
                "attribute": "strict",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.true"
            },
            "language": {
                "type": "string",
                "attribute": "language",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "autosuggest_focus": {
                "type": "string",
                "attribute": "autosuggest_focus",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.emptyString"
            },
            "n_focus_results": {
                "type": "number",
                "attribute": "n_focus_results",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "clip_to_country": {
                "type": "string",
                "attribute": "clip_to_country",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.emptyString"
            },
            "clip_to_bounding_box": {
                "type": "string",
                "attribute": "clip_to_bounding_box",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.emptyString"
            },
            "clip_to_circle": {
                "type": "string",
                "attribute": "clip_to_circle",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.emptyString"
            },
            "clip_to_polygon": {
                "type": "string",
                "attribute": "clip_to_polygon",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.emptyString"
            },
            "return_coordinates": {
                "type": "boolean",
                "attribute": "return_coordinates",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "DEFAULTS.returnCoordinates"
            },
            "options": {
                "type": "unknown",
                "attribute": "options",
                "mutable": false,
                "complexType": {
                    "original": "CustomOption[]",
                    "resolved": "CustomOption[]",
                    "references": {
                        "CustomOption": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::CustomOption"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "defaultValue": "[]"
            }
        };
    }
    static get states() {
        return {
            "rawValue": {},
            "value": {},
            "input": {},
            "latInput": {},
            "lngInput": {},
            "suggestions": {},
            "selectedSuggestion": {},
            "showSuggestions": {},
            "hasFocus": {},
            "latitude": {},
            "longitude": {},
            "apiRequestTimeout": {},
            "loading": {},
            "hoverIndex": {},
            "error": {},
            "errorTimeout": {},
            "clients": {}
        };
    }
    static get events() {
        return [{
                "method": "value_changed",
                "name": "value_changed",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "InputValuePayload",
                    "resolved": "InputValuePayload",
                    "references": {
                        "InputValuePayload": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::InputValuePayload"
                        }
                    }
                }
            }, {
                "method": "value_valid",
                "name": "value_valid",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "InputValuePayload",
                    "resolved": "InputValuePayload",
                    "references": {
                        "InputValuePayload": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::InputValuePayload"
                        }
                    }
                }
            }, {
                "method": "value_invalid",
                "name": "value_invalid",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "InputValuePayload",
                    "resolved": "InputValuePayload",
                    "references": {
                        "InputValuePayload": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::InputValuePayload"
                        }
                    }
                }
            }, {
                "method": "selected_suggestion",
                "name": "selected_suggestion",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "SuggestionPayload",
                    "resolved": "SuggestionPayload",
                    "references": {
                        "SuggestionPayload": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::SuggestionPayload"
                        }
                    }
                }
            }, {
                "method": "suggestions_changed",
                "name": "suggestions_changed",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "SuggestionsPayload",
                    "resolved": "SuggestionsPayload",
                    "references": {
                        "SuggestionsPayload": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::SuggestionsPayload"
                        }
                    }
                }
            }, {
                "method": "suggestions_not_found",
                "name": "suggestions_not_found",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }, {
                "method": "coordinates_changed",
                "name": "coordinates_changed",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "CoordinatesPayload",
                    "resolved": "CoordinatesPayload",
                    "references": {
                        "CoordinatesPayload": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::CoordinatesPayload"
                        }
                    }
                }
            }, {
                "method": "selected_custom_option",
                "name": "selected_custom_option",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "CustomOption",
                    "resolved": "CustomOption",
                    "references": {
                        "CustomOption": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::CustomOption"
                        }
                    }
                }
            }, {
                "method": "deselected_suggestion",
                "name": "deselected_suggestion",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "SuggestionPayload",
                    "resolved": "SuggestionPayload",
                    "references": {
                        "SuggestionPayload": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::SuggestionPayload"
                        }
                    }
                }
            }, {
                "method": "__hover",
                "name": "__hover",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "SuggestionPayload",
                    "resolved": "SuggestionPayload",
                    "references": {
                        "SuggestionPayload": {
                            "location": "import",
                            "path": "./domain",
                            "id": "src/components/what3words-autosuggest/domain.ts::SuggestionPayload"
                        }
                    }
                }
            }, {
                "method": "__focus",
                "name": "__focus",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }, {
                "method": "__blur",
                "name": "__blur",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }, {
                "method": "__error",
                "name": "__error",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "{ error: Error }",
                    "resolved": "{ error: Error; }",
                    "references": {
                        "Error": {
                            "location": "global",
                            "id": "global::Error"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "api_key",
                "methodName": "setApiKey"
            }, {
                "propName": "base_url",
                "methodName": "setBaseUrl"
            }, {
                "propName": "api_version",
                "methodName": "setApiVersion"
            }, {
                "propName": "headers",
                "methodName": "setHeaders"
            }, {
                "propName": "options",
                "methodName": "setCustomOptions"
            }];
    }
    static get listeners() {
        return [{
                "name": "value_changed",
                "method": "onValueChanged",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "value_valid",
                "method": "onValueValid",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "value_invalid",
                "method": "onValueInvalid",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "suggestions_changed",
                "method": "onSuggestionsChanged",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "suggestions_not_found",
                "method": "onSuggestionsNotFound",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "selected_suggestion",
                "method": "onSelectedSuggestion",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "selected_custom_option",
                "method": "_onSelectedCustomOption",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "coordinates_changed",
                "method": "_onCoordinatesChanged",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "__hover",
                "method": "_onHover",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "__focus",
                "method": "_onFocus",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "__blur",
                "method": "_onBlur",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "__error",
                "method": "_onError",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "input",
                "method": "onInput",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "paste",
                "method": "onPaste",
                "target": undefined,
                "capture": true,
                "passive": false
            }, {
                "name": "blur",
                "method": "onBlur",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "focus",
                "method": "onFocus",
                "target": undefined,
                "capture": true,
                "passive": true
            }, {
                "name": "keyup",
                "method": "onKeyUp",
                "target": undefined,
                "capture": true,
                "passive": false
            }];
    }
}
