function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/* eslint-disable no-param-reassign */
import { LineString, MultiLineString } from "ol/geom";
import { unByKey } from "ol/Observable";
import { Feature } from "ol";
import MapboxStyleLayer from "../MapboxStyleLayer";
import getTrafimageFilter from "../../utils/getTrafimageFilter";
import { DV_KEY } from "../../utils/constants";
const DV_TRIPS_SOURCELAYER_ID = "ch.sbb.direktverbindungen_trips";
const DV_FILTER_REGEX = /^ipv_(.+)?(day|night|all)$/;
const DV_FILTER_UNSELECTED_REGEX = /^ipv_(day|night|all)$/;
/**
 * Layer for visualizing international train connections.
 *
 * @class
 * @param {Object} [options] Layer options.
 * @inheritdoc
 * @private
 */
class DirektverbindungenLayer extends MapboxStyleLayer {
  constructor() {
    let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    super(_objectSpread({
      queryRenderedLayersFilter: layer => {
        const clickRegex = new RegExp("^ipv_(call_)?((station||full)_)?".concat(this.getCurrentLayer()));
        return clickRegex.test(getTrafimageFilter(layer)) && !/(displace|edge_bg)/.test(layer.id) // Avoid detecting displace layer
        ;
      },
      styleLayersFilter: layer => DV_FILTER_UNSELECTED_REGEX.test(getTrafimageFilter(layer))
    }, options));
    this.allFeatures = [];
    this.syncTimeout = null;
  }
  onLoad() {
    var _this$allFeatures;
    super.onLoad();
    this.onChangeVisible();
    if (!((_this$allFeatures = this.allFeatures) !== null && _this$allFeatures !== void 0 && _this$allFeatures.length)) {
      this.fetchDvFeatures();
    }
    // We can only get the mapbox features from the view on load.
    // In order to assign the Cartaro features their corresponding
    // mapbox features for the full list view, we sync the features when
    // the view changes and add the mapbox feature to any ol feature
    // that still hasn't got one.
    this.viewChangeListener = this.map.on("moveend", () => {
      clearTimeout(this.syncTimeout);
      this.syncTimeout = setTimeout(() => {
        this.syncFeatures();
      }, 400);
    });
    const {
      mbMap
    } = this.mapboxLayer;
    if (!mbMap) {
      return;
    }
    mbMap.once("idle", () => this.syncFeatures());
  }
  getMapboxFeatures() {
    const {
      mbMap
    } = this.mapboxLayer;
    if (!mbMap) {
      return null;
    }
    const renderedMbFeatures = mbMap.querySourceFeatures(DV_KEY, {
      sourceLayer: DV_TRIPS_SOURCELAYER_ID,
      filter: ["==", "$type", "LineString"]
    });
    renderedMbFeatures.forEach(feat => {
      feat.source = DV_KEY;
      feat.sourceLayer = DV_TRIPS_SOURCELAYER_ID;
    });
    return renderedMbFeatures || [];
  }

  /**
   * Assigns mapbox features to Cartaro ol features using their ID
   * @returns {array<ol.Feature>} Array of ol features
   */
  syncFeatures() {
    var _this$allFeatures2;
    const mbFeatures = this.getMapboxFeatures();
    const cartaroFeatIsMissingMbFeat = ((_this$allFeatures2 = this.allFeatures) === null || _this$allFeatures2 === void 0 ? void 0 : _this$allFeatures2.length) && !this.allFeatures.every(feat => feat.get("mapboxFeature"));
    if (cartaroFeatIsMissingMbFeat && mbFeatures !== null && mbFeatures !== void 0 && mbFeatures.length) {
      this.allFeatures.forEach(feat => {
        const mbFeature = mbFeatures.find(mbFeat => {
          var _mbFeat$properties;
          return (mbFeat === null || mbFeat === void 0 || (_mbFeat$properties = mbFeat.properties) === null || _mbFeat$properties === void 0 ? void 0 : _mbFeat$properties.cartaro_id) === (feat === null || feat === void 0 ? void 0 : feat.get("cartaro_id"));
        });
        if (!feat.get("mapboxFeature")) {
          feat.set("mapboxFeature", mbFeature);
        }
      });
    }
    this.dispatchEvent({
      type: "sync:features",
      features: this.allFeatures,
      target: this
    });
    return this.allFeatures;
  }

