"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.checkNodeElevationTextureValidity = checkNodeElevationTextureValidity;
exports.computeMinMaxElevation = computeMinMaxElevation;
exports.insertSignificantValuesFromParent = insertSignificantValuesFromParent;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _DEMUtils = require("../Utils/DEMUtils");
function minMax4Corners(texture, pitch, options) {
  var u = pitch.x;
  var v = pitch.y;
  var w = pitch.z;
  var z = [(0, _DEMUtils.readTextureValueWithBilinearFiltering)(options, texture, u, v), (0, _DEMUtils.readTextureValueWithBilinearFiltering)(options, texture, u + w, v), (0, _DEMUtils.readTextureValueWithBilinearFiltering)(options, texture, u + w, v + w), (0, _DEMUtils.readTextureValueWithBilinearFiltering)(options, texture, u, v + w)].filter(function (val) {
    return val != undefined;
  });
  if (z.length) {
    return {
      min: Math.min.apply(Math, (0, _toConsumableArray2["default"])(z)),
      max: Math.max.apply(Math, (0, _toConsumableArray2["default"])(z))
    };
  } else {
    return {
      min: Infinity,
      max: -Infinity
    };
  }
}

/**
 * Calculates the minimum maximum texture elevation with xbil data
 *
 * @param      {THREE.Texture}   texture                     The texture to parse
 * @param      {THREE.Vector4}   pitch                       The pitch,  restrict zone to parse
 * @param      {Object}          options                     No data value and clamp values
 * @param      {number}          options.noDataValue         No data value
 * @param      {number}          [options.zmin]   The minimum elevation value after which it will be clamped
 * @param      {number}          [options.zmax]   The maximum elevation value after which it will be clamped
 * @return     {Object}  The minimum and maximum elevation.
 */
function computeMinMaxElevation(texture, pitch, options) {
  var _texture$image = texture.image,
    width = _texture$image.width,
    height = _texture$image.height,
    data = _texture$image.data;
  if (!data) {
    // Return null values means there's no elevation values.
    // They can't be determined.
    // Don't return 0 because the result will be wrong
    return {
      min: null,
      max: null
    };
  }

  // compute the minimum and maximum elevation on the 4 corners texture.
  var _minMax4Corners = minMax4Corners(texture, pitch, options),
    min = _minMax4Corners.min,
    max = _minMax4Corners.max;
  var sizeX = Math.floor(pitch.z * width);
  if (sizeX > 2) {
    var sizeY = Math.floor(pitch.z * height);
    var xs = Math.floor(pitch.x * width);
    var ys = Math.floor(pitch.y * height);
    var inc = Math.max(Math.floor(sizeX / 32), 2);
    for (var y = ys; y < ys + sizeY; y += inc) {
      var pit = y * (width || 0);
      var x = pit + xs;
      var _limX = x + sizeX;
      for (x; x < _limX; x += inc) {
        var val = data[x];
        if (val !== options.noDataValue) {
          max = Math.max(max, val);
          min = Math.min(min, val);
        }
      }
    }
    if (options.zmin > min) {
      min = options.zmin;
    }
    if (options.zmax < max) {
      max = options.zmax;
    }
  }
  if (max === -Infinity || min === Infinity) {
    // Return null values means the elevation values are incoherent
    // They can't be determined.
    // Don't return 0, -Infinity or Infinity because the result will be wrong
    return {
      min: null,
      max: null
    };
  } else {
    return {
      min: min,
      max: max
    };
  }
}

// We check if the elevation texture has some significant values through corners
function checkNodeElevationTextureValidity(data, noDataValue) {
  var l = data.length;
  return data[0] > noDataValue && data[l - 1] > noDataValue && data[Math.sqrt(l) - 1] > noDataValue && data[l - Math.sqrt(l)] > noDataValue;
}

// This function replaces noDataValue by significant values from parent texture (or 0)
function insertSignificantValuesFromParent(data) {
  var dataParent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
    return 0;
  };
  var noDataValue = arguments.length > 2 ? arguments[2] : undefined;
  for (var i = 0, l = data.length; i < l; ++i) {
    if (data[i] === noDataValue) {
      data[i] = dataParent(i);
    }
  }
}