import * as Cesium from "cesium";
import Sandcastle from "Sandcastle";

// Set the ellipsoid to be the moon before creating the viewer
Cesium.Ellipsoid.default = Cesium.Ellipsoid.MOON;

const viewer = new Cesium.Viewer("cesiumContainer", {
  terrainProvider: false,
  baseLayer: false,
  timeline: false,
  animation: false,
  baseLayerPicker: false,
  geocoder: false,
  shadows: true,
});

const scene = viewer.scene;

// Add Moon Terrain 3D Tiles
try {
  const tileset1 = await Cesium.Cesium3DTileset.fromIonAssetId(2684829, {
    // Allow clamp to 3D Tiles
    enableCollision: true,
  });
  viewer.scene.primitives.add(tileset1);
} catch (error) {
  console.log(`Error loading tileset: ${error}`);
}

// Boundary data from https://wms.lroc.asu.edu/lroc/view_rdr/SHAPEFILE_LROC_GLOBAL_MARE
const boundariesResource = await Cesium.IonResource.fromAssetId(2683530);
const boundarySource = await Cesium.GeoJsonDataSource.load(boundariesResource, {
  clampToGround: true,
  fill: Cesium.Color.fromBytes(26, 106, 113).withAlpha(0.6),
});
boundarySource.show = false;
viewer.dataSources.add(boundarySource);

// Possible Artemis 3 landing locations. data from https://files.actgate.com/lunar/A3_Named_regions.geojson
const artemis3resource = await Cesium.IonResource.fromAssetId(2683531);
const artemis3Source = await Cesium.GeoJsonDataSource.load(artemis3resource, {
  clampToGround: true,
  fill: Cesium.Color.fromBytes(243, 242, 99).withAlpha(0.6),
});
artemis3Source.show = false;
viewer.dataSources.add(artemis3Source);

// Positions courtesy of https://www.sciencedirect.com/science/article/abs/pii/S0019103516301518?via%3Dihub
const pointsOfInterest = [
  {
    text: "Apollo 11",
    latitude: 0.67416,
    longitude: 23.47315,
  },
  {
    text: "Apollo 14",
    latitude: -3.64417,
    longitude: 342.52135,
  },
  {
    text: "Apollo 15",
    latitude: 26.13341,
    longitude: 3.6285,
  },
  {
    text: "Lunokhod 1",
    latitude: 38.2378,
    longitude: -35.0017,
  },
  {
    text: "Lunokhod 2",
    latitude: 25.83232,
    longitude: 30.92215,
  },
];

for (const poi of pointsOfInterest) {
  viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(poi.longitude, poi.latitude),
    label: {
      text: poi.text,
      font: "14pt Verdana",
      outlineColor: Cesium.Color.DARKSLATEGREY,
      outlineWidth: 2,
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      pixelOffset: new Cesium.Cartesian2(0, -22),
      scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5),
      translucencyByDistance: new Cesium.NearFarScalar(2.5e7, 1.0, 4.0e7, 0.0),
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      disableDepthTestDistance: new Cesium.CallbackProperty(() => {
        return Cesium.Cartesian3.magnitude(scene.camera.positionWC);
      }, false),
    },
    point: {
      pixelSize: 10,
      color: Cesium.Color.fromBytes(243, 242, 99),
      outlineColor: Cesium.Color.fromBytes(219, 218, 111),
      outlineWidth: 2,
      scaleByDistance: new Cesium.NearFarScalar(1.5e3, 1.0, 4.0e7, 0.1),
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      disableDepthTestDistance: new Cesium.CallbackProperty(() => {
        return Cesium.Cartesian3.magnitude(scene.camera.positionWC);
      }, false),
    },
  });
}

const seaOfTranquility = {
  destination: new Cesium.Cartesian3(
    2134594.9298812235,
    1256488.0678322134,
    379606.9284823841,
  ),
  orientation: {
    direction: new Cesium.Cartesian3(
      -0.8518395698371783,
      -0.5014189063342804,
      -0.1514873843927112,
    ),
    up: new Cesium.Cartesian3(
      -0.13054959630640847,
      -0.07684549781463353,
      0.9884591910493093,
    ),
  },
  easingFunction: Cesium.EasingFunction.LINEAR_NONE,
};

