"use strict";

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

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

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

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

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

var _Cache = _interopRequireDefault(require("../Core/Scheduler/Cache"));

var _CancelledCommandException = _interopRequireDefault(require("../Core/Scheduler/CancelledCommandException"));

var supportedFetchers = new Map([['image/x-bil;bits=32', _Fetcher["default"].textureFloat], ['geojson', _Fetcher["default"].json], ['application/json', _Fetcher["default"].json], ['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/x-protobuf;type=mapbox-vector', _VectorTileParser["default"].parse]]);

function isValidData(data, extentDestination, validFn) {
  if (data && (!validFn || validFn(data, extentDestination))) {
    return data;
  }
}

var error = function (err, url, source) {
  source.handlingError(err, url);
  throw err;
};

function convertSourceData(data, extDest, layer) {
  return layer.convert(data, extDest, layer);
}

function parseSourceData(data, extSrc, extDest, layer) {
  var source = layer.source;

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

  var options = {
    buildExtent: source.isFileSource || !layer.isGeometryLayer,
    crsIn: source.projection,
    crsOut: layer.projection,
    // TODO FIXME: error in filtering vector tile
    // filteringExtent: extentDestination.as(layer.projection),
    filteringExtent: !source.isFileSource && layer.isGeometryLayer ? extDest.as(source.projection) : undefined,
    overrideAltitudeInToZero: layer.overrideAltitudeInToZero,
    filter: layer.filter,
    isInverted: source.isInverted,
    mergeFeatures: layer.mergeFeatures === undefined ? true : layer.mergeFeatures,
    withNormal: layer.isGeometryLayer,
    withAltitude: layer.isGeometryLayer
  };
  data.coords = extSrc;
  return parser(data, options).then(function (parsedFile) {
    if (source.isFileSource) {
      source.parsedData = parsedFile;

      if (parsedFile.extent && parsedFile.extent.crs != 'EPSG:4978') {
        source.extent = parsedFile.extent;
      }
    }

    return parsedFile;
  });
}

function fetchSourceData(url, layer) {
  var source = layer.source;

  var fetcher = source.fetcher || supportedFetchers.get(source.format) || _Fetcher["default"].texture; // Fetch data


  return fetcher(url, source.networkOptions);
}

var _default = {
  executeCommand: function executeCommand(command) {
    var promises = [];
    var layer = command.layer;
    var source = layer.source;
    var requester = command.requester;
    var extentsSource = command.extentsSource;
    var extentsDestination = command.extentsDestination || extentsSource;
    var parsedData = command.parsedData || []; // TODO: Find best place to cancel Command

    if (requester && !requester.material) {
      // request has been deleted
      return Promise.reject(new _CancelledCommandException["default"](command));
    }

    var _loop = function (i) {
      var extSource = extentsSource[i];
      var extDest = extentsDestination[i]; // If source, we must fetch and convert data
      // URL of the resource you want to fetch

      var url = source.urlFromExtent(extSource); // Already fetched and parsed data that can be used

      var validedParsedData = isValidData(parsedData[i], extDest, layer.isValidData) || source.parsedData; // Tag to Cache data

      var tag = "".concat(source.uid, "-").concat(extSource.toString('-')); // Get converted source data, in cache

      var convertedSourceData = _Cache["default"].get(tag); // If data isn't in cache


      if (!convertedSourceData) {
        if (validedParsedData) {
          // Convert
          convertedSourceData = convertSourceData(validedParsedData, extDest, layer);
        } else if (source.fetchedData) {
          // Parse and convert
          convertedSourceData = parseSourceData(source.fetchedData, extSource, extDest, layer).then(function (parsedData) {
            return convertSourceData(parsedData, extDest, layer);
          }, function (err) {
            return error(err, url, source);
          });
        } else {
          // Fetch, parse and convert
          convertedSourceData = fetchSourceData(url, layer).then(function (fetchedData) {
            return parseSourceData(fetchedData, extSource, extDest, layer);
          }, function (err) {
            return error(err, url, source);
          }).then(function (parsedData) {
            return convertSourceData(parsedData, extDest, layer);
          }, function (err) {
            return error(err, url, source);
          });
        } // Put converted data in cache


        _Cache["default"].set(tag, convertedSourceData, _Cache["default"].POLICIES.TEXTURE);
      } // Verify some command is resolved
      // See old WFSProvider : command.resolve(result)


      promises.push(convertedSourceData);
    };

    for (var i = 0, max = extentsSource.length; i < max; i++) {
      _loop(i, max);
    }

    return Promise.all(promises);
  }
};
exports["default"] = _default;