<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Waste Simulation (Cesium)</title>
  <link
    rel="stylesheet"
    href="https://cesium.com/downloads/cesiumjs/releases/1.114/Build/Cesium/Widgets/widgets.css"
  />
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.114/Build/Cesium/Cesium.js"></script>
  <style>
    html, body, #cesiumContainer {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
      background: #0b0f1a;
    }
    #toolbar {
      position: absolute;
      top: 12px;
      left: 12px;
      z-index: 10;
      background: rgba(0, 0, 0, 0.65);
      color: #fff;
      padding: 12px 14px;
      border-radius: 8px;
      font-family: Arial, sans-serif;
      font-size: 13px;
      width: 320px;
    }
    #toolbar h4 {
      margin: 0 0 8px 0;
      font-size: 14px;
      font-weight: 600;
    }
    #toolbar .field {
      margin-top: 8px;
    }
    #toolbar .row {
      display: flex;
      justify-content: space-between;
      gap: 8px;
    }
    #toolbar .metric {
      display: flex;
      justify-content: space-between;
      padding: 2px 0;
    }
    #toolbar select {
      width: 100%;
    }
    .legend {
      display: flex;
      gap: 10px;
      flex-wrap: wrap;
      margin-top: 6px;
    }
    .legend span {
      display: inline-flex;
      align-items: center;
      gap: 6px;
    }
    .swatch {
      width: 10px;
      height: 10px;
      border-radius: 50%;
      display: inline-block;
    }
    .swatch.served { background: #50c878; }
    .swatch.missed-time { background: #ff5a5a; }
    .swatch.missed-capacity { background: #ffa63c; }
    .status {
      margin-top: 6px;
      color: #d0d7e2;
      font-size: 12px;
    }
  </style>
</head>
<body>
  <div id="toolbar">
    <h4>Waste Simulation (Cesium)</h4>
    <div class="field">
      <div>Subdivision: <span id="metaSubdivision"></span></div>
      <div>Vehicle: <span id="metaVehicle"></span></div>
    </div>
    <div class="field">
      <label for="basemap">Basemap</label>
      <select id="basemap">
        <option value="osm">OpenStreetMap</option>
        <option value="esri">ESRI World Imagery</option>
        <option value="carto_light">CARTO Light</option>
        <option value="carto_dark">CARTO Dark</option>
      </select>
    </div>
    <div class="field">
      <div class="metric"><span>Bins</span><span id="metricBins">-</span></div>
      <div class="metric"><span>Served</span><span id="metricServed">-</span></div>
      <div class="metric"><span>Missed (time)</span><span id="metricMissedTime">-</span></div>
      <div class="metric"><span>Missed (capacity)</span><span id="metricMissedCapacity">-</span></div>
      <div class="metric"><span>Route</span><span id="metricRoute">-</span></div>
    </div>
    <div class="field">
      <div class="metric"><span>Organic collected</span><span id="metricOrganic">-</span></div>
      <div class="metric"><span>Recyclable collected</span><span id="metricRecyclable">-</span></div>
      <div class="metric"><span>Landfill collected</span><span id="metricLandfill">-</span></div>
    </div>
    <div class="field legend">
      <span><i class="swatch served"></i>Served</span>
      <span><i class="swatch missed-time"></i>Missed time</span>
      <span><i class="swatch missed-capacity"></i>Missed capacity</span>
    </div>
    <div id="status" class="status">Loading simulation...</div>
  </div>
  <div id="cesiumContainer"></div>

  <script>
    Cesium.Ion.defaultAccessToken = "{{ ion_token }}";

    const subdivision = "{{ subdivision }}";
    const vehicle = "{{ vehicle }}";
    document.getElementById("metaSubdivision").textContent = subdivision;
    document.getElementById("metaVehicle").textContent = vehicle;

    const viewer = new Cesium.Viewer("cesiumContainer", {
      imageryProvider: false,
      animation: true,
      timeline: true,
      baseLayerPicker: false,
      geocoder: false,
      homeButton: false,
      navigationHelpButton: false,
      sceneModePicker: false,
      infoBox: true,
      selectionIndicator: true,
      shouldAnimate: true,
    });

    const basemapSelect = document.getElementById("basemap");
    const basemapLayers = {};

    function getBasemapProvider(key) {
      if (key === "osm") {
        return new Cesium.OpenStreetMapImageryProvider({
          url: "https://tile.openstreetmap.org/",
        });
      }
      if (key === "esri") {
        return new Cesium.UrlTemplateImageryProvider({
          url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
          credit: "Esri",
        });
      }
      if (key === "carto_light") {
        return new Cesium.UrlTemplateImageryProvider({
          url: "https://cartodb-basemaps-a.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png",
          credit: "CARTO",
        });
      }
      if (key === "carto_dark") {
        return new Cesium.UrlTemplateImageryProvider({
          url: "https://cartodb-basemaps-a.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png",
          credit: "CARTO",
        });
      }
      return null;
    }

    function setBaseLayer(key) {
      let layer = basemapLayers[key];
      if (!layer) {
        const provider = getBasemapProvider(key);
        if (!provider) {
          return;
        }
        layer = viewer.imageryLayers.addImageryProvider(provider);
        basemapLayers[key] = layer;
      }
      Object.keys(basemapLayers).forEach((k) => {
        basemapLayers[k].show = k === key;
      });
      viewer.imageryLayers.raiseToTop(layer);
    }

    basemapSelect.addEventListener("change", () => {
      setBaseLayer(basemapSelect.value);
    });
    setBaseLayer(basemapSelect.value);

    async function loadBuildings() {
      try {
        viewer.terrainProvider = await Cesium.createWorldTerrainAsync();
      } catch (err) {
        console.error("Failed to load terrain", err);
      }
      try {
        const osmBuildings = await Cesium.createOsmBuildingsAsync();
        viewer.scene.primitives.add(osmBuildings);
      } catch (err) {
        console.error("Failed to load OSM buildings", err);
      }
    }

    function updateMetrics(metrics) {
      if (!metrics) return;
      document.getElementById("metricBins").textContent = metrics.bins_total ?? "-";
      document.getElementById("metricServed").textContent = metrics.bins_served ?? "-";
      document.getElementById("metricMissedTime").textContent = metrics.bins_missed_time ?? "-";
      document.getElementById("metricMissedCapacity").textContent = metrics.bins_missed_capacity ?? "-";
      if (metrics.route_km != null && metrics.route_minutes != null) {
        document.getElementById("metricRoute").textContent = `${metrics.route_km} km / ${metrics.route_minutes} min`;
      }
      const waste = metrics.waste_collected || {};
      document.getElementById("metricOrganic").textContent = waste.organic != null ? waste.organic.toFixed(1) : "-";
      document.getElementById("metricRecyclable").textContent = waste.recyclable != null ? waste.recyclable.toFixed(1) : "-";
      document.getElementById("metricLandfill").textContent = waste.landfill != null ? waste.landfill.toFixed(1) : "-";
    }

    async function loadSimulation() {
      const statusEl = document.getElementById("status");
      statusEl.textContent = "Loading simulation...";
      try {
        const resp = await fetch(`/api/simulations/waste/cesium/${encodeURIComponent(subdivision)}/${encodeURIComponent(vehicle)}/`);
        const data = await resp.json();
        if (!resp.ok || data.ok === false) {
          throw new Error(data.message || "Failed to load simulation");
        }
        updateMetrics(data.metrics);
        const czml = data.czml || [];
        viewer.dataSources.removeAll();
        const dataSource = await Cesium.CzmlDataSource.load(czml);
        viewer.dataSources.add(dataSource);

        if (dataSource.clock) {
          viewer.clock.startTime = dataSource.clock.startTime.clone();
          viewer.clock.stopTime = dataSource.clock.stopTime.clone();
          viewer.clock.currentTime = dataSource.clock.currentTime.clone();
          viewer.clock.multiplier = dataSource.clock.multiplier || 10;
          viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
          viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime);
        }

        await viewer.flyTo(dataSource);
        statusEl.textContent = "Click bins to inspect waste and timing.";
      } catch (err) {
        console.error(err);
        statusEl.textContent = err.message || "Simulation failed.";
      }
    }

    loadBuildings();
    loadSimulation();
  </script>
</body>
</html>
