import {checkRendering} from '../../lib/utils.js';

const usage = `Usage:
var customSearchBox = connectSearchBox(function render(params, isFirstRendering) {
  // params = {
  //   query,
  //   onHistoryChange,
  //   search,
  //   instantSearchInstance,
  //   widgetParams,
  // }
});
search.addWidget(
  customSearchBox({
    [ queryHook ],
  })
);
Full documentation available at https://community.algolia.com/instantsearch.js/connectors/connectSearchBox.html
`;

/**
 * @typedef {Object} CustomSearchBoxWidgetOptions
 * @property {function(string, function(string))} [queryHook = undefined] A function that will be called every time
 * a new value for the query is set. The first parameter is the query and the second is a
 * function to actually trigger the search. The function takes the query as the parameter.
 *
 * This queryHook can be used to debounce the number of searches done from the searchBox.
 */

/**
 * @typedef {Object} SearchBoxRenderingOptions
 * @property {string} query The query from the last search.
 * @property {function(SearchParameters)} onHistoryChange Registers a callback when the browser history changes.
 * @property {function(string)} refine Sets a new query and searches.
 * @property {Object} widgetParams All original `CustomSearchBoxWidgetOptions` forwarded to the `renderFn`.
 */

/**
 * **SearchBox** connector provides the logic to build a widget that will let the user search for a query.
 *
 * The connector provides to the rendering: `refine()` to set the query. The behaviour of this function
 * may be impacted by the `queryHook` widget parameter.
 * @type {Connector}
 * @param {function(SearchBoxRenderingOptions, boolean)} renderFn Rendering function for the custom **SearchBox** widget.
 * @return {function(CustomSearchBoxWidgetOptions)} Re-usable widget factory for a custom **SearchBox** widget.
 * @example
 * // custom `renderFn` to render the custom SearchBox widget
 * function renderFn(SearchBoxRenderingOptions, isFirstRendering) {
 *   if (isFirstRendering) {
 *     SearchBoxRenderingOptions.widgetParams.inputNode.on('keyup', function() {
 *       SearchBoxRenderingOptions.refine($(this).val());
 *     });
 *     SearchBoxRenderingOptions.widgetParams.inputNode.val(SearchBoxRenderingOptions.query);
 *   }
 * }
 *
 * // connect `renderFn` to SearchBox logic
 * var customSearchBox = instantsearch.connectors.connectSearchBox(renderFn);
 *
 * // mount widget on the page
 * search.addWidget(
 *   customSearchBox({
 *     inputNode: $('input#custom-searchbox'),
 *   })
 * );
 */
export default function connectSearchBox(renderFn) {
  checkRendering(renderFn, usage);

  return (widgetParams = {}) => {
    const {queryHook} = widgetParams;

    return {
      init({helper, onHistoryChange, instantSearchInstance}) {
        this._refine = (() => {
          let previousQuery;

          const setQueryAndSearch = (q, doSearch = true) => {
            if (q !== helper.state.query) {
              previousQuery = helper.state.query;
              helper.setQuery(q);
            }
            if (doSearch && previousQuery !== undefined && previousQuery !== q) helper.search();
          };

          return queryHook ?
            q => queryHook(q, setQueryAndSearch) :
            setQueryAndSearch;
        })();

        this._onHistoryChange = onHistoryChange;

        renderFn({
          query: helper.state.query,
          onHistoryChange: this._onHistoryChange,
          refine: this._refine,
          widgetParams,
          instantSearchInstance,
        }, true);
      },

      render({helper, instantSearchInstance}) {
        renderFn({
          query: helper.state.query,
          onHistoryChange: this._onHistoryChange,
          refine: this._refine,
          widgetParams,
          instantSearchInstance,
        }, false);
      },
    };
  };
}

@@ -2064,25 +2064,154 @@
 tParams.
-inputNode
+containerNode.html('%3Cinput type=%22text%22 /%3E');%0A *     SearchBoxRenderingOptions.widgetParams.containerNode%0A *       .find('input')%0A *       
 .on('key
@@ -2226,24 +2226,26 @@
 ction() %7B%0A *
+  
        Searc
@@ -2286,24 +2286,26 @@
 ).val());%0A *
+  
      %7D);%0A * 
@@ -2347,25 +2347,63 @@
 tParams.
-inputNode
+containerNode%0A *       .find('input')%0A *       
 .val(Sea
@@ -2655,21 +2655,25 @@
 %0A *     
-input
+container
 Node: $(
@@ -2673,21 +2673,16 @@
 ode: $('
-input
 #custom-

fix example for live example