import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { always, touchOnly } from "ol/events/condition";
import { Layer } from "mobility-toolbox-js/ol";
import { unByKey } from "ol/Observable";
import OLMap from "ol/Map";
import BasicMap from "react-spatial/components/BasicMap";
import { MouseWheelZoom } from "ol/interaction";
import MapAccessibility from "../MapAccessibility";
import { setResolution, setCenter, setZoom, setZoomType } from "../../model/map/actions";
import { setFeatureInfo, setSearchOpen, updateDrawEditLink } from "../../model/app/actions";
import Copyright from "../Copyright/Copyright";
import NoDragPanWarning from "../NoDragPanWarning";
import NoMouseWheelWarning from "../NoMouseWheelWarning";
import getFeatureInfoAtCoordinate from "../../utils/getFeatureInfoAtCoordinate";
import getQueryableLayers from "../../utils/getQueryableLayers";
import { trackEvent } from "../../utils/trackingUtils";
const propTypes = {
  dispatchHtmlEvent: PropTypes.func,
  // mapStateToProps
  center: PropTypes.arrayOf(PropTypes.number),
  extent: PropTypes.arrayOf(PropTypes.number),
  maxExtent: PropTypes.arrayOf(PropTypes.number),
  layers: PropTypes.arrayOf(PropTypes.instanceOf(Layer)),
  map: PropTypes.instanceOf(OLMap).isRequired,
  activeTopic: PropTypes.shape().isRequired,
  resolution: PropTypes.number,
  zoom: PropTypes.number,
  showPopups: PropTypes.bool,
  maxZoom: PropTypes.number,
  minZoom: PropTypes.number,
  zoomType: PropTypes.string,
  // mapDispatchToProps
  dispatchSetCenter: PropTypes.func.isRequired,
  dispatchSetResolution: PropTypes.func.isRequired,
  dispatchSetZoom: PropTypes.func.isRequired,
  dispatchSetFeatureInfo: PropTypes.func.isRequired,
  dispatchSetSearchOpen: PropTypes.func.isRequired,
  dispatchUpdateDrawEditlink: PropTypes.func.isRequired,
  dispatchSetZoomType: PropTypes.func.isRequired,
  t: PropTypes.func.isRequired
};
const defaultProps = {
  // mapStateToProps
  center: [925472, 5920000],
  layers: [],
  extent: undefined,
  maxExtent: undefined,
  resolution: undefined,
  zoom: 9,
  maxZoom: 20,
  minZoom: 2,
  dispatchHtmlEvent: () => {},
  showPopups: true
};
class Map extends PureComponent {
  componentDidMount() {
    const {
      map,
      dispatchHtmlEvent,
      dispatchSetZoomType
    } = this.props;
    this.onPointerMoveRef = map.on("pointermove", e => this.onPointerMove(e));
    this.onSingleClickRef = map.on("singleclick", e => this.onSingleClick(e));
    dispatchHtmlEvent(new CustomEvent("load"));
    map === null || map === void 0 || map.updateSize();
    const mapInteractions = map.getInteractions();
    mapInteractions.insertAt(0, new MouseWheelZoom({
      condition: evt => {
        if (evt.type === "wheel") {
          dispatchSetZoomType("scroll");
        }
        return always(evt);
      }
    }));
  }
  componentDidUpdate() {
    const {
      map
    } = this.props;
    // VIP: Without the map stays white.
    map === null || map === void 0 || map.updateSize();
  }
  componentWillUnmount() {
    unByKey([this.onPointerMoveRef, this.onSingleClickRef]);
  }
  onMapMoved(evt) {
    const {
      center,
      resolution,
      dispatchSetCenter,
      dispatchSetResolution,
      dispatchSetZoom,
      zoom,
      zoomType,
      dispatchHtmlEvent,
      dispatchUpdateDrawEditlink,
      dispatchSetZoomType,
      activeTopic,
      t
    } = this.props;
    const newResolution = evt.map.getView().getResolution();
    const newZoom = evt.map.getView().getZoom();
    const newCenter = evt.map.getView().getCenter();
    if (zoom !== newZoom) {
      dispatchSetZoom(newZoom);
      dispatchUpdateDrawEditlink();
      if (zoomType) {
        const isZoomingIn = zoom < newZoom;
        let label = isZoomingIn ? t("Hineinzoomen") : t("Rauszoomen");
        if (zoomType === "slider") label = undefined;
        trackEvent({
          eventType: "action",
          componentName: zoomType,
          label,
          location: t(activeTopic === null || activeTopic === void 0 ? void 0 : activeTopic.name, {
            lng: "de"
          }),
          variant: isZoomingIn ? "ZoomIn" : "ZoomOut"
        }, activeTopic);
        dispatchSetZoomType(null);
      }
    }
    if (resolution !== newResolution) {
      dispatchSetResolution(newResolution);
      dispatchUpdateDrawEditlink();
    }
    if (center[0] !== newCenter[0] || center[1] !== newCenter[1]) {
      dispatchSetCenter(newCenter);
      dispatchUpdateDrawEditlink();
    }

    // Propagate the ol event to the WebComponent
    const htmlEvent = new CustomEvent(evt.type, {
      detail: evt
    });
    dispatchHtmlEvent(htmlEvent);
  }
  onPointerMove(evt) {
    var _activeTopic$elements;
    const {
      map,
      coordinate
    } = evt;
    const {
      layers,
      showPopups,
      activeTopic
    } = this.props;
    if (document.activeElement !== map.getTargetElement()) {
      map.getTargetElement().focus();
    }
    if (touchOnly(evt) || !showPopups || !(activeTopic !== null && activeTopic !== void 0 && (_activeTopic$elements = activeTopic.elements) !== null && _activeTopic$elements !== void 0 && _activeTopic$elements.popup) && !activeTopic.enableFeatureClick || map.getView().getInteracting() || map.getView().getAnimating()) {
      return;
    }
    const queryableLayers = getQueryableLayers("pointermove", layers, map);
    getFeatureInfoAtCoordinate(coordinate, queryableLayers, "pointermove").then(newInfos => {
      // If the featureInfos contains one from a priority layer.
      // We display only these featureInfos.
      // See DirektVerbindungen layers for an example.
      const priorityLayersInfos = newInfos.filter(_ref => {
        let {
          layer
        } = _ref;
        return layer.get("priorityFeatureInfo");
      });
      const hasPriorityLayer = !!priorityLayersInfos.length;
      const otherLayersInfos = newInfos.filter(_ref2 => {
        let {
          layer
        } = _ref2;
        return !layer.get("priorityFeatureInfo");
      });
      const infos = hasPriorityLayer ? priorityLayersInfos : otherLayersInfos;

      // Show the hover style if the layer has the method.
      infos.forEach(_ref3 => {
        let {
          layer,
          features
        } = _ref3;
        if (!layer.get("priorityFeatureInfo")) {
          var _layer$hover;
          layer === null || layer === void 0 || (_layer$hover = layer.hover) === null || _layer$hover === void 0 || _layer$hover.call(layer, features);
        }
      });
      map.getTarget().style.cursor = infos.find(_ref4 => {
        let {
          features
        } = _ref4;
        return !!features.length;
      }) ? "pointer" : "auto";
    });
  }
  onSingleClick(evt) {
    var _activeTopic$elements2;
    const {
      coordinate,
      map
    } = evt;
    const {
      dispatchSetFeatureInfo,
      dispatchSetSearchOpen,
      dispatchHtmlEvent,
      activeTopic,
      showPopups,
      layers
    } = this.props;

    // If there is no popup to display just ignore the click event.
    if (!showPopups || !(activeTopic !== null && activeTopic !== void 0 && (_activeTopic$elements2 = activeTopic.elements) !== null && _activeTopic$elements2 !== void 0 && _activeTopic$elements2.popup) && !activeTopic.enableFeatureClick) {
      return;
    }
    const queryableLayers = getQueryableLayers("singleclick", layers, map);
    getFeatureInfoAtCoordinate(coordinate, queryableLayers, "singleclick").then(featureInfos => {
      // If the featureInfos contains one from a priority layer.
      // We display only these featureInfos.
      // See DirektVerbindungen layers for an example.
      const priorityLayersInfos = featureInfos.filter(_ref5 => {
        let {
          features,
          layer
        } = _ref5;
        return features.length && layer.get("priorityFeatureInfo");
      });
      const hasPriorityLayer = !!priorityLayersInfos.length;
      const otherLayersInfos = featureInfos.filter(_ref6 => {
        let {
          features,
          layer
        } = _ref6;
        return features.length && !layer.get("priorityFeatureInfo");
      });

      // Display only info of layers with a popup defined.
      const infos = (hasPriorityLayer ? priorityLayersInfos : otherLayersInfos).reverse().filter(_ref7 => {
        let {
          layer
        } = _ref7;
        return layer.get("popupComponent") || activeTopic.enableFeatureClick;
      });

      // Dispatch only infos with features found.
      dispatchSetFeatureInfo(infos);

      // Propagate the infos clicked to the WebComponent
      dispatchHtmlEvent(new CustomEvent("getfeatureinfo", {
        detail: infos
      }));
    });

    // Propagate the ol event to the WebComponent
    const htmlEvent = new CustomEvent(evt.type, {
      detail: evt
    });
    dispatchHtmlEvent(htmlEvent);
    dispatchSetSearchOpen(false);
  }
  render() {
    const {
      center,
      zoom,
      maxZoom,
      minZoom,
      layers,
      map,
      resolution,
      maxExtent,
      extent,
      t,
      activeTopic
    } = this.props;
    return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(BasicMap, {
      center: center,
      resolution: resolution,
      extent: extent,
      layers: layers,
      zoom: zoom,
      map: map,
      ariaLabel: t("Karte"),
      onMapMoved: evt => this.onMapMoved(evt),
      viewOptions: {
        maxZoom,
        minZoom,
        extent: maxExtent,
        constrainOnlyCenter: activeTopic.constrainOnlyCenter
      },
      tabIndex: 0
    }), /*#__PURE__*/React.createElement(MapAccessibility, {
      layers: layers,
      map: map
    }), /*#__PURE__*/React.createElement(Copyright, null), /*#__PURE__*/React.createElement(NoDragPanWarning, null), /*#__PURE__*/React.createElement(NoMouseWheelWarning, null));
  }
}
Map.propTypes = propTypes;
Map.defaultProps = defaultProps;
const mapStateToProps = state => ({
  layers: state.map.layers,
  center: state.map.center,
  extent: state.map.extent,
  resolution: state.map.resolution,
  zoom: state.map.zoom,
  maxExtent: state.map.maxExtent,
  maxZoom: state.map.maxZoom,
  minZoom: state.map.minZoom,
  showPopups: state.app.showPopups,
  activeTopic: state.app.activeTopic,
  zoomType: state.map.zoomType,
  t: state.app.t
});
const mapDispatchToProps = {
  dispatchSetCenter: setCenter,
  dispatchSetResolution: setResolution,
  dispatchSetZoom: setZoom,
  dispatchSetFeatureInfo: setFeatureInfo,
  dispatchSetSearchOpen: setSearchOpen,
  dispatchUpdateDrawEditlink: updateDrawEditLink,
  dispatchSetZoomType: setZoomType
};
export default connect(mapStateToProps, mapDispatchToProps)(Map);
//# sourceMappingURL=Map.js.map