import { SearchOptions, SearchQuery, InputSearchQuery, SearchResult } from '@nosto/nosto-js/client';
import * as _nosto_search_js from '@nosto/search-js';
import { HitDecorator, SearchOptions as SearchOptions$1 } from '@nosto/search-js';
export { priceDecorator } from '@nosto/search-js/currencies';

type AutocompleteInstance = {
    /**
     * Open the dropdown.
     */
    open(): void;
    /**
     * Close the dropdown.
     */
    close(): void;
    /**
     * Destroy the autocomplete instance.
     */
    destroy(): void;
};
type SearchAutocompleteOptions = Pick<SearchOptions, "isKeyword" | "redirect">;
/**
 * @param config Autocomplete configuration.
 * @returns Autocomplete instance.
 * @group Autocomplete
 * @category Core
 * @example
 * ```js
 * import { autocomplete } from '@nosto/autocomplete';
 *
 * // Basic usage
 * autocomplete({
 *   inputSelector: '#search',
 *   dropdownSelector: '#dropdown',
 *   render: (container, state) => {
 *     container.innerHTML = `
 *        <div>
 *         <h1>${state.query}</h1>
 *        <ul>
 *        ${state.response.products
 *          .map((product) => `<li>${product.name}</li>`)
 *          .join('')}
 *       </ul>
 *     </div>
 *    `;
 *   },
 *   fetch: {
 *     products: {
 *       fields: ['name', 'url', 'imageUrl', 'price', 'listPrice', 'brand'],
 *       size: 5
 *     },
 *     keywords: {
 *       size: 5,
 *       fields: ['keyword', '_highlight.keyword'],
 *       highlight: {
 *         preTag: `<strong>`,
 *         postTag: '</strong>'
 *       }
 *     }
 *   }
 * });
 *
 * // Liquid template.
 * import { autocomplete, fromRemoteLiquidTemplate, fromLiquidTemplate, defaultLiquidTemplate } from '@nosto/autocomplete/liquid';
 *
 * autocomplete({
 *   inputSelector: '#search',
 *   dropdownSelector: '#dropdown',
 *   render: fromRemoteLiquidTemplate('autocomplete.liquid'),
 *   // Or:
 *   render: window.nostoAutocomplete.fromLiquidTemplate(defaultLiquidTemplate),
 *   ...
 * });
 *
 * // Mustache template.
 * import { autocomplete, fromRemoteMustacheTemplate, fromMustacheTemplate, defaultMustacheTemplate } from '@nosto/autocomplete/mustache';
 *
 * autocomplete({
 *   inputSelector: '#search',
 *   dropdownSelector: '#dropdown',
 *   render: fromRemoteMustacheTemplate('autocomplete.mustache'),
 *   // Or:
 *   render: fromMustacheTemplate(defaultMustacheTemplate),
 *   ...
 * });
 *
 * // React example.
 * import { autocomplete, Autocomplete } from '@nosto/autocomplete/react';
 * import ReactDOM from 'react-dom';
 *
 * let reactRoot;
 *
 * autocomplete({
 *   inputSelector: '#search',
 *   dropdownSelector: '#dropdown',
 *   render: function (container, state) {
 *     if (!reactRoot) {
 *       reactRoot = ReactDOM.createRoot(container);
 *     }
 *     reactRoot.render(<Autocomplete {...state} />);
 *   },
 *   ...
 * });
 * ```
 */
declare function autocomplete$1<State = DefaultState>(config: AutocompleteConfig<State>): AutocompleteInstance;

/**
 * @group Autocomplete
 * @category Core
 */
interface GoogleAnalyticsConfig {
    /**
     * Path of search page
     * @default "/search"
     */
    serpPath?: string;
    /**
     * Search query url parameter name
     * @default "query"
     */
    queryParamName?: string;
    /**
     * Enable Google Analytics
     * @default true
     */
    enabled?: boolean;
}
type Selector = string | Element;
/**
 * @group Autocomplete
 * @category Core
 */
