<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Mapbox + GeoServer WMS (Interactive GetFeatureInfo)</title>
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <link href="https://api.mapbox.com/mapbox-gl-js/v3.15.0/mapbox-gl.css" rel="stylesheet" />
  <style>
    body { margin:0; padding:0; font-family:Arial, sans-serif; }
    #map { position:absolute; top:0; bottom:0; width:100%; }
    #topbar {
      position: absolute; left: 10px; top: 10px; z-index: 20;
      background: rgba(255,255,255,0.95); padding: 8px 10px; border-radius: 8px;
      box-shadow: 0 2px 6px rgba(0,0,0,0.15); font-size: 13px;
    }
    #status { margin-top:6px; color:#555; font-size:12px; max-width:320px; }
    .btn { display:inline-block; padding:6px 8px; background:#2b7; color:#002; border-radius:6px; cursor:pointer; text-decoration:none; margin-left:6px; }
    .btn:active { transform:translateY(1px); }
    .mapboxgl-popup-content > div {
        height: 200px;
        overflow-y: auto;
    }
  </style>
</head>
<body>
  <div id="map"></div>
  <div id="topbar">
    <b>Mapbox + GeoServer WMS (rtrw_pr)</b>
    <div id="status">Klik peta untuk melihat atribut feature. Jika muncul error CORS, baca petunjuk di bawah.</div>
  </div>

  <script src="https://api.mapbox.com/mapbox-gl-js/v3.15.0/mapbox-gl.js"></script>
  <script>
    /**********************
     * CONFIG (ubah sesuai)
     **********************/
    const MAPBOX_TOKEN = 'pk.eyJ1IjoiaGFtZGFuZXJvciIsImEiOiJjbWdlaGNneGIwczJqMm5vZ2drNnR5ZWZyIn0.23-d0gCVPWyMfzZ0DssK-w'; // <-- ganti jika mau pakai Mapbox basemap (opsional)
    const GEOSERVER_WMS = 'http://103.236.151.68:8080/geoserver/katara/ows'; // basis endpoint
    const LAYER_NAME = 'katara:rtrw_pr'; // layer full name
    // optional style name: 'rtrw_kaltara_full_generated' (sesuaikan jika mau pakai style tertentu)
    const STYLE_NAME = ''; // biarkan string kosong untuk default style

    /***************************
     * END CONFIG
     ***************************/

    // gunakan token kalau ada
    if (MAPBOX_TOKEN && MAPBOX_TOKEN !== '') {
      mapboxgl.accessToken = MAPBOX_TOKEN;
    } else {
      // kosongkan access token agar Mapbox menolak tile load jika style membutuhkan token.
      // Kita nanti pakai style object sederhana yang tidak memerlukan Mapbox tiles jika token kosong.
      mapboxgl.accessToken = undefined;
    }

    // Build Mapbox style object — memakai hanya satu raster source (WMS) supaya mudah dipakai tanpa token
    const mapStyle = {
      version: 8,
      sources: {
        'geoserver-wms': {
          type: 'raster',
          tiles: [
            // WMS 1.3.0 + CRS=EPSG:4326 — Mapbox placeholder {bbox-epsg-4326} akan diisi
            `${GEOSERVER_WMS}?service=WMS&version=1.3.0&request=GetMap&layers=${LAYER_NAME}&styles=${STYLE_NAME}&format=image/png&transparent=true&SRS=EPSG:3857&width=256&height=256&bbox={bbox-epsg-3857}`
          ],
          tileSize: 256
        }
      },
      layers: [
        {
          id: 'wms-raster',
          type: 'raster',
          source: 'geoserver-wms',
          paint: {}
        }
      ]
    };

    // create map
    const map = new mapboxgl.Map({
      container: 'map',
      projection: 'globe',
       style: {
            version: 8,
            sources: {
                'osm-s':{
                type: 'raster',
                tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'],
                tileSize: 256
            }
            },
            layers: [{
            id: 'osm-base',
            type: 'raster',
            source: 'osm-s'
            }]
        },
      center: [116.3, 3.0], // reasonable center for Kaltara; ubah sesuai kebutuhan
      zoom: 7
    });

    // Status helper
    const status = document.getElementById('status');
    function setStatus(msg, isError = false) {
      status.textContent = msg;
      status.style.color = isError ? '#a00' : '#333';
    }

    map.on('load', () => {
        map.addSource('geoserver-wms', {
            type: 'raster',
            tiles: [
            // WMS 1.3.0 + CRS=EPSG:4326 — Mapbox placeholder {bbox-epsg-4326} akan diisi
            `${GEOSERVER_WMS}?service=WMS&version=1.3.0&request=GetMap&layers=${LAYER_NAME}&styles=${STYLE_NAME}&format=image/png&transparent=true&SRS=EPSG:3857&width=256&height=256&bbox={bbox-epsg-3857}`
            ],
            tileSize: 256
        });

        map.addLayer({
            id: 'geoserver-wms-layer',
            type: 'raster',
            source: 'geoserver-wms',
            paint: { 'raster-opacity': 0.85 }
        });
      setStatus('Peta siap. Klik area layer untuk melihat atribut.');
    });

    // Helper: build GetFeatureInfo URL for WMS 1.3.0 using CRS=EPSG:4326
    function buildGetFeatureInfoUrl(clickLngLat) {
      // Note: WMS 1.3.0 + EPSG:4326 uses axis order lat,lon for BBOX:
      // BBOX = minlat,minlon,maxlat,maxlon
      const bounds = map.getBounds();
      const sw = bounds.getSouthWest(); // {lng, lat}
      const ne = bounds.getNorthEast();

      // minlat, minlon, maxlat, maxlon
      const bbox = `${sw.lat},${sw.lng},${ne.lat},${ne.lng}`;

      const width = map.getCanvas().width;
      const height = map.getCanvas().height;
      const p = map.project(clickLngLat); // pixel coords relative container
      const i = Math.round(p.x);
      const j = Math.round(p.y);

      const params = new URLSearchParams({
        service: 'WMS',
        version: '1.3.0',
        request: 'GetFeatureInfo',
        layers: LAYER_NAME,
        query_layers: LAYER_NAME,
        styles: STYLE_NAME || '',
        CRS: 'EPSG:4326',
        bbox: bbox,
        width: String(width),
        height: String(height),
        I: String(i),
        J: String(j),
        info_format: 'application/json' // GeoServer supports application/json per GetCapabilities
      });

      return `${GEOSERVER_WMS}?${params.toString()}`;
    }

    // Click handler: request GetFeatureInfo, show Popup
    map.on('click', (e) => {
      setStatus('Meminta atribut...');

      const url = buildGetFeatureInfoUrl(e.lngLat);
      console.log('GetFeatureInfo URL:', url);

      fetch(url)
        .then(async (res) => {
          if (!res.ok) {
            const text = await res.text().catch(()=>null);
            throw new Error(`HTTP ${res.status} ${res.statusText} ${text ? ' - ' + text : ''}`);
          }
          // parse JSON (info_format=application/json)
          return res.json();
        })
        .then((geojson) => {
          if (!geojson || !geojson.features || geojson.features.length === 0) {
            setStatus('Tidak ada fitur di lokasi ini.');
            return;
          }

          // build html content from feature properties (first feature)
          const feat = geojson.features[0];
          const props = feat.properties || {};
          const rows = Object.entries(props).map(([k,v]) => {
            return `<div style="margin:2px 0"><b>${escapeHtml(k)}:</b> ${escapeHtml(String(v))}</div>`;
          }).join('');

          // show as Mapbox popup
          new mapboxgl.Popup({ closeButton:true, closeOnClick:true })
            .setLngLat(e.lngLat)
            .setHTML(`<div style="max-width:320px">${rows}</div>`)
            .addTo(map);

          setStatus('Menampilkan atribut (popup).');
        })
        .catch(err => {
          console.error(err);
          // Likely CORS or network error
          setStatus('Gagal mengambil atribut. Periksa CORS (Access-Control-Allow-Origin) dan koneksi ke GeoServer.', true);
          alert('GetFeatureInfo error:\n' + err.message + '\n\nJika ini CORS, aktifkan header Access-Control-Allow-Origin di GeoServer atau gunakan proxy.');
        });
    });

    // helper to escape HTML (simple)
    function escapeHtml(s) {
      return s.replace(/[&<>"'`]/g, function (m) {
        return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;', '`':'&#96;'}[m];
      });
    }

    // pointer cursor
    map.on('mouseenter', () => map.getCanvas().style.cursor = 'crosshair');
    map.on('mouseleave', () => map.getCanvas().style.cursor = '');

  </script>
</body>
</html>
