import React from "react";
import ReactDOM from "react-dom";
import GeocoderOverlay from "./overlay";
import Overlay from "ol/Overlay";
import { transform } from "ol/proj";

const zoomScales = {
  region: 8,
  postcode: 11,
  district: 11,
  place: 12,
  locality: 12,
  neighborhood: 14,
  address: 19,
  poi: 19,
  "poi.landmark": 19,
};

export default {
  name: "geocoder",

  getReducer() {
    const initialData = {
      shouldRegister: true,
      shouldHandleSelect: false,
      selectedItem: null,
    };

    return (state = initialData, { type, payload }) => {
      switch (type) {
        case "SEARCH_ITEM_SELECTED":
          if (
            payload.selected.provider &&
            payload.selected.provider === "geocoder"
          ) {
            return Object.assign({}, state, {
              shouldHandleSelect: true,
              selectedItem: payload.selected,
            });
          } else {
            return state;
          }
        case "GEOCODER_REGISTERED":
        case "GEOCODER_HANDLED_SELECT":
        case "GEOCODER_OVERLAY_RENDERED":
        case "GEOCODER_OVERLAY_REMOVED":
          return Object.assign({}, state, payload);
        default:
          return state;
      }
    };
  },

  doGeocoderRegister:
    () =>
    ({ dispatch, store }) => {
      dispatch({
        type: "GEOCODER_REGISTERED",
        payload: { shouldRegister: false },
      });
      store.doSearchAddCollection({
        onFireSearch: store.doGeocoderFireSearch,
      });
    },

  doGeocoderHandleSelect:
    () =>
    ({ dispatch, store }) => {
      dispatch({
        type: "GEOCODER_HANDLED_SELECT",
        payload: { shouldHandleSelect: false },
      });
      const selectedItem = store.selectGeocoderLastSelected();
      const map = store.selectMap();

      if (selectedItem) {
        //generate overlay
        const el = document.createElement("div");
        const overlay = new Overlay({
          element: el,
          positioning: "bottom-center",
          offset: [0, -10],
        });
        const displayProjection = store.selectDisplayProjection();
        const overlayCenter = transform(
          selectedItem.center,
          displayProjection,
          "EPSG:3857"
        );

        //add overlay to map
        map.addOverlay(overlay);
        ReactDOM.render(
          <GeocoderOverlay
            overlay={overlay}
            item={selectedItem}
            map={map}
            onClear={store.doClearGeocoderOverlay}
          />,
          el
        );
        overlay.setPosition(overlayCenter);

        //set view to item center & zoom level.
        store.doSetView({
          center: selectedItem.center,
          zoom: selectedItem.zoom,
        });
      }
    },
  doClearGeocoderOverlay:
    (e, overlay) =>
    ({ store }) => {
      e.preventDefault();
      e.stopPropagation();

      const map = store.selectMap();
      overlay.setPosition(undefined);
      const el = overlay.getElement();
      el.parentNode.removeChild(el);
      map.removeOverlay(overlay);
    },

  doGeocoderFireSearch:
    (callback) =>
    ({ dispatch, store, apiGet }) => {
      // Yeah, this is a hack, don't @ me
      // assumes something sets window.LIMIT_GEOCODER_COUNTRIES to an array of country codes
      // from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
      // i.e. `var window.LIMIT_GEOCODER_COUNTRIES = ['us','as','mp','gu','pw','pr','vi','um'];`
      const countries = window.LIMIT_GEOCODER_COUNTRIES;
      let q = store.selectSearchQueryString();
      const mapProjection = store.selectMapProjection();
      const geoProjection = store.selectGeoProjection();
      let c = transform(store.selectViewCenter(), mapProjection, geoProjection); 
      let mapboxToken = store.selectDefaultConfig().mapboxToken;
      if (q.length < 2) return;
      q = encodeURIComponent(q);
      apiGet(
        `https://api.mapbox.com/geocoding/v5/mapbox.places/${q}.json?proximity=${c.toString()}${
          countries && countries.length ? `&country=${countries.join(",")}` : ""
        }&access_token=${mapboxToken}`,
        (err, response, body) => {
          if (err) return callback(err);

          const results = JSON.parse(body);

          return callback(
            null,
            results.features.map((r) => {
              let icon = "mdi mdi-map-marker";

              // maki stylesheet marked as deprecated.
              // if (r.properties.maki) icon = `maki maki-${r.properties.maki}`;

              const z = zoomScales[r.place_type[0]] || 11;
              return {
                provider: "geocoder",
                displayName: r.place_name,
                place_type: r.place_type,
                iconClass: icon,
                center: r.center,
                zoom: z,
                geometry: r.geometry,
                properties: r.properties,
              };
            })
          );
        }
      );
    },

  selectGeocoderLastSelected: (state) => {
    return state.geocoder.selectedItem;
  },

  reactGeocoderShouldHandleSelect: (state) => {
    if (state.geocoder.shouldHandleSelect)
      return { actionCreator: "doGeocoderHandleSelect" };
  },

  reactGeocoderShouldRegister: (state) => {
    if (state.geocoder.shouldRegister)
      return { actionCreator: "doGeocoderRegister" };
  },
};