interface AutocompleteConfig<State> {
    /**
     * The input element to attach the autocomplete to
     */
    inputSelector: Selector;
    /**
     * The dropdown element to attach the autocomplete to
     */
    dropdownSelector: Selector | ((input: HTMLInputElement) => Selector);
    /**
     * The function to use to render the dropdown
     */
    render: (container: HTMLElement, state: State) => void | PromiseLike<void>;
    /**
     * Minimum length of the query before searching
     */
    minQueryLength?: number;
    /**
     * The function to use to fetch the search state
     */
    fetch: SearchQuery | ((input: string) => PromiseLike<State>);
    /**
     * The function to use to submit the search
     */
    submit?: (query: string, config: AutocompleteConfig<State>, options?: SearchAutocompleteOptions) => void;
    /**
     * Enable history
     */
    historyEnabled?: boolean;
    /**
     * Max number of history items to show
     */
    historySize?: number;
    /**
     * Enable Nosto Analytics
     */
    nostoAnalytics?: boolean;
    /**
     * Google Analytics configuration. Set to `false` to disable.
     */
    googleAnalytics?: GoogleAnalyticsConfig | boolean;
    /**
     * Decorate each search hit before rendering
     *
     * @example
     * ```ts
     * import { priceDecorator } from "@nosto/autocomplete"
     *
     * autocomplete({
     *   hitDecorators: [
     *     priceDecorator({ defaultCurrency: "USD" })
     *   ]
     * })
     * ```
     */
    hitDecorators?: HitDecorator[];
    /**
     * Whether to submit the form natively or not
     */
    nativeSubmit?: boolean;
    /**
     * A function to call when the user clicks on a search hit to use custom routing
     * @example
     * ```ts
     * autocomplete({
     *  routingHandler: (url) => {
     *    location.href = url
     *  }
     * })
     * ```
     */
    routingHandler?: (url: string) => void;
}

/**
 * @group Autocomplete
 * @category Core
 */
interface DefaultState {
    /**
     * The current search query object.
     */
    query?: InputSearchQuery;
    /**
     * The current search response.
     */
    response?: SearchResult;
    /**
     * The history items.
     */
    history?: {
        item: string;
    }[];
}

var autocomplete = "{% assign hasKeywords = response.keywords.hits.length > 0 %}\n{% assign hasProducts = response.products.hits.length > 0 %}\n{% assign hasHistory = history.length > 0 %}\n{% assign imagePlaceHolder = 'https://cdn.nosto.com/nosto/9/mock' %}\n\n<div class=\"ns-autocomplete-results\">\n  {% if hasKeywords == false and hasProducts == false and hasHistory %}\n    <div class=\"ns-autocomplete-history\">\n      <div class=\"ns-autocomplete-header\">\n        Recently searched\n      </div>\n      {% for hit in history %}\n        <div class=\"ns-autocomplete-history-item\" data-ns-hit=\"{{ hit | json | escape }}\" data-testid=\"history\">\n          {{ hit.item }}\n          <a\n            href=\"#\"\n            class=\"ns-autocomplete-history-item-remove\"\n            data-ns-remove-history=\"{{hit.item}}\">\n            &#x2715;\n          </a>\n        </div>\n      {% endfor %}\n    </div>\n    <div class=\"ns-autocomplete-history-clear\">\n      <button\n        type=\"button\"\n        class=\"ns-autocomplete-button\"\n        data-ns-remove-history=\"all\">\n        Clear history\n      </button>\n    </div>\n  {% elsif hasKeywords or hasProducts %}\n    {% if hasKeywords %}\n      <div class=\"ns-autocomplete-keywords\">\n        <div class=\"ns-autocomplete-header\">\n          Keywords\n        </div>\n        {% for hit in response.keywords.hits %}\n          <div class=\"ns-autocomplete-keyword\" data-ns-hit=\"{{ hit | json | escape }}\" data-testid=\"keyword\">\n            {% if hit._highlight and hit._highlight.keyword %}\n              <span>{{ hit._highlight.keyword }}</span>\n            {% else %}\n              <span>{{ hit.keyword }}</span>\n            {% endif %}\n          </div>\n        {% endfor %}\n      </div>\n    {% endif %}\n    {% if hasProducts %}\n      <div class=\"ns-autocomplete-products\">\n        <div class=\"ns-autocomplete-header\">\n          Products\n        </div>\n        {% for hit in response.products.hits %}\n          <a\n            class=\"ns-autocomplete-product\"\n            href=\"{{ hit.url }}\"\n            data-ns-hit=\"{{ hit | json | escape }}\"\n            data-testid=\"product\">\n            <img\n              class=\"ns-autocomplete-product-image\"\n              src=\"{% if hit.imageUrl %}{{ hit.imageUrl }}{% else %}{{ imagePlaceHolder }}{% endif %}\"\n              alt=\"{{ hit.name }}\"\n              width=\"60\"\n              height=\"40\" />\n            <div class=\"ns-autocomplete-product-info\">\n              {% if hit.brand %}\n                <div class=\"ns-autocomplete-product-brand\">\n                  {{ hit.brand }}\n                </div>\n              {% endif %}\n              <div class=\"ns-autocomplete-product-name\">\n                {{ hit.name }}\n              </div>\n              <div>\n                <span>\n                  {{ hit.price }}&euro;\n                </span>\n                {% if hit.listPrice and hit.listPrice != hit.price %}\n                    <span class=\"ns-autocomplete-product-list-price\">\n                        {{ hit.listPrice }}\n                        &euro;\n                    </span>\n                {% endif %}\n              </div>\n            </div>\n          </a>\n        {% endfor %}\n      </div>\n    {% endif %}\n    <div class=\"ns-autocomplete-submit\">\n      <button type=\"submit\" class=\"ns-autocomplete-button\">\n        See all search results\n      </button>\n    </div>\n  {% endif %}\n</div>\n";

