import async from "async";
import _ from "lodash";

export default {
  name: "search",

  getReducer() {
    const initialData = {
      shouldFireSearch: false,
      q: "",
      selected: null,
      onFireSearchListeners: [],
      results: [],
    };

    return (state = initialData, { type, payload }) => {
      if (type.indexOf("SEARCH_") !== -1) {
        return Object.assign({}, state, payload);
      }
      return state;
    };
  },

  doSearchAddCollection:
    (options) =>
    ({ dispatch, store }) => {
      const listeners = store.selectSearchOnFireSearchListeners();
      if (options.onFireSearch) listeners.push(options.onFireSearch);
      dispatch({
        type: "SEARCH_COLLECTION_ADDED",
        payload: {
          onFireSearchListeners: listeners,
        },
      });
    },

  doSearchShouldFire:
    () =>
    ({ dispatch }) => {
      dispatch({ type: "SEARCH_SHOULD_FIRE", payload: { shouldFire: true } });
    },

  doSearchSetQuery:
    (q) =>
    ({ dispatch, store }) => {
      dispatch({ type: "SEARCH_SET_QUERY", payload: { q: q, results: [] } });
    },

  doSearchSelectItem:
    (item) =>
    ({ dispatch }) => {
      dispatch({ type: "SEARCH_ITEM_SELECTED", payload: { selected: item } });
    },

  doSearchFire:
    () =>
    ({ dispatch, store }) => {
      dispatch({ type: "SEARCH_START", payload: { shouldFire: false } });
      const listeners = store.selectSearchOnFireSearchListeners();
      
      async.parallel(listeners, (err, r) => {
        if (err)
          return dispatch({
            type: "SEARCH_ERROR",
            payload: { err: err, results: [] },
          });
        const results = _.flatten(r);

        const sortedResultsGeo = [];
        const sortedResultsWMS = [];
        results.forEach((result) => {
          if (result.provider !== "geocoder") {
            sortedResultsWMS.push(result);
          }
          if (result.provider === "geocoder") {
            sortedResultsGeo.push(result);
          }
        });

        const sortedResults = [...sortedResultsWMS, ...sortedResultsGeo];

        dispatch({
          type: "SEARCH_SUCCESS",
          payload: { results: sortedResults },
        });
      });
    },

  selectSearchOnFireSearchListeners: (state) => {
    return state.search.onFireSearchListeners;
  },

  selectSearchQueryString: (state) => {
    return state.search.q;
  },

  selectSearchResults: (state) => {
    return state.search.results;
  },

  reactSearchShouldFire: (state) => {
    if (state.search.shouldFire) return { actionCreator: "doSearchFire" };
  },
};

// =>  add collection, should have a name and implement the following api:

// .onFireSearch = function(callback(err, results)) => return results as an array
// each bundle contributing to search can listen for the following action types:
// 'SEARCH_SET_QUERY' => fired when user types into search bar
// 'SEARCH_ITEM_SELECTED' => fired when user selects a search result

// each result should fit the following schema, but can be extended by adding additional keys

// {
//   type: 'Feature',  // geojson feature
//   provider: <string>, // optional provider of information, makes it easy to distinguish
//   displayName: <string>,
//   iconClass: <string>,
//   geometry: <object>, // geojson geometry
//   properties: <object> // geojson properties
// }