const apollo11 = {
  destination: new Cesium.Cartesian3(
    1609100.311044896,
    733266.0643925276,
    53608.976740262646,
  ),
  orientation: {
    direction: new Cesium.Cartesian3(
      -0.41704286323660256,
      -0.7222280712427744,
      -0.5517806297183315,
    ),
    up: new Cesium.Cartesian3(
      0.8621189850799429,
      -0.12210806245903304,
      -0.49177278965720556,
    ),
  },
  easingFunction: Cesium.EasingFunction.LINEAR_NONE,
};

const copernicus = {
  destination: new Cesium.Cartesian3(
    1613572.8201475781,
    -677039.3827805589,
    339559.7958496013,
  ),
  orientation: {
    direction: new Cesium.Cartesian3(
      -0.10007925201262617,
      0.8771366500325052,
      -0.4696971795597116,
    ),
    up: new Cesium.Cartesian3(
      0.9948921707513932,
      0.08196514973381885,
      -0.058917593354560566,
    ),
  },
  easingFunction: Cesium.EasingFunction.LINEAR_NONE,
};

const tycho = {
  destination: new Cesium.Cartesian3(
    1368413.3560818078,
    -166198.00035620513,
    -1203576.7397013502,
  ),
  orientation: {
    direction: new Cesium.Cartesian3(
      -0.8601315724135887,
      -0.5073902275496569,
      0.05223825345888711,
    ),
    up: new Cesium.Cartesian3(
      0.2639103814694499,
      -0.5303301783281616,
      -0.8056681776681204,
    ),
  },
  easingFunction: Cesium.EasingFunction.LINEAR_NONE,
};

const shackleton = {
  destination: Cesium.Rectangle.fromBoundingSphere(
    new Cesium.BoundingSphere(
      new Cesium.Cartesian3(
        -17505.087036391753,
        38147.40236305639,
        -1769721.5748224584,
      ),
      40000.0,
    ),
  ),
  orientation: {
    direction: new Cesium.Cartesian3(
      0.2568703591904826,
      -0.6405212914728244,
      0.7237058060699372,
    ),
    up: new Cesium.Cartesian3(
      0.26770932874967773,
      -0.6723714327527822,
      -0.6901075073627064,
    ),
  },
  easingFunction: Cesium.EasingFunction.LINEAR_NONE,
};

const rotationSpeed = Cesium.Math.toRadians(0.1);
const removeRotation = viewer.scene.postRender.addEventListener(
  function (scene, time) {
    viewer.scene.camera.rotateRight(rotationSpeed);
  },
);

const options1 = [
  {
    text: "Fly to...",
    onselect: () => {},
  },
  {
    text: "Sea of Tranquility",
    onselect: function () {
      removeRotation();
      scene.camera.flyTo(seaOfTranquility);
      artemis3Source.show = false;
    },
  },
  {
    text: "Apollo 11 Landing Site",
    onselect: () => {
      removeRotation();
      scene.camera.flyTo(apollo11);
      artemis3Source.show = false;
    },
  },
  {
    text: "Copernicus Crater",
    onselect: () => {
      removeRotation();
      scene.camera.flyTo(copernicus);
      artemis3Source.show = false;
    },
  },
  {
    text: "Tycho Crater",
    onselect: () => {
      removeRotation();
      scene.camera.flyTo(tycho);
      artemis3Source.show = false;
    },
  },
  {
    text: "Shackleton Crater (South Pole) and Artemis 3 landing options",
    onselect: () => {
      removeRotation();
      scene.camera.flyTo(shackleton);
      artemis3Source.show = true;
    },
  },
];
Sandcastle.addToolbarMenu(options1);

Sandcastle.addToggleButton("Show Mare Boundaries", false, function (checked) {
  boundarySource.show = checked;
});

// Spin the moon on first load but disable the spinning upon any input
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(
  () => removeRotation(),
  Cesium.ScreenSpaceEventType.LEFT_DOWN,
);
handler.setInputAction(
  () => removeRotation(),
  Cesium.ScreenSpaceEventType.RIGHT_DOWN,
);
handler.setInputAction(
  () => removeRotation(),
  Cesium.ScreenSpaceEventType.MIDDLE_DOWN,
);
handler.setInputAction(
  () => removeRotation(),
  Cesium.ScreenSpaceEventType.WHEEL,
);
