/*!
 * Custom elements for Nanopore-Digital Web applications
 */
import { Host, Build, writeTask, readTask, } from "@stencil/core";
import algoliasearch from "algoliasearch/dist/algoliasearch-lite.esm.browser";
import { getDirectChildren } from "../../utils/dom";
import { PromiseQueue } from "../../utils/promise-queue";
import { ComponentStore, } from "../../utils/store/component-store";
import { debounce } from "../../utils/throttle";
import { transformTag, h } from "../../utils/renderer";
import { Squirrel } from "./lib/template";
import { Universe, SearchChangeEvent } from "./algolia-data";
/**
 * Algolia search container to contain and sync nano-algolia-results and nano-algolia-filter components.
 * @slot search-input - optional. Should contain an `input` or `nano-input` component.
 * @slot loader - optional. Elements to show when search results are loading.
 * @slot template - optional. Template string (format depends on 'tplEngine' property). May contain other algolia-... components with nested templates.
 * @slot output - Search result output. Will be a placeholder for template output or optionally nest algolia-... components.
 */
export class Algolia {
    /* eslint-disable @stencil-community/strict-mutable */
    // filters that have an initial value
    staticFacetFilters = {};
    dynFacetFilters = {};
    tplSlot;
    outputSlot;
    slottedInput;
    hasLoadSlot = false;
    resultsDiv;
    defaultDiv;
    tpl;
    facets;
    placedAlgoliaEles = [];
    algoliaClient;
    // lots of stuff happens asynchronously. This makes sure they fire in the correct order
    promiseQueue = new PromiseQueue();
    host;
    // Internal state
    // filters that change via a template. They have no initial value
    _dynFacetFilters = {};
    inputField;
    algoliaIndex;
    indeces = [];
    indexResults;
    filterChanged = '';
    currentHits;
    changeEvent = SearchChangeEvent.Init;
    isLoading = false;
    wormholeState = this;
    // Public props
    /**
     * Show the result panel. By default it will automatically show when the result receives new hits.
     */
    showResults = false;
    /**
     * The current algolia page of results currently being viewed or to get.
     */
    resultsPage = 0;
    /**
     * An Algolia App ID key. Used in conjunction with 'searchIndex' & 'apiKey'.
     */
    appId;
    /**
     * An Algolia API Key. Used in conjunction with 'searchIndex' & 'appId'.
     */
    apiKey;
    /**
     * Algolia search index. Used in conjunction with 'apiKey' & 'appId'.
     * ```
     * { index: string, // algolia index name
     *   domain?: string, // used in template filters to resolve incomplete url fields
     *   filters?: [string], // algolia facets to retrive
     *   hitsPerPage?: number,
     *   name?: string // human readable index name
     * }
     * ```
     */
    searchIndex = {};
    /**
     * Algolia search index name. Alternative to 'searchIndex'.
     * A simplified shortcut for setting an index.
     * Properties such as hitsPerPage and facets will come from the algolia index
     */
    searchIndexName = '';
    /**
     * JS querySelector string of a `nano-input` / `input` element from which
     * to listen to `nano-change` or `change` events and change the `query` prop.
     * Not required if an appropriate field is in the 'search-input' slot
     */
    listenTo = null;
    handleListenToChange() {
        if (!this.listenTo)
            return;
        const foundInput = document.querySelector(this.listenTo);
        if (['nano-input', 'input'].includes(foundInput.tagName.toLocaleLowerCase())) {
            this.inputField = foundInput;
        }
    }
    /**
     * The query string used to search the index. Will automatically be set with any slotted
     * `search-input` input elements or from elements linked to from `listen-to`
     */
    query = '';
    /**
     * The external operator joining filter values.
     */
    operator = 'and';
    /**
     * Query filters to apply to all searches.
     * Refer to https://www.algolia.com/doc/api-reference/api-parameters/filters for format.
     */
    filters = [];
    /**
     * Template engine render function to use when rendering results and filters.
     * Defaults to Squirrel v8's render (https://squirrelly.js.org/).
     */
    tplRenderFn = Squirrel.render;
    /**
     * Changes the index without removing any current filters. Most appropriate for algolia replicas.
     */
    replicaIndex = '';
    /**
     * Will maintain a search all / '*' on init and reset allowing for a view
     * then filter experience rather than a search first experience
     */
    browseIndex = false;
    /**
     * Minimum number of characters before performing a search
     */
    minChars = 2;
    /**
     * Store search queries (against this ID) to the component store.
     * Use in conjunction with storeMethod
     */
    storeId;
    /**
     * The method of storage.
     * Either session storage, url hash (after the '#') or url query (after the '?').
     */
    storeMethod = 'session';
    // Events
    /**
     * Emitted when the algolia element has been created.
     */
    nanoDidLoad;
    /**
     * Emitted when results and all filters are shown and have loaded.
     */
    nanoResultsShown;
    /**
     * Emitted before an algolia search.
     */
    nanoBeforeQuery;
    /**
     * Emitted after an algolia search.
     */
    nanoAfterQuery;
    /**
     * Emitted after an results have been updated
     */
    nanoNewResults;
    // Public methods
    /**
     * @param facetName - will clear all filter selections of that type
     * @param facetValue - will remove a single filter selection
     * Remove facet filters (as set from nano-algolia-filter elements).
     * The omission or both will remove all facet filters
     */
    async removeFilters(facetName, facetValue) {
        if (!facetName && !facetValue)
            this.clearAllFacetFilters();
        else {
            Object.keys(this._dynFacetFilters).forEach((filterId) => {
                if (facetName &&
                    this._dynFacetFilters[filterId].facetName === facetName) {
                    if (!facetValue)
                        this._dynFacetFilters[filterId].element.value = '';
                    else {
                        this._dynFacetFilters[filterId].element.value =
                            this._dynFacetFilters[filterId].value.filter((val) => val !== facetValue);
                    }
                }
            });
        }
    }
    // Listeners to external events
    // a child nano-algolia-... updated their template
    onAllTplUpdate(ev) {
        ev.stopPropagation();
        if (ev.target.tagName.toLowerCase() === transformTag('nano-algolia-results')) {
            requestAnimationFrame(() => {
                this.nanoNewResults.emit(this.indexResults);
            });
        }
    }
    // a nano-algolia-pagination or nano-algolia-results changed the page
    async onPageChange(ev) {
        if (!this.indexResults)
            return;
        let page = this.resultsPage;
        if (ev) {
            ev.stopPropagation();
            page = ev.detail.page;
        }
        page = Math.min(this.indexResults.totalPages - 1, page);
        page = Math.max(page, 0);
        if (this.indexResults.currentPage === page)
            return;
        this.indexResults.currentPage = page;
        await this.algoliaSearch(SearchChangeEvent.Page);
    }
    /**
     * nano-algolia-filter changed value.
     * If that happened before a indexResults were setup, it was a static filter.
     * Static filters persist accross search changes
     */
    async onFilterChange(ev) {
        ev.stopPropagation();
        const dynFilterObj = {};
        const filter = ev.detail;
        filter.element = ev.target;
        if (this.indexResults) {
            if (this.staticFacetFilters[filter.filterId])
                this.staticFacetFilters[filter.filterId] = filter;
            else {
                dynFilterObj[filter.filterId] = filter;
                this._dynFacetFilters = { ...this._dynFacetFilters, ...dynFilterObj };
            }
            this.indexResults.appliedFilters = this.makeAppliedFilters();
        }
        else
            this.staticFacetFilters[filter.filterId] = filter;
        this.filterChanged =
            filter.value && filter.value.length ? filter.filterId : 'all';
        this.resetPage();
        this.algoliaSearch(SearchChangeEvent.Filter);
    }
    // Internal state watchers
    // Filters can fire a change event, cause a re-render then get detached.
    // This can cause filter dupes. Check to see if the original element is still in the DOM.
    dynFacetFiltersChange() {
        Object.values(this._dynFacetFilters).forEach((filter) => {
            if (this.host.ownerDocument === filter.element.ownerDocument)
                this.dynFacetFilters[filter.filterId] = filter;
            else
                delete this.dynFacetFilters[filter.filterId];
        });
    }
    browseIndexChange() {
        if (this.browseIndex &&
            (!this.query || this.query.length < this.minChars)) {
            this.query = '*';
        }
    }
    inputFieldSet() {
        if (!this.inputField)
            return;
        if (this.query !== '*' &&
            this.inputField &&
            this.inputField.value !== this.query)
            this.inputField.value = this.query;
    }
    queryChange() {
        this.searchChange();
    }
    searchChange = async () => {
        if (!this.algoliaIndex)
            return;
        if (!this.query || this.query.length < this.minChars) {
            if (!this.browseIndex) {
                if (!this.query || this.query.length === 0) {
                    this.handleSearchReset();
                    return;
                }
                else
                    return;
            }
            else if (this.query !== '*') {
                this.query = '*';
                return;
            }
        }
        // Do an initialise search (setup searchIndex)
        this.isLoading = true;
        setTimeout(async () => {
            // Clear dynamic filters and reset page
            this.resetPage();
            await this.algoliaSearch(SearchChangeEvent.Init);
            // Populate master content - optionally from template
            await this.updateContent();
            setTimeout((_) => (this.isLoading = false), 800);
            this.showResults = true;
            this.nanoResultsShown.emit({
                meta: this.indexResults,
                client: { appId: this.appId, apiKey: this.apiKey },
            });
        }, 200);
    };
    async internalIndexSwitch() {
        if (!this.replicaIndex ||
            !this.indexResults ||
            this.indexResults.index === this.replicaIndex)
            return;
        this.indexResults.index = this.replicaIndex;
        this.algoliaIndex = this.algoliaClient.initIndex(this.indexResults.index);
        this.resetPage();
        this.algoliaSearch(SearchChangeEvent.Replica);
    }
    pageChange() {
        this.onPageChange();
    }
    searchIndexNameChange() {
        if (!this.searchIndexName ||
            !this.searchIndexName.length ||
            (this.searchIndex && this.searchIndex.index === this.searchIndexName))
            return;
        this.searchIndex = { index: this.searchIndexName };
    }
    initAlgoliaClient() {
        if (!this.appId || !this.apiKey)
            return;
        this.algoliaClient = algoliasearch(this.appId, this.apiKey);
    }
    initAlgoliaIndex() {
        if (!this.algoliaClient || !this.searchIndex)
            return;
        if (this.searchIndex.index) {
            if (!this.searchIndex.hitsPerPage)
                this.searchIndex.hitsPerPage = 100;
            if (this.replicaIndex)
                this.searchIndex.index = this.replicaIndex;
            this.searchIndexName = this.searchIndex.index;
            this.algoliaIndex = this.algoliaClient.initIndex(this.searchIndex.index);
            this.searchChange();
        }
    }
    showResultsChange() {
        if (!this.resultsDiv || !this.defaultDiv)
            return;
        if (this.showResults) {
            this.resultsDiv.style.width = this.host.scrollWidth + 'px';
            this.resultsDiv.style.minHeight = this.host.scrollHeight + 'px';
            writeTask(() => {
                this.resultsDiv.addEventListener('transitionend', this.onResultDisplay);
                this.resultsDiv.style.display = 'block';
                setTimeout(() => this.resultsDiv.classList.add('show'), 50);
            });
        }
        else {
            writeTask(() => {
                this.resultsDiv.classList.remove('shown');
                this.defaultDiv.style.display = 'block';
                setTimeout(() => {
                    this.resultsDiv.addEventListener('transitionend', this.onResultDisplay);
                    this.resultsDiv.classList.remove('show');
                    if (this.slottedInput)
                        this.slottedInput.focus({ preventScroll: true });
                    else
                        this.defaultDiv.focus({ preventScroll: true });
                }, 50);
            });
        }
    }
    handleFilterpropChange() {
        this.algoliaSearch(SearchChangeEvent.Init);
    }
    // Internal methods
    fixDomain(results) {
        if (!this.searchIndex || !this.searchIndex.domain)
            return results;
        results.hits.map((hit) => {
            if (hit.url && !hit.url.match(/^http/))
                hit.url = location.protocol + '//' + this.searchIndex.domain + hit.url;
        });
        return results;
    }
    // Takes all current filters (dynamic and static)
    // and merges common filters' values togther
    makeAppliedFilters = () => {
        const appliedFtrs = [];
        const makeAppliedFilter = (facetFilters) => {
            Object.values(facetFilters).forEach((filter) => {
                if (filter.value && filter.value.length) {
                    const found = appliedFtrs.find((appFilter) => appFilter.name === filter.facetName);
                    if (!found)
                        appliedFtrs.push({
                            name: filter.facetName,
                            values: [...filter.value],
                        });
                    else
                        found.values = [...found.values, ...filter.value];
                }
            });
        };
        makeAppliedFilter(this.dynFacetFilters);
        makeAppliedFilter(this.staticFacetFilters);
        if (appliedFtrs.length)
            return appliedFtrs;
        return null;
    };
    // Queue up a search
    algoliaSearch = async (eventType) => {
        return this.promiseQueue.enqueue(() => this.queueSearch(eventType));
    };
    // Do a search
    queueSearch = async (eventType) => {
        if (!this.algoliaIndex ||
            !this.query ||
            !this.searchIndex ||
            !this.searchIndex.index)
            return;
        this.nanoBeforeQuery.emit(this.indexResults);
        // clear all facet filters on init (new query)
        if (SearchChangeEvent.Init === eventType)
            this.clearAllFacetFilters();
        const searchParams = {
            filters: this.algoliaFilterStr(),
            page: this.indexResults ? this.indexResults.currentPage : 0,
            clickAnalytics: true,
        };
        if (this.searchIndex.filters)
            searchParams.facets = this.searchIndex.filters;
        if (this.searchIndex.hitsPerPage)
            searchParams.hitsPerPage = this.searchIndex.hitsPerPage;
        let result = (await this.algoliaIndex.search(this.query, searchParams));
        result = this.fixDomain(result);
        // set event type - this informs children components why things changed
        this.changeEvent = eventType;
        // Setup initial meta on new queries. Some of it should not change on filter / pagination
        if (eventType === SearchChangeEvent.Init || !this.indexResults) {
            this.indexResults = {
                queryID: result.queryID,
                currentPage: 0,
                totalHits: result.nbHits,
                hitsPerPage: null,
                origFilters: result.facets,
                query: this.query,
                domain: this.searchIndex.domain || null,
                totalHitsWithFilters: 0,
                results: [],
                totalPages: 0,
                appliedFilters: this.makeAppliedFilters(),
                indexName: this.searchIndex.name || null,
                index: this.searchIndex.index,
                searchIndex: this.searchIndex,
            };
        }
        this.indexResults.dynFilters = result.facets;
        this.indexResults.results = result.hits;
        this.indexResults.totalHitsWithFilters = result.nbHits;
        this.indexResults.currentPage = result.page;
        this.indexResults.totalPages = result.nbPages;
        this.indexResults.hitsPerPage = result.hitsPerPage;
        this.indexResults.query = result.query;
        // console.log('I GOT NEW RESULTS', eventType, this.query, this.algoliaFilterStr(), this.indexResults.results.length, this.indexResults.currentPage )
        if (this.changeEvent !== SearchChangeEvent.Page &&
            this.changeEvent !== SearchChangeEvent.Replica) {
            this.facets = result.facets;
        }
        this.nanoAfterQuery.emit(this.indexResults);
        // current hits and page will cause re-renders in children components.
        // Wait a tick before firing otherwise events can fire in the wrong order
        return new Promise((resolve) => {
            setTimeout(() => resolve('tpl updated'), 20);
        }).then((_) => {
            this.currentHits = this.indexResults.results;
            this.resultsPage = this.indexResults.currentPage;
        });
    };
    resetPage() {
        if (!this.indexResults)
            return;
        this.indexResults.currentPage = 0;
    }
    clearAllFacetFilters() {
        Object.values(this._dynFacetFilters).forEach((filter) => {
            filter.element.value = '';
        });
        this._dynFacetFilters = {};
    }
    algoliaFilterStr() {
        // groups applied facet filters (from algolia-filter components)
        // with their applied, 'internal' operators (and, or, not)
        const facetFilterObj = {};
        const groupFilters = (facetFilters) => {
            let filter;
            let filterOp;
            Object.keys(facetFilters).forEach((filterId) => {
                filter = facetFilters[filterId];
                facetFilterObj[filterId] = facetFilterObj[filterId] || {
                    name: filter.facetName,
                    or: [],
                    and: [],
                    not: [],
                };
                filterOp = facetFilterObj[filterId][filter.operator];
                if (filter.value && filter.value.length) {
                    facetFilterObj[filterId][filter.operator] = [
                        ...filterOp,
                        ...filter.value,
                    ];
                }
            });
        };
        groupFilters(this.dynFacetFilters);
        groupFilters(this.staticFacetFilters);
        const formatVal = (name, val) => {
            if (val.indexOf(' ') > -1)
                return name + ':"' + val + '"';
            else
                return name + ':' + val;
        };
        let filterStrParts = [];
        let operatorGrp;
        let filterName;
        // let processedFilters: string[] = [];
        // joins all applied facet filter operator groups with the set 'outer'
        // operator into an algolia filter query string
        Object.values(facetFilterObj).forEach(function (filter) {
            Object.keys(filter)
                .filter((filterProp) => filterProp.match(/(or|and|not)/))
                .forEach((operator) => {
                operatorGrp = filter;
                filterName = filter.name;
                if (operator === 'or' || operator === 'and') {
                    if (operatorGrp[operator].length) {
                        filterStrParts.push('( \
                ' +
                            operatorGrp[operator]
                                .map((val) => {
                                if (val.length)
                                    return formatVal(filterName, val);
                            })
                                .join(' ' + operator.toLocaleUpperCase() + ' ') +
                            ' \
              )');
                    }
                }
                else {
                    if (operatorGrp.not.length) {
                        filterStrParts.push('( \
                ' +
                            operatorGrp[operator]
                                .map((val) => {
                                if (val.length)
                                    return 'NOT ' + formatVal(filterName, val);
                            })
                                .join(' AND ') +
                            ' \
              )');
                    }
                }
            });
        });
        // add in any static applied filters from filters prop
        filterStrParts = [...this.filters, ...filterStrParts];
        // console.log('filterStr:', filterStrParts.join(' ' + this.operator.toLocaleUpperCase() + ' '))
        return filterStrParts.join(' ' + this.operator.toLocaleUpperCase() + ' ');
    }
    handleInputChange(ev) {
        if (ev.target !== this.inputField)
            return;
        this.query = this.inputField.value;
    }
    handleSearchReset = () => {
        this.showResults = false;
        this.indexResults = null;
    };
    onResultDisplay = () => {
        writeTask(() => {
            this.resultsDiv.removeEventListener('transitionend', this.onResultDisplay);
            if (!this.showResults)
                this.resultsDiv.style.display = 'none';
            else {
                this.defaultDiv.style.display = 'none';
                this.resultsDiv.classList.add('shown');
                this.resultsDiv.style.minHeight = '';
                this.resultsDiv.style.width = '';
            }
        });
    };
    async updateContent() {
        return this.promiseQueue.enqueue(() => this.updateContentQueue());
    }
    async updateContentQueue() {
        const outputTo = this.outputSlot || this.resultsDiv;
        if (!outputTo || !this.tpl)
            return 'no tpl';
        const tmpCont = document.createElement('div');
        tmpCont.innerHTML = this.tpl;
        const algoliaEles = [];
        this.placedAlgoliaEles = [];
        // take out children algolia elements 'cos they have their own templates
        // don't want to swap in their templates
        Array.from(tmpCont.querySelectorAll(`${transformTag('nano-algolia')}, ${transformTag('nano-algolia-filter')}, ${transformTag('nano-algolia-results')}`)).forEach((el, i) => {
            const placeholder = document.createElement('div');
            placeholder.dataset.placeholderId = i.toString();
            placeholder.classList.add('nano-ele-placeholder');
            algoliaEles.push(el);
            el.parentNode.replaceChild(placeholder, el);
        });
        // swap in template content
        // (all this nonsense htmlencodes any < or >)
        outputTo.innerHTML = this.tplRenderFn(tmpCont.innerHTML
            .replace(/&gt;/gm, '>')
            .replace(/&lt;/gm, '<')
            .replace(/&amp;/gm, '&'), this.indexResults);
        // put back in algolia elements
        Array.from(outputTo.querySelectorAll('div.nano-ele-placeholder')).forEach((el) => {
            el.parentNode.replaceChild(algoliaEles[parseInt(el.dataset.placeholderId)], el);
            this.placedAlgoliaEles.push(algoliaEles[parseInt(el.dataset.placeholderId)]);
        });
        if (!this.placedAlgoliaEles.length)
            return Promise.resolve('algolia setup');
        // wait for all children algolia elements to resolve before calling 'done'
        return new Promise((resolve) => {
            const childrenResolver = (ev) => {
                this.placedAlgoliaEles = this.placedAlgoliaEles.filter((ele) => ele !== ev.detail);
                if (!this.placedAlgoliaEles.length) {
                    setTimeout(() => resolve('tpl updated'), 500);
                    outputTo.removeEventListener('nanoTplUpdated', childrenResolver);
                }
            };
            outputTo.addEventListener('nanoTplUpdated', childrenResolver);
        });
    }
    // Stencil hooks
    componentWillLoad() {
        readTask((_) => {
            this.tplSlot = getDirectChildren(this.host, '[slot="template"]')[0];
            this.outputSlot = getDirectChildren(this.host, '[slot="output"]')[0];
            this.slottedInput = getDirectChildren(this.host, '[slot="search-input"]')[0];
            this.hasLoadSlot = !!getDirectChildren(this.host, '[slot="loader"]')[0];
            if (this.tplSlot)
                this.tpl = this.tplSlot.innerHTML || this.tplSlot.innerText;
            // get input field to listen to
            if (this.slottedInput &&
                (this.slottedInput.tagName.toLocaleLowerCase() ===
                    transformTag('nano-input') ||
                    this.slottedInput instanceof HTMLInputElement)) {
                this.inputField = this.slottedInput;
            }
            else if (this.slottedInput) {
                this.inputField = this.slottedInput.querySelector(`${transformTag('nano-input')}, input:not([type="radio"]):not([type="checkbox"])`);
            }
            else
                this.handleListenToChange();
            writeTask((_) => {
                if (this.showResults && this.tpl)
                    this.searchChange();
            });
        });
        this.searchIndexNameChange();
        this.initAlgoliaClient();
        this.initAlgoliaIndex();
        // Create wormwhole shared 'universe' (https://github.com/mihar-22/stencil-wormhole)
        Universe.create(this, this.wormholeState);
        if (this.storeId) {
            ComponentStore.init(this, ['query', 'replicaIndex'], this.storeMethod, this.storeId);
            ComponentStore.init(this, ['apiKey', 'appId', 'searchIndex'], 'session', this.storeId + '_api');
        }
        this.internalIndexSwitch();
    }
    connectedCallback() {
        this.searchChange = debounce(this.searchChange, 300);
        this.browseIndexChange();
        if (!Build.isBrowser)
            return;
        this.host.dispatchEvent(new CustomEvent('nanoDidLoad', {
            detail: this.host,
        }));
    }
    render() {
        const wormholeState = {
            indexResults: this.indexResults,
            results: this.currentHits,
            filterChanged: this.filterChanged,
            tplRenderFn: this.tplRenderFn,
            resultsPage: this.resultsPage,
            changeEvent: this.changeEvent,
            facets: this.facets,
            algoliaIndex: this.algoliaIndex,
            searchIndex: this.searchIndex,
            globalStoreMethod: this.storeMethod,
            isLoading: this.isLoading,
        };
        return (h(Host, { key: 'e5a080bf3b11c991465f1b44521b75539f80d5ec', class: {
                'show-results': this.showResults,
                'is-loading': this.isLoading,
                'nano-algolia': true,
            }, "aria-busy": this.isLoading }, this.hasLoadSlot && (h("div", { key: '586696526af9ba7b721ebfe8aeba2b5a45b8a19a', hidden: !this.isLoading }, h("slot", { key: '40556633911954fd20b756fedf71aea7e15b15e1', name: "loader" }))), !this.hasLoadSlot && (h("div", { key: 'e5ee4968b6864b656b3537ec46b69e64ebe76370', class: {
                loader: true,
                loading: this.isLoading,
            } }, h("nano-spinner", { key: '420a97d058127ea029329d6eca5055c0c54f4c1f', overlay: true }))), h(Universe.Provider, { key: '9c271e35ea7f850eb1ec2f99415ab2eebf014387', state: wormholeState }, h("slot", { key: '7a7a5ac869321d6db0a2f6f784a28e638cbe1a3f', name: "search-input" }), h("div", { key: '91b799022bee756066f1eb60038fdb428c98d3dc', class: "results-container", "aria-live": "polite" }, h("div", { key: '4209e438e0cefbc244dde4c3a9c10e3e5bf56137', ref: (div) => (this.resultsDiv = div), class: "results" }, h("slot", { key: '44b89a4cae72f8ff38c08dd605df32df03a2fc9a', name: "output" })))), h("div", { key: 'a584e0f2f10c38ffc46decc5b4b6bd2a1e14118a', ref: (div) => (this.defaultDiv = div), class: "default", tabindex: "-1", part: "default-content" }, h("slot", { key: 'dcf3c87479d48774b63bf32b4e2de2bfe9a6b1ea' }))));
    }
    static get is() { return "nano-algolia"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["algolia.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["algolia.css"]
        };
    }
    static get properties() {
        return {
            "showResults": {
                "type": "boolean",
                "attribute": "show-results",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Show the result panel. By default it will automatically show when the result receives new hits."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "resultsPage": {
                "type": "number",
                "attribute": "results-page",
                "mutable": true,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The current algolia page of results currently being viewed or to get."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "0"
            },
            "appId": {
                "type": "string",
                "attribute": "app-id",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "An Algolia App ID key. Used in conjunction with 'searchIndex' & 'apiKey'."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "apiKey": {
                "type": "string",
                "attribute": "api-key",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "An Algolia API Key. Used in conjunction with 'searchIndex' & 'appId'."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "searchIndex": {
                "type": "unknown",
                "attribute": "search-index",
                "mutable": true,
                "complexType": {
                    "original": "SearchIndex",
                    "resolved": "SearchIndex",
                    "references": {
                        "SearchIndex": {
                            "location": "import",
                            "path": "./algolia-interface",
                            "id": "src/components/algolia/algolia-interface.ts::SearchIndex"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Algolia search index. Used in conjunction with 'apiKey' & 'appId'.\n```\n{ index: string, // algolia index name\n  domain?: string, // used in template filters to resolve incomplete url fields\n  filters?: [string], // algolia facets to retrive\n  hitsPerPage?: number,\n  name?: string // human readable index name\n}\n```"
                },
                "getter": false,
                "setter": false,
                "defaultValue": "{} as SearchIndex"
            },
            "searchIndexName": {
                "type": "string",
                "attribute": "search-index-name",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Algolia search index name. Alternative to 'searchIndex'.\nA simplified shortcut for setting an index.\nProperties such as hitsPerPage and facets will come from the algolia index"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "''"
            },
            "listenTo": {
                "type": "string",
                "attribute": "listen-to",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "JS querySelector string of a `nano-input` / `input` element from which\nto listen to `nano-change` or `change` events and change the `query` prop.\nNot required if an appropriate field is in the 'search-input' slot"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "null"
            },
            "query": {
                "type": "string",
                "attribute": "query",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The query string used to search the index. Will automatically be set with any slotted\n`search-input` input elements or from elements linked to from `listen-to`"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "''"
            },
            "operator": {
                "type": "string",
                "attribute": "operator",
                "mutable": false,
                "complexType": {
                    "original": "'or' | 'and'",
                    "resolved": "\"and\" | \"or\"",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The external operator joining filter values."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'and'"
            },
            "filters": {
                "type": "unknown",
                "attribute": "filters",
                "mutable": false,
                "complexType": {
                    "original": "Array<string>",
                    "resolved": "string[]",
                    "references": {
                        "Array": {
                            "location": "global",
                            "id": "global::Array"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Query filters to apply to all searches.\nRefer to https://www.algolia.com/doc/api-reference/api-parameters/filters for format."
                },
                "getter": false,
                "setter": false,
                "defaultValue": "[]"
            },
            "tplRenderFn": {
                "type": "unknown",
                "attribute": "tpl-render-fn",
                "mutable": false,
                "complexType": {
                    "original": "(...args: any[]) => any",
                    "resolved": "(...args: any[]) => any",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Template engine render function to use when rendering results and filters.\nDefaults to Squirrel v8's render (https://squirrelly.js.org/)."
                },
                "getter": false,
                "setter": false,
                "defaultValue": "Squirrel.render"
            },
            "replicaIndex": {
                "type": "string",
                "attribute": "replica-index",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Changes the index without removing any current filters. Most appropriate for algolia replicas."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "''"
            },
            "browseIndex": {
                "type": "boolean",
                "attribute": "browse-index",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Will maintain a search all / '*' on init and reset allowing for a view\nthen filter experience rather than a search first experience"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "minChars": {
                "type": "number",
                "attribute": "min-chars",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Minimum number of characters before performing a search"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "2"
            },
            "storeId": {
                "type": "string",
                "attribute": "store-id",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Store search queries (against this ID) to the component store.\nUse in conjunction with storeMethod"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "storeMethod": {
                "type": "string",
                "attribute": "store-method",
                "mutable": false,
                "complexType": {
                    "original": "StorageMethods",
                    "resolved": "\"local\" | \"session\" | \"url-hash\" | \"url-hash-push\" | \"url-query\" | \"url-query-push\"",
                    "references": {
                        "StorageMethods": {
                            "location": "import",
                            "path": "../../utils/store/component-store",
                            "id": "src/utils/store/component-store.ts::StorageMethods"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The method of storage.\nEither session storage, url hash (after the '#') or url query (after the '?')."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'session'"
            }
        };
    }
    static get states() {
        return {
            "_dynFacetFilters": {},
            "inputField": {},
            "algoliaIndex": {},
            "indeces": {},
            "indexResults": {},
            "filterChanged": {},
            "currentHits": {},
            "changeEvent": {},
            "isLoading": {},
            "wormholeState": {}
        };
    }
    static get events() {
        return [{
                "method": "nanoDidLoad",
                "name": "nanoDidLoad",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the algolia element has been created."
                },
                "complexType": {
                    "original": "HTMLNanoAlgoliaElement",
                    "resolved": "HTMLNanoAlgoliaElement",
                    "references": {
                        "HTMLNanoAlgoliaElement": {
                            "location": "global",
                            "id": "global::HTMLNanoAlgoliaElement"
                        }
                    }
                }
            }, {
                "method": "nanoResultsShown",
                "name": "nanoResultsShown",
                "bubbles": false,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when results and all filters are shown and have loaded."
                },
                "complexType": {
                    "original": "{\n    meta: IndexResult;\n    client: { apiKey: string; appId: string };\n  }",
                    "resolved": "{ meta: IndexResult; client: { apiKey: string; appId: string; }; }",
                    "references": {
                        "IndexResult": {
                            "location": "import",
                            "path": "./algolia-interface",
                            "id": "src/components/algolia/algolia-interface.ts::IndexResult"
                        }
                    }
                }
            }, {
                "method": "nanoBeforeQuery",
                "name": "nanoBeforeQuery",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted before an algolia search."
                },
                "complexType": {
                    "original": "IndexResult",
                    "resolved": "IndexResult",
                    "references": {
                        "IndexResult": {
                            "location": "import",
                            "path": "./algolia-interface",
                            "id": "src/components/algolia/algolia-interface.ts::IndexResult"
                        }
                    }
                }
            }, {
                "method": "nanoAfterQuery",
                "name": "nanoAfterQuery",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted after an algolia search."
                },
                "complexType": {
                    "original": "IndexResult",
                    "resolved": "IndexResult",
                    "references": {
                        "IndexResult": {
                            "location": "import",
                            "path": "./algolia-interface",
                            "id": "src/components/algolia/algolia-interface.ts::IndexResult"
                        }
                    }
                }
            }, {
                "method": "nanoNewResults",
                "name": "nanoNewResults",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted after an results have been updated"
                },
                "complexType": {
                    "original": "IndexResult",
                    "resolved": "IndexResult",
                    "references": {
                        "IndexResult": {
                            "location": "import",
                            "path": "./algolia-interface",
                            "id": "src/components/algolia/algolia-interface.ts::IndexResult"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "removeFilters": {
                "complexType": {
                    "signature": "(facetName?: string, facetValue?: string) => Promise<void>",
                    "parameters": [{
                            "name": "facetName",
                            "type": "string",
                            "docs": "- will clear all filter selections of that type"
                        }, {
                            "name": "facetValue",
                            "type": "string",
                            "docs": "- will remove a single filter selection\nRemove facet filters (as set from nano-algolia-filter elements).\nThe omission or both will remove all facet filters"
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": [{
                            "name": "param",
                            "text": "facetName - will clear all filter selections of that type"
                        }, {
                            "name": "param",
                            "text": "facetValue - will remove a single filter selection\nRemove facet filters (as set from nano-algolia-filter elements).\nThe omission or both will remove all facet filters"
                        }]
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "listenTo",
                "methodName": "handleListenToChange"
            }, {
                "propName": "_dynFacetFilters",
                "methodName": "dynFacetFiltersChange"
            }, {
                "propName": "browseIndex",
                "methodName": "browseIndexChange"
            }, {
                "propName": "inputField",
                "methodName": "inputFieldSet"
            }, {
                "propName": "query",
                "methodName": "queryChange"
            }, {
                "propName": "replicaIndex",
                "methodName": "internalIndexSwitch"
            }, {
                "propName": "resultsPage",
                "methodName": "pageChange"
            }, {
                "propName": "searchIndexName",
                "methodName": "searchIndexNameChange"
            }, {
                "propName": "apiKey",
                "methodName": "initAlgoliaClient"
            }, {
                "propName": "appId",
                "methodName": "initAlgoliaClient"
            }, {
                "propName": "searchIndex",
                "methodName": "initAlgoliaIndex"
            }, {
                "propName": "showResults",
                "methodName": "showResultsChange"
            }, {
                "propName": "filters",
                "methodName": "handleFilterpropChange"
            }];
    }
    static get listeners() {
        return [{
                "name": "nanoTplUpdated",
                "method": "onAllTplUpdate",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "nanoPageChanged",
                "method": "onPageChange",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "nanoFilterChanged",
                "method": "onFilterChange",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "nanoChange",
                "method": "handleInputChange",
                "target": "body",
                "capture": false,
                "passive": false
            }, {
                "name": "change",
                "method": "handleInputChange",
                "target": "body",
                "capture": false,
                "passive": false
            }];
    }
}