/**
 * Render a liquid template into a container
 *
 * @param template Liquid template
 * @returns Render function
 * @group Autocomplete
 * @category Liquid
 * @example
 * ```js
 * import { fromLiquidTemplate } from "@nosto/autocomplete/liquid";
 *
 * const render = fromLiquidTemplate(`
 *   <div>
 *      <h1>{{title}}</h1>
 *    <ul>
 *    {% for product in products %}
 *     <li>{{product.name}}</li>
 *  {% endfor %}
 *  </ul>
 *  </div>
 *  `);
 *
 * render(document.getElementById("container"), {
 *   title: "My Title",
 *   products: [
 *     { name: "Product 1" },
 *     { name: "Product 2" },
 *     { name: "Product 3" }
 *   ]
 * });

 * ```
 */
declare function fromLiquidTemplate<State extends object = DefaultState>(template: string): (container: HTMLElement, state: State) => PromiseLike<void>;

/**
 *
 * @param query Query object.
 * @param options Options object.
 * @returns Promise of search response.
 * @group Autocomplete
 * @category Core
 * @example
 * ```js
 * import { search } from "@nosto/autocomplete"
 *
 * search({
 *     query: "shoes",
 *     products: {
 *       fields: ["name", "price"],
 *       facets: ["brand", "category"],
 *       size: 10,
 *       from: 0,
 *     }
 * }).then((state) => {
 *    console.log(state.response)
 * })
 * ```
 */
declare function search(query: SearchQuery, options?: SearchOptions$1): Promise<{
    query: SearchQuery;
    response: _nosto_search_js.DecoratedResult<readonly _nosto_search_js.HitDecorator[]>;
}>;

/**
 * Nosto Autocomplete Web Component using Liquid templates.
 *
 * This component integrates the Nosto Autocomplete functionality with Liquid templating.
 * It fetches the configuration from a script tag, compiles the Liquid template,
 * and initializes the autocomplete with the compiled template as the render function.
 * If a custom template isn't passed, the component will use the default Liquid template.
 *
 * @example
 * ```html
 * <nosto-autocomplete>
 *   <form>
 *     <input type="text" id="input" />
 *   </form>
 *     <div id="results"></div>
 *   <script autocomplete-config type="application/json">
 *     {
 *       "inputSelector": "#input",
 *       "dropdownSelector": "#results",
 *       "fetch": {
 *         "products": {
 *           "fields": ["name", "url", "imageUrl", "price", "listPrice", "brand"],
 *           "size": 5
 *         },
 *         "keywords": {
 *           "size": 5,
 *           "fields": ["keyword", "_highlight.keyword"]
 *         }
 *       }
 *     }
 *   </script>
 *   <script type="text/x-liquid" autocomplete-template>
 *     <h1>{{ query }}</h1>
 *     <ul>
 *       {% for product in products %}
 *         <li>{{ product.name }}</li>
 *       {% endfor %}
 *     </ul>
 *   </script>
 * </nosto-autocomplete>
 * ```
 */
declare class NostoAutocomplete extends HTMLElement {
    connectedCallback(): Promise<AutocompleteInstance>;
}

export { NostoAutocomplete, autocomplete$1 as autocomplete, autocomplete as defaultLiquidTemplate, fromLiquidTemplate, search };
export type { AutocompleteConfig, AutocompleteInstance, DefaultState, GoogleAnalyticsConfig };
