const _excluded = ["url"];
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
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); }
import { MaplibreLayer, getMapboxMapCopyrights } from "mobility-toolbox-js/ol";
import { toLonLat } from "ol/proj";
const applyFilters = (mbStyle, filters) => {
  const newStyle = _objectSpread({}, mbStyle);
  /* Apply filters, remove style layers */
  if (mbStyle && filters) {
    const layers = [];
    (filters || []).forEach(filter => {
      const styleLayers = mbStyle.layers;
      for (let i = 0; i < styleLayers.length; i += 1) {
        const style = styleLayers[i];
        /* filter.include boolean determines if the identified
         * styleLayers or all others should be removed
         */
        const condition = filter.include ? filter.value.test(style[filter.field]) : !filter.value.test(style[filter.field]);
        if (condition) {
          // mapboxStyle.layers.splice(i, 1);
          layers.push(mbStyle.layers[i]);
        }
      }
    });
    newStyle.layers = layers;
  }
  return newStyle;
};
class TrafimageMapboxLayer extends MaplibreLayer {
  constructor(options) {
    super(_objectSpread(_objectSpread({}, options), {}, {
      mapOptions: _objectSpread({
        maxCanvasSize: [20000, 20000]
      }, options.mapOptions || {}),
      styleUrl: {
        version: 8,
        sources: {},
        layers: []
      },
      isHoverActive: false,
      isClickActive: false
    }));
    this.filters = options.filters;

    // TODO don't use process.env here it fails in Schulzug
    // this.stylePrefix = process?.env?.REACT_APP_STYLE_REVIEW_PREFIX || "";
    this.stylePrefix = "";
    this.style = options.style;
  }
  attachToMap(map) {
    super.attachToMap(map);
    if (this.map) {
      this.dispatchEvent({
        type: "init",
        target: this
      });
    }

    // Set zIndex if specified
    if (this.options && this.options.zIndex) {
      this.olLayer.getLayersArray().forEach(layer => layer.setZIndex(this.options.zIndex));
    }
    this.abortController = new AbortController();
  }
  detachFromMap(map) {
    if (this.abortController) {
      this.abortController.abort();
    }
    super.detachFromMap(map);
    this.dispatchEvent({
      type: "terminate",
      target: this
    });
  }
  setStyle(newStyle) {
    // TODO manage if newStyle is null
    if (this.style === newStyle || !newStyle) {
      return;
    }
    this.style = newStyle;
    this.setStyleConfig();
  }
  applyStyle(data) {
    const styleFiltered = applyFilters(data, this.filters);
    this.mbMap.setStyle(styleFiltered);
    this.mbMap.once("styledata", () => {
      this.onStyleLoaded();
    });
  }
  setStyleConfig(url, key, apiKeyName) {
    if (url && url !== this.url) {
      this.url = url;
    }
    if (key && key !== this.apiKey) {
      this.apiKey = key;
    }
    if (apiKeyName && apiKeyName !== this.apiKeyName) {
      this.apiKeyName = apiKeyName;
    }
    const searchParams = new URLSearchParams({
      [this.apiKeyName]: this.apiKey
    });
    const newStyleUrl = "".concat(this.url, "/styles/").concat(this.stylePrefix).concat(this.style, "/style.json?").concat(searchParams.toString());

    // Don't apply style if not necessary otherwise
    // it will remove styles applied by MapboxStyleLayer layers.
    if (this.styleUrl === newStyleUrl) {
      return;
    }
    this.styleUrl = newStyleUrl;
    if (!this.mbMap) {
      if (this.filters) {
        this.on("load", () => {
          this.applyStyle(this.mbMap.getStyle());
        });
      }
      return;
    }

    // We load the new style.
    this.loadStyle(newStyleUrl);
  }
  getFeatures() {
    let {
      source,
      sourceLayer,
      filter
    } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    const {
      mbMap
    } = this;
    // Ignore the getFeatureInfo until the source is loaded
    if (!mbMap || !mbMap.getSource(source) || !mbMap.isSourceLoaded(source)) {
      return [];
    }
    return mbMap.querySourceFeatures(source, {
      sourceLayer,
      filter
    });
  }

