"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));

var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));

var _Source2 = _interopRequireDefault(require("./Source"));

var _URLBuilder = _interopRequireDefault(require("../Provider/URLBuilder"));

/**
 * @classdesc
 * An object defining the source of resources to get from a
 * [WFS]{@link http://www.opengeospatial.org/standards/wfs} server. It inherits
 * from {@link Source}.
 *
 * @extends Source
 *
 * @property {boolean} isWFSSource - Used to checkout whether this source is a
 * WFSSource. Default is true. You should not change this, as it is used
 * internally for optimisation.
 * @property {string} typeName - The name of the feature to get, used in the
 * generation of the url.
 * @property {string} version - The version of the WFS server to request on.
 * Default value is '2.0.2'.
 * @property {Object} zoom - Object containing the minimum and maximum values of
 * the level, to zoom in the source.
 * @property {number} zoom.min - The minimum level of the source. Default value
 * is 0.
 * @property {number} zoom.max - The maximum level of the source. Default value
 * is 21.
 * @property {Object} vendorSpecific - An object containing vendor specific
 * parameters. See for example a [list of these parameters for GeoServer]{@link
 * https://docs.geoserver.org/latest/en/user/services/wfs/vendor.html}. This
 * object is read simply with the `key` being the name of the parameter and
 * `value` being the value of the parameter. If used, this property should be
 * set in the constructor parameters.
 *
 * @example
 * // Add color layer with WFS source
 * // Create the source
 * const wfsSource = new itowns.WFSSource({
 *     url: 'http://wxs.fr/wfs',
 *     version: '2.0.0',
 *     typeName: 'BDTOPO_BDD_WLD_WGS84G:bati_remarquable',
 *     projection: 'EPSG:4326',
 *     extent: {
 *         west: 4.568,
 *         east: 5.18,
 *         south: 45.437,
 *         north: 46.03,
 *     },
 *     zoom: { min: 14, max: 14 },
 *     format: 'application/json',
 * });
 *
 * // Create the layer
 * const colorlayer = new itowns.ColorLayer('color_build', {
 *     style: {
 *         fill: 'red',
 *         fillOpacity: 0.5,
 *         stroke: 'white',
 *     },
 *     source: wfsSource,
 * });
 *
 * // Add the layer
 * view.addLayer(colorlayer);
 *
 * @example
 * // Add geometry layer with WFS source
 * // Create the source
 * const wfsSource = new itowns.WFSSource({
 *     url: 'http://wxs.fr/wfs',
 *     version: '2.0.0',
 *     typeName: 'BDTOPO_BDD_WLD_WGS84G:bati_remarquable',
 *     projection: 'EPSG:4326',
 *     extent: {
 *         west: 4.568,
 *         east: 5.18,
 *         south: 45.437,
 *         north: 46.03,
 *     },
 *     zoom: { min: 14, max: 14 },
 *     format: 'application/json',
 * });
 *
 * // Create the layer
 * const geometryLayer = new itowns.GeometryLayer('mesh_build', {
 *     update: itowns.FeatureProcessing.update,
 *     convert: itowns.Feature2Mesh.convert({ extrude: () => 50 }),
 *     source: wfsSource,
 * });
 *
 * // Add the layer
 * view.addLayer(geometryLayer);
 */
var WFSSource =
/*#__PURE__*/
function (_Source) {
  (0, _inherits2["default"])(WFSSource, _Source);

  /**
   * @param {Object} source - An object that can contain all properties of a
   * WFSSource and {@link Source}. `url`, `typeName` and `projection` are
   * mandatory.
   *
   * @constructor
   */
  function WFSSource(source) {
    var _this;

    (0, _classCallCheck2["default"])(this, WFSSource);

    if (!source.typeName) {
      throw new Error('source.typeName is required in wfs source.');
    }

    if (!source.projection) {
      throw new Error('source.projection is required in wfs source');
    }

    _this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(WFSSource).call(this, source));
    _this.isWFSSource = true;
    _this.typeName = source.typeName;
    _this.format = _this.format || 'application/json';
    _this.version = source.version || '2.0.2';
    _this.url = "".concat(source.url, "SERVICE=WFS&REQUEST=GetFeature&typeName=").concat(_this.typeName, "&VERSION=").concat(_this.version, "&SRSNAME=").concat(_this.projection, "&outputFormat=").concat(_this.format, "&BBOX=%bbox,").concat(_this.projection);
    _this.zoom = source.zoom || {
      min: 0,
      max: 21
    };
    _this.vendorSpecific = source.vendorSpecific;

    for (var name in _this.vendorSpecific) {
      if (Object.prototype.hasOwnProperty.call(_this.vendorSpecific, name)) {
        _this.url = "".concat(_this.url, "&").concat(name, "=").concat(_this.vendorSpecific[name]);
      }
    }

    return _this;
  }

  (0, _createClass2["default"])(WFSSource, [{
    key: "handlingError",
    value: function handlingError(err, url) {
      var _this2 = this;

      if (err.response && err.response.status == 400) {
        return err.response.text().then(function (text) {
          var getCapUrl = "".concat(_this2.url, "SERVICE=WFS&REQUEST=GetCapabilities&VERSION=").concat(_this2.version);
          var xml = new DOMParser().parseFromString(text, 'application/xml');
          var errorElem = xml.querySelector('Exception');
          var errorCode = errorElem.getAttribute('exceptionCode');
          var errorMessage = errorElem.querySelector('ExceptionText').textContent;
          console.error("Source ".concat(_this2.typeName, ": bad request when fetching data. Server says: \"").concat(errorCode, ": ").concat(errorMessage, "\". \nReviewing ").concat(getCapUrl, " may help."), err);
          throw err;
        });
      } else {
        console.error("Source ".concat(this.typeName, ": error while trying to fetch/parse/convert WFS data. Url was ").concat(url, "."), err);
        throw err;
      }
    }
  }, {
    key: "urlFromExtent",
    value: function urlFromExtent(extent) {
      return _URLBuilder["default"].bbox(extent, this);
    }
  }, {
    key: "extentInsideLimit",
    value: function extentInsideLimit(extent) {
      return (extent.zoom == undefined || extent.zoom >= this.zoom.min && extent.zoom <= this.zoom.max) && this.extent.intersectsExtent(extent);
    }
  }]);
  return WFSSource;
}(_Source2["default"]);

var _default = WFSSource;
exports["default"] = _default;