  /**
   * Fetch features from Cartaro for the list view
   */
  async fetchDvFeatures() {
    try {
      var _this$mapboxLayer, _this$mapboxLayer2;
      if (!((_this$mapboxLayer = this.mapboxLayer) !== null && _this$mapboxLayer !== void 0 && _this$mapboxLayer.url) || !((_this$mapboxLayer2 = this.mapboxLayer) !== null && _this$mapboxLayer2 !== void 0 && _this$mapboxLayer2.apiKey)) {
        // eslint-disable-next-line no-console
        throw new Error("DirektVerbindungLayer: No url or apiKey defined.");
      }
      const response = await fetch("".concat(this.mapboxLayer.url, "/data/ch.sbb.direktverbindungen.public.json?key=").concat(this.mapboxLayer.apiKey));
      const data = await response.json();
      this.allFeatures = data["geops.direktverbindungen"].map(line => {
        return new Feature(_objectSpread(_objectSpread({}, line), {}, {
          geometry: new LineString([[line.bbox[0], line.bbox[1]], [line.bbox[2], line.bbox[3]]])
        }));
      });
      this.syncFeatures();
    } catch (err) {
      // eslint-disable-next-line no-console
      console.error(err);
    }
  }

  /**
   * @returns {array<mapbox.stylelayer>} Array of mapbox style layers
   */
  getDvLayers(regex) {
    const {
      mbMap
    } = this.mapboxLayer;
    if (!mbMap) {
      return null;
    }
    const style = mbMap.getStyle();
    return style === null || style === void 0 ? void 0 : style.layers.filter(stylelayer => {
      return (regex || DV_FILTER_REGEX).test(getTrafimageFilter(stylelayer));
    });
  }

  /**
   * Gets the current visible IPV layer
   * @returns {string} 'day', 'night' or 'all'
   */
  getCurrentLayer() {
    const nightLayer = this.get("nightLayer");
    const dayLayer = this.get("dayLayer");
    if (dayLayer !== null && dayLayer !== void 0 && dayLayer.get("visible") && nightLayer !== null && nightLayer !== void 0 && nightLayer.get("visible")) {
      this.visible = true;
      return "all";
    }
    if (dayLayer !== null && dayLayer !== void 0 && dayLayer.get("visible") || nightLayer !== null && nightLayer !== void 0 && nightLayer.get("visible")) {
      const visibleLayer = [dayLayer, nightLayer].find(layer => layer.get("visible"));
      this.visible = true;
      return visibleLayer.get("routeType");
    }
    this.visible = false;
    return null;
  }
  attachToMap(map) {
    var _this$map;
    super.attachToMap(map);
    this.fetchDvFeatures();
    this.singleClickKey = (_this$map = this.map) === null || _this$map === void 0 ? void 0 : _this$map.on("singleclick", evt => {
      this.getFeatureInfoAtCoordinate(evt.coordinate).then(_ref => {
        let {
          features
        } = _ref;
        if (this.visible) {
          this.highlightStation(features.find(feat => !!feat.get("direktverbindung_ids")));
        }
      });
    });
    this.onChangeVisibleKeys = [];
    const dvNight = this.get("nightLayer");
    const dvDay = this.get("dayLayer");
    const that = this;
    this.onDayNightChangeVisibleKeys = [dvNight, dvDay].map(layer => {
      return layer === null || layer === void 0 ? void 0 : layer.on("change:visible", evt => {
        that.onChangeVisible(evt.target);
      });
    });
  }
  detachFromMap() {
    super.detachFromMap();
    unByKey([this.viewChangeListener, this.singleClickKey, ...(this.onDayNightChangeVisibleKeys || [])]);
  }

  // Updates the IPV mapbox stylelayer visibility according
  // to the current visible WKP layer
  onChangeVisible() {
    var _this$mapboxLayer3, _this$mapboxLayer4, _this$getDvLayers;
    // WARNING: the getCurrentLayer set the visiblity of the layer.
    const currentLayer = this.getCurrentLayer();
    if (!((_this$mapboxLayer3 = this.mapboxLayer) !== null && _this$mapboxLayer3 !== void 0 && _this$mapboxLayer3.mbMap) || !((_this$mapboxLayer4 = this.mapboxLayer) !== null && _this$mapboxLayer4 !== void 0 && _this$mapboxLayer4.visible)) {
      return;
    }
    const {
      mbMap
    } = this.mapboxLayer;
    const filterRegex = new RegExp("^ipv_(".concat(currentLayer, ")$"));
    (_this$getDvLayers = this.getDvLayers()) === null || _this$getDvLayers === void 0 || _this$getDvLayers.forEach(stylelayer => {
      mbMap.setLayoutProperty(stylelayer.id, "visibility", filterRegex.test(getTrafimageFilter(stylelayer)) ? "visible" : "none");
    });
  }
  getLayerOriginalFilter(layerId, filterExpression) {
    var _mbMap$getFilter;
    const {
      mbMap
    } = this.mapboxLayer;
    if (!mbMap) {
      return null;
    }
    return mbMap === null || mbMap === void 0 || (_mbMap$getFilter = mbMap.getFilter(layerId)) === null || _mbMap$getFilter === void 0 ? void 0 : _mbMap$getFilter.filter(item => {
      return !(Array.isArray(item) && item[1].toString() === filterExpression.toString());
    });
  }