  /**
   * Request feature information for a given coordinate and read clustered features.
   * @param {ol/coordinate~Coordinate} coordinate Coordinate to request the information at.
   * @param {Object} options A [mapboxgl.Map#queryrenderedfeatures](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures) options parameter.
   * @returns {Promise<Object>} Promise with features, layer and coordinate
   *  or null if no feature was hit.
   * @ignore
   */
  async getFeatureInfoAtCoordinate(coordinate, options) {
    var _this$map, _this$map2;
    // Ignore the getFeatureInfo until the mapbox map is loaded
    if (!options || !this.format || !this.mbMap || !this.mbMap.isStyleLoaded() || (_this$map = this.map) !== null && _this$map !== void 0 && _this$map.getView().getAnimating() || (_this$map2 = this.map) !== null && _this$map2 !== void 0 && _this$map2.getView().getInteracting()) {
      return Promise.resolve({
        coordinate,
        features: [],
        layer: this
      });
    }
    let pixel = coordinate && this.mbMap.project(toLonLat(coordinate));
    if (this.hitTolerance) {
      const {
        x,
        y
      } = pixel;
      pixel = [{
        x: x - this.hitTolerance,
        y: y - this.hitTolerance
      }, {
        x: x + this.hitTolerance,
        y: y + this.hitTolerance
      }];
    }

    // At this point we get GeoJSON Mapbox feature, we transform it to an OpenLayers
    // feature to be consistent with other layers.
    const renderedFeatures = this.mbMap.queryRenderedFeatures(pixel, options);
    const features = [];
    const promises = [];
    for (let i = 0; i < renderedFeatures.length; i += 1) {
      const feature = renderedFeatures[i];
      if (feature.properties.cluster) {
        const source = this.mbMap.getSource(feature.layer.source);
        const {
          cluster_id: id,
          point_count: count
        } = feature.properties;
        // because Mapbox GL JS should be fast ...
        // eslint-disable-next-line no-await-in-loop
        promises.push(new Promise(resolve => {
          source.getClusterLeaves(id, count, 0, (_, cfs) => {
            cfs === null || cfs === void 0 || cfs.forEach(cf => {
              const olFeature = this.format.readFeature(cf);
              if (olFeature) {
                olFeature.set("mapboxFeature", cf);
              }
              features.push(olFeature);
            });
            resolve(cfs);
          });
        }));
      } else {
        const olFeature = this.format.readFeature(feature);
        if (olFeature) {
          olFeature.set("mapboxFeature", feature);
        }
        features.push(olFeature);
      }
    }
    if (promises.length) {
      return Promise.all(promises).then(() => {
        return {
          layer: this,
          features,
          coordinate
        };
      });
    }
    return Promise.resolve({
      layer: this,
      features,
      coordinate
    });
  }
  loadStyle(newStyleUrl) {
    var _this$options;
    if (!newStyleUrl) {
      return;
    }
    if (this.abortController) {
      this.abortController.abort();
    }
    this.abortController = new AbortController();
    const transformRequest = (_this$options = this.options) === null || _this$options === void 0 || (_this$options = _this$options.mapOptions) === null || _this$options === void 0 ? void 0 : _this$options.transformRequest;
    const transformedRequest = transformRequest ? transformRequest(newStyleUrl, "Style") : null;
    const _ref = transformedRequest || {},
      {
        url = newStyleUrl
      } = _ref,
      requestOptions = _objectWithoutProperties(_ref, _excluded);
    fetch(url, _objectSpread(_objectSpread({}, requestOptions), {}, {
      signal: this.abortController.signal
    })).then(response => {
      return response.json();
    }).then(data => {
      if (!this.mbMap) {
        return;
      }
      this.applyStyle(data);
    }).catch(err => {
      if (err && err.name === "AbortError") {
        // ignore user abort request
        return;
      }
      // eslint-disable-next-line no-console
      console.log("Loading of mapbox style failed: ", newStyleUrl, err);
    });
  }
  onStyleLoaded() {
    this.loaded = true;
    this.olLayer.getSource().setAttributions(this.copyrights || getMapboxMapCopyrights(this.mbMap));
    this.dispatchEvent({
      type: "load",
      target: this
    });
  }

  /**
   * Create a copy of the TrafimageMapboxLayer.
   * @param {Object} newOptions Options to override
   * @returns {TrafimageMapboxLayer} A TrafimageMapboxLayer
   * @ignore
   */
  clone(newOptions) {
    return new TrafimageMapboxLayer(_objectSpread(_objectSpread({}, this.options), newOptions));
  }
}
export default TrafimageMapboxLayer;
//# sourceMappingURL=TrafimageMapboxLayer.js.map