"use strict";

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

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

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

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

var _Extent = _interopRequireDefault(require("../Core/Geographic/Extent"));

var _GeoJsonParser = _interopRequireDefault(require("../Parser/GeoJsonParser"));

var _KMLParser = _interopRequireDefault(require("../Parser/KMLParser"));

var _GpxParser = _interopRequireDefault(require("../Parser/GpxParser"));

var _VectorTileParser = _interopRequireDefault(require("../Parser/VectorTileParser"));

var _Fetcher = _interopRequireDefault(require("../Provider/Fetcher"));

function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function () {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

var supportedFetchers = new Map([['image/x-bil;bits=32', _Fetcher["default"].textureFloat], ['geojson', _Fetcher["default"].json], ['application/json', _Fetcher["default"].json], ['application/kml', _Fetcher["default"].xml], ['application/gpx', _Fetcher["default"].xml], ['application/x-protobuf;type=mapbox-vector', _Fetcher["default"].arrayBuffer]]);
exports.supportedFetchers = supportedFetchers;
var supportedParsers = new Map([['geojson', _GeoJsonParser["default"].parse], ['application/json', _GeoJsonParser["default"].parse], ['application/kml', _KMLParser["default"].parse], ['application/gpx', _GpxParser["default"].parse], ['application/x-protobuf;type=mapbox-vector', _VectorTileParser["default"].parse]]);
exports.supportedParsers = supportedParsers;
var uid = 0;
/**
 * @classdesc
 * Sources are object containing informations on how to fetch resources, from a
 * set source.
 *
 * To extend a Source, it is necessary to implement two functions:
 * `urlFromExtent` and `extentInsideLimit`.
 *
 * @property {boolean} isSource - Used to checkout whether this source is a
 * Source. Default is true. You should not change this, as it is used internally
 * for optimisation.
 * @property {number} uid - Unique uid mainly used to store data linked to this
 * source into Cache.
 * @property {string} url - The url of the resources that are fetched.
 * @property {string} format - The format of the resources that are fetched.
 * @property {function} fetcher - The method used to fetch the resources from
 * the source. iTowns provides some methods in {@link Fetcher}, but it can be
 * specified a custom one. This method should return a `Promise` containing the
 * fetched resource. If this property is set, it overrides the chosen fetcher
 * method with `format`.
 * @property {Object} networkOptions - Fetch options (passed directly to
 * `fetch()`), see [the syntax for more information]{@link
 * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Syntax}.
 * By default, set to `{ crossOrigin: 'anonymous' }`.
 * @property {string} projection - The projection of the resources.
 * @property {string} attribution - The intellectual property rights for the
 * resources.
 * @property {Extent} extent - The extent of the resources.
 * @property {function} parser - The method used to parse the resources attached
 * to the layer. iTowns provides some parsers, visible in the `Parser/` folder.
 * If the method is custom, it should return a `Promise` containing the parsed
 * resource. If this property is set, it overrides the default selected parser
 * method with `source.format`. If `source.format` is also empty, no parsing
 * action is done.
 * <br><br>
 * When calling this method, two parameters are passed:
 * <ul>
 *  <li>the fetched data, i.e. the data to parse</li>
 *  <li>an object containing severals properties, set when this method is
 *  called: it is specific to each call, so the value of each property can vary
 *  depending on the current fetched tile for example</li>
 * </ul>
 *
 * The properties of the second parameter are:
 * <ul>
 *  <li>`buildExtent : boolean` - True if the layer does not inherit from {@link
 *  GeometryLayer}.</li>
 *  <li>`crsIn : string` - The projection of the source.</li>
 *  <li>`crsOut : string` - The projection of the layer.</li>
 *  <li>`filteringExtent : Extent` - If the layer inherits from {@link
 *  GeometryLayer}, it is set to the extent of destination, otherwise it is
 *  undefined.</li>
 *  <li>`filter : function` - Property of the layer.</li>
 *  <li>`mergeFeatures : boolean (default true)` - Property of the layer,
 *  default to true.</li>
 *  <li>`withNormal : boolean` - True if the layer inherits from {@link
 *  GeometryLayer}.</li>
 *  <li>`withAltitude : boolean` - True if the layer inherits from {@link
 *  GeometryLayer}.</li>
 *  <li>`isInverted : string` - Property of the source.</li>
 * </ul>
 */

var Source = /*#__PURE__*/function () {
  /**
   * @param {Object} source - An object that can contain all properties of a
   * Source. Only the `url` property is mandatory.
   *
   * @constructor
   */
  function Source(source) {
    (0, _classCallCheck2["default"])(this, Source);
    this.isSource = true;

    if (!source.url) {
      throw new Error('New Source: url is required');
    }

    this.uid = uid++;
    this.url = source.url;
    this.format = source.format;
    this.fetcher = source.fetcher || supportedFetchers.get(source.format) || _Fetcher["default"].texture;

    this.parser = source.parser || supportedParsers.get(source.format) || function (d) {
      return Promise.resolve(d);
    };

    this.isVectorSource = (source.parser || supportedParsers.get(source.format)) != undefined;
    this.networkOptions = source.networkOptions || {
      crossOrigin: 'anonymous'
    };
    this.projection = source.projection;
    this.attribution = source.attribution;
    this.whenReady = Promise.resolve();

    if (source.extent && !source.extent.isExtent) {
      this.extent = new _Extent["default"](this.projection, source.extent);
    } else {
      this.extent = source.extent;
    }
  }

  (0, _createClass2["default"])(Source, [{
    key: "handlingError",
    value: function handlingError(err) {
      console.warn("err ".concat(this), err);
    }
    /**
     * Generates an url from an extent. This url is a link to fetch the
     * resources inside the extent.
     *
     * @param {Extent} extent - Extent to convert in url.
      * @return {string} The URL constructed from the extent.
     */
    // eslint-disable-next-line

  }, {
    key: "urlFromExtent",
    value: function urlFromExtent() {
      throw new Error('In extended Source, you have to implement the method urlFromExtent!');
    }
    /**
     * Tests if an extent is inside the source limits.
     *
     * @param {Extent} extent - Extent to test.
      * @return {boolean} True if the extent is inside the limit, false otherwise.
     */
    // eslint-disable-next-line

  }, {
    key: "extentInsideLimit",
    value: function extentInsideLimit() {
      throw new Error('In extented Source, you have to implement the method extentInsideLimit!');
    }
    /**
     * Tests if an array of extents is inside the source limits.
     *
     * @param {Array.<Extent>} extents - Array of extents to test.
      * @return {boolean} True if all extents are inside, false otherwise.
     */

  }, {
    key: "extentsInsideLimit",
    value: function extentsInsideLimit(extents) {
      var _iterator = _createForOfIteratorHelper(extents),
          _step;

      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var extent = _step.value;

          if (!this.extentInsideLimit(extent)) {
            return false;
          }
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }

      return true;
    }
  }, {
    key: "onParsedFile",
    value: function onParsedFile(parsedFile) {
      return parsedFile;
    }
  }]);
  return Source;
}();

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