/**
 * vue-cesium - https://github.com/zouyaoji/vue-cesium
 * Vue 2.x components for CesiumJS.
 *
 * @package VueCesium
 * @author zouyaoji <370681295@qq.com>
 * @version 2.2.8
 * @license MIT
 * @homepage https://zouyaoji.top/vue-cesium
 * @copyright (c) 2018-2021, zouyaoji <370681295@qq.com>
 */
/**
 * The Earth Gravity Model 1996 (EGM96) geoid.
 * @param {String} gridFileUrl The URL of the WW15MGH.DAC file.
 */
var EarthGravityModel1996 = function EarthGravityModel1996(gridFileUrl) {
  this.gridFileUrl = gridFileUrl;
  this.data = undefined; // These values were determined by inspecting the WW15MGH.DAC file.  We hard-code them here because
  // we need them available before that file finishes loading.

  this.minimumHeight = -106.99;
  this.maximumHeight = 85.39;
};
/**
 * Determines if this class will work in the current environment.  It will return false on older browsers without support
 * for typed arrays.
 * @return {Boolean} True if this class may be used in this environment; otherwise, false.
 */


EarthGravityModel1996.isSupported = function () {
  return typeof Int16Array !== 'undefined' && typeof Uint8Array !== 'undefined';
};
/**
 * Gets the height of EGM96 above the surface of the ellipsoid.
 * @param {String} baseUrl The base URL for TerriaJS resources.
 * @param {Number} longitude The longitude.
 * @param {Number} latitude The latitude
 * @return {Promise|Number} A promise, that, when it results The height of mean sea level above the ellipsoid at the specified location.  Negative numbers indicate that mean sea level
 *                  is below the ellipsoid.
 */


EarthGravityModel1996.prototype.getHeight = function (longitude, latitude) {
  return getHeightData(this).then(function (data) {
    return getHeightFromData(data, longitude, latitude);
  });
};

EarthGravityModel1996.prototype.getHeights = function (cartographicArray) {
  return getHeightData(this).then(function (data) {
    for (var i = 0; i < cartographicArray.length; ++i) {
      var cartographic = cartographicArray[i];
      cartographic.height = getHeightFromData(data, cartographic.longitude, cartographic.latitude);
    }

    return cartographicArray;
  });
};

function getHeightData(model) {
  var _Cesium = Cesium,
      defined = _Cesium.defined,
      when = _Cesium.when;

  if (!defined(model.data)) {
    model.data = loadArrayBuffer(model.gridFileUrl);
  }

  return when(model.data, function (data) {
    if (!(model.data instanceof Int16Array)) {
      // Data file is big-endian, all relevant platforms are little endian, so swap the byte order.
      var byteView = new Uint8Array(data);

      for (var k = 0; k < byteView.length; k += 2) {
        var tmp = byteView[k];
        byteView[k] = byteView[k + 1];
        byteView[k + 1] = tmp;
      }

      model.data = new Int16Array(data);
    }

    return model.data;
  });
}

function getHeightFromData(data, longitude, latitude) {
  var _Cesium2 = Cesium,
      CesiumMath = _Cesium2.Math;
  var recordIndex = 720 * (CesiumMath.PI_OVER_TWO - latitude) / Math.PI;

  if (recordIndex < 0) {
    recordIndex = 0;
  } else if (recordIndex > 720) {
    recordIndex = 720;
  }

  longitude = CesiumMath.zeroToTwoPi(longitude);
  var heightIndex = 1440 * longitude / CesiumMath.TWO_PI;

  if (heightIndex < 0) {
    heightIndex = 0;
  } else if (heightIndex > 1440) {
    heightIndex = 1440;
  }

  var i = heightIndex | 0;
  var j = recordIndex | 0;
  var xMinusX1 = heightIndex - i;
  var yMinusY1 = recordIndex - j;
  var x2MinusX = 1.0 - xMinusX1;
  var y2MinusY = 1.0 - yMinusY1;
  var f11 = getHeightValue(data, j, i);
  var f21 = getHeightValue(data, j, i + 1);
  var f12 = getHeightValue(data, j + 1, i);
  var f22 = getHeightValue(data, j + 1, i + 1);
  return (f11 * x2MinusX * y2MinusY + f21 * xMinusX1 * y2MinusY + f12 * x2MinusX * yMinusY1 + f22 * xMinusX1 * yMinusY1) / 100.0;
} // Heights returned by this function are in centimeters.


function getHeightValue(data, recordIndex, heightIndex) {
  if (recordIndex > 720) {
    recordIndex = 720;
  } else if (recordIndex < 0) {
    recordIndex = 0;
  }

  if (heightIndex > 1439) {
    heightIndex -= 1440;
  } else if (heightIndex < 0) {
    heightIndex += 1440;
  }

  return data[recordIndex * 1440 + heightIndex];
}

function loadArrayBuffer(urlOrResource) {
  var _Cesium3 = Cesium,
      Resource = _Cesium3.Resource;
  var resource = Resource.createIfNeeded(urlOrResource);
  return resource.fetchArrayBuffer();
} // module.exports = EarthGravityModel1996

export default EarthGravityModel1996;
