import { useCallback, useEffect } from 'react';
import { useDebounce } from 'react-use';

import { backendSrv } from 'app/core/services/backend_srv';
import { SearchSrv } from 'app/core/services/search_srv';

import { FETCH_RESULTS, FETCH_ITEMS, TOGGLE_SECTION, SEARCH_START, FETCH_ITEMS_START } from '../reducers/actionTypes';
import { DashboardSection, UseSearch } from '../types';
import { hasId, getParsedQuery } from '../utils';

const searchSrv = new SearchSrv();

/**
 * Base hook for search functionality.
 * Returns state and dispatch, among others, from 'reducer' param, so it can be
 * further extended.
 * @param query
 * @param reducer - return result of useReducer
 * @param params - custom params
 */
export const useSearch: UseSearch = (query, reducer, params = {}) => {
  const { queryParsing } = params;
  const [state, dispatch] = reducer;

  const search = () => {
    dispatch({ type: SEARCH_START });
    const parsedQuery = getParsedQuery(query, queryParsing);
    searchSrv.search(parsedQuery).then((results) => {
      dispatch({ type: FETCH_RESULTS, payload: results });
    });
  };

  // Set loading state before debounced search
  useEffect(() => {
    dispatch({ type: SEARCH_START });
  }, [query.tag, query.sort, query.starred, query.layout, dispatch]);

  useDebounce(search, 300, [query, queryParsing]);

  const onToggleSection = useCallback(
    (section: DashboardSection) => {
      if (hasId(section.title) && !section.items.length) {
        dispatch({ type: FETCH_ITEMS_START, payload: section.id });
        backendSrv.search({ folderIds: [section.id] }).then((items) => {
          dispatch({ type: FETCH_ITEMS, payload: { section, items } });
          dispatch({ type: TOGGLE_SECTION, payload: section });
        });
      } else {
        dispatch({ type: TOGGLE_SECTION, payload: section });
      }
    },
    [dispatch]
  );

  return { state, dispatch, onToggleSection };
};