  /**
   * Updates visibility for stations, labels and select highlight mb layers
   * and applies the mb filter for the currently selected feature
   */
  highlightLine() {
    let features = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    const {
      mbMap
    } = this.mapboxLayer;
    if (!mbMap) {
      return;
    }
    const highlightLayerString = "(edge|station|full)_";
    const callLayersRegex = new RegExp("^ipv_call_(".concat(highlightLayerString, ")?").concat(this.getCurrentLayer(), "$"));
    const callLayers = this.getDvLayers(callLayersRegex);
    const highlightLayersRegex = new RegExp("^ipv_call_".concat(highlightLayerString).concat(this.getCurrentLayer(), "$"));
    // Highlight lines only
    const selectedLines = features.filter(feat => feat.getGeometry() instanceof MultiLineString || feat.getGeometry() instanceof LineString);
    callLayers.forEach(layer => {
      if (selectedLines.length > 0) {
        mbMap.setLayoutProperty(layer.id, "visibility", "visible");
        if (highlightLayersRegex.test(getTrafimageFilter(layer)) || /displace/.test(layer.id)) {
          const idFilterExpression = ["get", /^symbol$/.test(layer.type) ? "direktverbindung_id" : "id"];
          // Reset filter to original state
          const originalFilter = this.getLayerOriginalFilter(layer.id, idFilterExpression);
          mbMap.setFilter(layer.id, originalFilter);
          selectedLines.filter(feat => !!feat.get("name")).forEach(feature => {
            // Add feature id filter
            const featureIdFilter = [...mbMap.getFilter(layer.id), ["==", idFilterExpression, feature.get("id")]];
            mbMap.setFilter(layer.id, featureIdFilter);
          });
        }
        if (this.highlightedStation) {
          var _this$getDvLayers2;
          const fullLayer = (_this$getDvLayers2 = this.getDvLayers(new RegExp("^ipv_call_full_".concat(this.getCurrentLayer(), "$")))) === null || _this$getDvLayers2 === void 0 ? void 0 : _this$getDvLayers2[0];
          mbMap.setLayoutProperty(fullLayer.id, "visibility", "none");
        }
      } else {
        mbMap.setLayoutProperty(layer.id, "visibility", "none");
      }
    });
  }
  highlightStation(feature) {
    var _this$getDvLayers3;
    const {
      mbMap
    } = this.mapboxLayer;
    if (!mbMap) {
      return;
    }
    this.highlightedStation = feature;
    const selectedStationLayer = (_this$getDvLayers3 = this.getDvLayers(new RegExp("^ipv_selected_station_".concat(this.getCurrentLayer(), "$")))) === null || _this$getDvLayers3 === void 0 ? void 0 : _this$getDvLayers3[0];
    const idFilterExpression = ["get", "uid"];
    const originalFilter = this.getLayerOriginalFilter(selectedStationLayer.id, idFilterExpression);
    mbMap.setFilter(selectedStationLayer.id, originalFilter);
    if (this.highlightedStation) {
      var _this$getDvLayers4;
      mbMap.setLayoutProperty(selectedStationLayer.id, "visibility", "visible");
      // Add feature id filter
      const featureIdFilter = [...mbMap.getFilter(selectedStationLayer.id), ["==", idFilterExpression, this.highlightedStation.get("uid")]];
      mbMap.setFilter(selectedStationLayer.id, featureIdFilter);
      const fullLayer = (_this$getDvLayers4 = this.getDvLayers(new RegExp("^ipv_call_full_".concat(this.getCurrentLayer(), "$")))) === null || _this$getDvLayers4 === void 0 ? void 0 : _this$getDvLayers4[0];
      mbMap.setLayoutProperty(fullLayer.id, "visibility", "none");
    } else {
      mbMap.setLayoutProperty(selectedStationLayer.id, "visibility", "none");
    }
    this.dispatchEvent({
      type: "select:station",
      feature: this.highlightedStation
    });
  }
  highlight() {
    let features = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    if (this.visible && !(features !== null && features !== void 0 && features.length)) {
      // remove highlighted station when featureinformation is closed
      this.highlightStation();
    }
    super.highlight(features);
  }
  selectLine(features) {
    this.highlightLine(features);
  }
}
export default DirektverbindungenLayer;
//# sourceMappingURL=DirektverbindungenLayer.js.map