text: import createTileKey from "./createTileKey.js";
  import runLater from "./runLater.js";
  import { defined } from "../Source/Cesium.js";
  import { GeographicTilingScheme } from "../Source/Cesium.js";
  import { HeightmapTerrainData } from "../Source/Cesium.js";
  import { RuntimeError } from "../Source/Cesium.js";
  import { TerrainProvider } from "../Source/Cesium.js";
  import { when } from "../Source/Cesium.js";
  
  function MockTerrainProvider() {
    this.tilingScheme = new GeographicTilingScheme();
    this.heightmapWidth = 65;
    this.levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(
      this.tilingScheme.ellipsoid,
      this.heightmapWidth,
      this.tilingScheme.getNumberOfXTilesAtLevel(0)
    );
    this.ready = true;
    this.hasWaterMask = true;
  
    this._tileDataAvailable = {};
    this._requestTileGeometryWillSucceed = {};
    this._requestTileGeometryWillSucceedWith = {};
    this._willHaveWaterMask = {};
    this._createMeshWillSucceed = {};
    this._upsampleWillSucceed = {};
  }
  
  MockTerrainProvider.prototype.requestTileGeometry = function (
    x,
    y,
    level,
    request
  ) {
    var willSucceed = this._requestTileGeometryWillSucceed[
      createTileKey(x, y, level)
    ];
    if (willSucceed === undefined) {
      return undefined; // defer by default
    }
  
    var that = this;
    return runLater(function () {
      if (willSucceed === true) {
        return createTerrainData(that, x, y, level, false);
      } else if (willSucceed === false) {
        throw new RuntimeError("requestTileGeometry failed as requested.");
      }
  
      return when(willSucceed).then(function () {
        return createTerrainData(that, x, y, level, false);
      });
    });
  };
  
  MockTerrainProvider.prototype.getTileDataAvailable = function (
    xOrTile,
    y,
    level
  ) {
    return this._tileDataAvailable[createTileKey(xOrTile, y, level)];
  };
  
  MockTerrainProvider.prototype.getLevelMaximumGeometricError = function (level) {
    return this.levelZeroMaximumGeometricError / (1 << level);
  };
  
  MockTerrainProvider.prototype.requestTileGeometryWillSucceed = function (
    xOrTile,
    y,
    level
  ) {
    this._requestTileGeometryWillSucceed[createTileKey(xOrTile, y, level)] = true;
    return this;
  };
  
  MockTerrainProvider.prototype.requestTileGeometryWillSucceedWith = function (
    terrainData,
    xOrTile,
    y,
    level
  ) {
    this._requestTileGeometryWillSucceed[createTileKey(xOrTile, y, level)] = true;
    this._requestTileGeometryWillSucceedWith[
      createTileKey(xOrTile, y, level)
    ] = terrainData;
    return this;
  };
  
  MockTerrainProvider.prototype.requestTileGeometryWillFail = function (
    xOrTile,
    y,
    level
  ) {
    this._requestTileGeometryWillSucceed[
      createTileKey(xOrTile, y, level)
    ] = false;
    return this;
  };
  
  MockTerrainProvider.prototype.requestTileGeometryWillDefer = function (
    xOrTile,
    y,
    level
  ) {
    this._requestTileGeometryWillSucceed[
      createTileKey(xOrTile, y, level)
    ] = undefined;
    return this;
  };
  
  MockTerrainProvider.prototype.requestTileGeometryWillWaitOn = function (
    promise,
    xOrTile,
    y,
    level
  ) {
    this._requestTileGeometryWillSucceed[
      createTileKey(xOrTile, y, level)
    ] = promise;
    return this;
  };
  
  MockTerrainProvider.prototype.willHaveWaterMask = function (
    includeLand,
    includeWater,
    xOrTile,
    y,
    level
  ) {
    this._willHaveWaterMask[createTileKey(xOrTile, y, level)] =
      includeLand || includeWater
        ? {
            includeLand: includeLand,
            includeWater: includeWater,
          }
        : undefined;
    return this;
  };
  
  MockTerrainProvider.prototype.createMeshWillSucceed = function (
    xOrTile,
    y,
    level
  ) {
    this._createMeshWillSucceed[createTileKey(xOrTile, y, level)] = true;
    return this;
  };
  
  MockTerrainProvider.prototype.createMeshWillFail = function (
    xOrTile,
    y,
    level
  ) {
    this._createMeshWillSucceed[createTileKey(xOrTile, y, level)] = false;
    return this;
  };
  
  MockTerrainProvider.prototype.createMeshWillDefer = function (
    xOrTile,
    y,
    level
  ) {
    this._createMeshWillSucceed[createTileKey(xOrTile, y, level)] = undefined;
    return this;
  };
  
  MockTerrainProvider.prototype.createMeshWillWaitOn = function (
    promise,
    xOrTile,
    y,
    level
  ) {
    this._createMeshWillSucceed[createTileKey(xOrTile, y, level)] = promise;
    return this;
  };
  
  MockTerrainProvider.prototype.upsampleWillSucceed = function (
    xOrTile,
    y,
    level
  ) {
    this._upsampleWillSucceed[createTileKey(xOrTile, y, level)] = true;
    return this;
  };
  
  MockTerrainProvider.prototype.upsampleWillFail = function (xOrTile, y, level) {
    this._upsampleWillSucceed[createTileKey(xOrTile, y, level)] = false;
    return this;
  };
  
  MockTerrainProvider.prototype.upsampleWillDefer = function (xOrTile, y, level) {
    this._upsampleWillSucceed[createTileKey(xOrTile, y, level)] = undefined;
    return this;
  };
  
  MockTerrainProvider.prototype.willBeAvailable = function (xOrTile, y, level) {
    this._tileDataAvailable[createTileKey(xOrTile, y, level)] = true;
    return this;
  };
  
  MockTerrainProvider.prototype.willBeUnavailable = function (xOrTile, y, level) {
    this._tileDataAvailable[createTileKey(xOrTile, y, level)] = false;
    return this;
  };
  
  MockTerrainProvider.prototype.willBeUnknownAvailability = function (
    xOrTile,
    y,
    level
  ) {
    this._tileDataAvailable[createTileKey(xOrTile, y, level)] = undefined;
    return this;
  };
  
  function createTerrainData(terrainProvider, x, y, level, upsampled) {
    var terrainData =
      terrainProvider._requestTileGeometryWillSucceedWith[
        createTileKey(x, y, level)
      ];
  
    if (!defined(terrainData)) {
      var options = {
        width: 5,
        height: 5,
        buffer: new Float32Array(25),
        createdByUpsampling: upsampled,
      };
  
      var willHaveWaterMask =
        terrainProvider._willHaveWaterMask[createTileKey(x, y, level)];
      if (defined(willHaveWaterMask)) {
        if (willHaveWaterMask.includeLand && willHaveWaterMask.includeWater) {
          options.waterMask = new Uint8Array(4);
          options.waterMask[0] = 1;
          options.waterMask[1] = 1;
          options.waterMask[2] = 0;
          options.waterMask[3] = 0;
        } else if (willHaveWaterMask.includeLand) {
          options.waterMask = new Uint8Array(1);
          options.waterMask[0] = 0;
        } else if (willHaveWaterMask.includeWater) {
          options.waterMask = new Uint8Array(1);
          options.waterMask[0] = 1;
        }
      }
  
      terrainData = new HeightmapTerrainData(options);
    }
  
    var originalUpsample = terrainData.upsample;
    terrainData.upsample = function (
      tilingScheme,
      thisX,
      thisY,
      thisLevel,
      descendantX,
      descendantY
    ) {
      var willSucceed =
        terrainProvider._upsampleWillSucceed[
          createTileKey(descendantX, descendantY, thisLevel + 1)
        ];
      if (willSucceed === undefined) {
        return undefined; // defer by default
      }
  
      if (willSucceed) {
        return originalUpsample.apply(terrainData, arguments);
      }
  
      return runLater(function () {
        throw new RuntimeError("upsample failed as requested.");
      });
    };
  
    var originalCreateMesh = terrainData.createMesh;
    terrainData.createMesh = function (tilingScheme, x, y, level) {
      var willSucceed =
        terrainProvider._createMeshWillSucceed[createTileKey(x, y, level)];
      if (willSucceed === undefined) {
        return undefined; // defer by default
      }
  
      if (willSucceed === true) {
        return originalCreateMesh.apply(terrainData, arguments);
      } else if (willSucceed === false) {
        return runLater(function () {
          throw new RuntimeError("createMesh failed as requested.");
        });
      }
  
      var args = arguments;
  
      return runLater(function () {
        return when(willSucceed).then(function () {
          return originalCreateMesh.apply(terrainData, args);
        });
      });
    };
  
    return terrainData;
  }
  export default MockTerrainProvider;
  