"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.STRATEGY_PROGRESSIVE = exports.STRATEGY_MIN_NETWORK_TRAFFIC = exports.STRATEGY_GROUP = exports.STRATEGY_DICHOTOMY = void 0;
exports.chooseNextLevelToFetch = chooseNextLevelToFetch;
var _RasterTile = require("../Renderer/RasterTile");
/**
 * This modules implements various layer update strategies.
 *
 * Default strategy is STRATEGY_MIN_NETWORK_TRAFFIC which aims
 * to reduce the amount of network traffic.
 */

var STRATEGY_MIN_NETWORK_TRAFFIC = 0;
exports.STRATEGY_MIN_NETWORK_TRAFFIC = STRATEGY_MIN_NETWORK_TRAFFIC;
var STRATEGY_GROUP = 1;
exports.STRATEGY_GROUP = STRATEGY_GROUP;
var STRATEGY_PROGRESSIVE = 2;
exports.STRATEGY_PROGRESSIVE = STRATEGY_PROGRESSIVE;
var STRATEGY_DICHOTOMY = 3;
exports.STRATEGY_DICHOTOMY = STRATEGY_DICHOTOMY;
function _minimizeNetworkTraffic(node, nodeLevel, currentLevel) {
  if (node.pendingSubdivision) {
    return currentLevel;
  }
  return nodeLevel;
}

// Maps nodeLevel to groups defined in layer's options
// eg with groups = [3, 7, 12]:
//     * nodeLevel = 2 -> 3
//     * nodeLevel = 4 -> 3
//     * nodeLevel = 7 -> 7
//     * nodeLevel = 15 -> 12
function _group(nodeLevel, options) {
  var f = options.groups.filter(function (val) {
    return val <= nodeLevel;
  });
  return f.length ? f[f.length - 1] : options.groups[0];
}
function _progressive(nodeLevel, currentLevel, options) {
  return Math.min(nodeLevel, currentLevel + (options.increment || 1));
}

// Load textures at mid-point between current level and node's level.
// This produces smoother transitions and a single fetch updates multiple
// tiles thanks to caching.
function _dichotomy(nodeLevel, currentLevel) {
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  if (currentLevel == _RasterTile.EMPTY_TEXTURE_ZOOM) {
    return options.zoom ? options.zoom.min : 0;
  }
  return Math.min(nodeLevel, Math.ceil((currentLevel + nodeLevel) / 2));
}
function chooseNextLevelToFetch(strategy, node) {
  var nodeLevel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : node.level;
  var currentLevel = arguments.length > 3 ? arguments[3] : undefined;
  var layer = arguments.length > 4 ? arguments[4] : undefined;
  var failureParams = arguments.length > 5 ? arguments[5] : undefined;
  var nextLevelToFetch;
  var maxZoom = layer.source.zoom ? layer.source.zoom.max : Infinity;
  if (failureParams.lowestLevelError != Infinity) {
    nextLevelToFetch = _dichotomy(failureParams.lowestLevelError, currentLevel, layer.source);
    nextLevelToFetch = failureParams.lowestLevelError == nextLevelToFetch ? nextLevelToFetch - 1 : nextLevelToFetch;
    if (strategy == STRATEGY_GROUP) {
      nextLevelToFetch = _group(nextLevelToFetch, layer.updateStrategy.options);
    }
  } else {
    switch (strategy) {
      case STRATEGY_GROUP:
        nextLevelToFetch = _group(nodeLevel, layer.updateStrategy.options);
        break;
      case STRATEGY_PROGRESSIVE:
        {
          nextLevelToFetch = _progressive(nodeLevel, currentLevel, layer.updateStrategy.options);
          break;
        }
      case STRATEGY_DICHOTOMY:
        nextLevelToFetch = _dichotomy(nodeLevel, currentLevel, layer.source);
        break;
      // default strategy
      case STRATEGY_MIN_NETWORK_TRAFFIC:
      default:
        nextLevelToFetch = _minimizeNetworkTraffic(node, nodeLevel, currentLevel);
    }
    nextLevelToFetch = Math.min(nextLevelToFetch, maxZoom);
  }
  return nextLevelToFetch;
}