/* global IITC -- eslint */

/**
 * Provides functionality for the search system within the application.
 *
 * You can implement your own result provider by listening to the search hook:
 * ```window.addHook('search', function(query) {});```.
 *
 * @example
 * // Adding a search result
 * window.addHook('search', function(query) {
 *   query.addResult({
 *     title: 'My Result',
 *     position: L.latLng(0, 0)
 *   });
 * });
 *
 *  @namespace IITC.search
 *  @memberof IITC
 */

/**
 * @memberOf IITC.search
 * @typedef {Object} SearchQuery
 * @property {string} term - The term for which the user has searched.
 * @property {boolean} confirmed - Indicates if the user has pressed enter after searching.
 *           You should not search online or do heavy processing unless the user has confirmed the search term.
 * @property {IITC.search.Query.addResult} addResult - Method to add a result to the query.
 * @property {IITC.search.Query.addPortalResult} addPortalResult - Method to add a portal to the query.
 */

IITC.search = {
  lastSearch: null,
};

/**
 * Initiates a search with the specified term and confirmation status.
 *
 * @function IITC.search.doSearch
 * @param {string} term - The search term.
 * @param {boolean} confirmed - Indicates if the search term is confirmed.
 */
IITC.search.doSearch = function (term, confirmed) {
  const searchTerm = term.trim();
  const searchCancelButton = document.querySelector('#searchcancel');

  if (searchCancelButton) {
    searchCancelButton.classList.toggle('visible', searchTerm.length > 0);
  }

  // Minimum 3 characters for automatic search
  if (searchTerm.length < 3 && !confirmed) return;

  // Avoid clearing last confirmed search
  const lastSearch = IITC.search.lastSearch;
  if (lastSearch?.confirmed && !confirmed) return;

  // Prevent repeat of identical query
  if (lastSearch?.confirmed === confirmed && lastSearch.term === searchTerm) return;

  if (lastSearch) lastSearch.hide();
  IITC.search.lastSearch = null;

  if (searchTerm === '') return;

  if (window.useAppPanes()) window.show('info');

  document.querySelectorAll('.ui-tooltip').forEach((tooltip) => tooltip.remove());

  IITC.search.lastSearch = new IITC.search.Query(searchTerm, confirmed);
  IITC.search.lastSearch.show();
};

/**
 * Sets up the search input field and button functionality.
 *
 * @function IITC.search.setup
 */
IITC.search.setup = function () {
  const searchInput = document.querySelector('#search');
  const searchCancelButton = document.querySelector('#searchcancel');
  const geoLocationButton = document.querySelector('#buttongeolocation');
  let searchTimer;

  if (searchInput) {
    searchInput.addEventListener('keydown', (e) => {
      if (e.key !== 'Enter') return;
      e.preventDefault();

      const term = searchInput.value.trim();
      clearTimeout(searchTimer);
      IITC.search.doSearch(term, true);
    });

    searchInput.addEventListener('input', () => {
      clearTimeout(searchTimer);
      searchTimer = setTimeout(() => {
        const term = searchInput.value.trim();
        IITC.search.doSearch(term, false);
      }, 100);
    });
  }

  if (searchCancelButton) {
    searchCancelButton.classList.remove('visible');

    searchCancelButton.addEventListener('click', () => {
      if (searchInput) {
        searchInput.value = '';
        searchInput.focus();
        searchCancelButton.classList.remove('visible');

        // Clear the current search
        clearTimeout(searchTimer);
        IITC.search.doSearch('', true);
      }
    });
  }

  if (geoLocationButton) {
    geoLocationButton.addEventListener('click', () => {
      window.map.locate({ setView: true, maxZoom: 13 });
    });
  }
};

// Redirect all window.search access to IITC.search
Object.defineProperty(window, 'search', {
  get() {
    return IITC.search;
  },
  set(value) {
    IITC.search = value;
  },
  configurable: true,
});

/*
 * @deprecated - use query.addPortalResult
 */
window.search.addSearchResult = function (query, data, guid) {
  query.addPortalResult(data, guid);
};