// Attach cluster-click + cursor handlers to a "-clusters" layer.
// Auto-branches on source capability:
//   - live-clustered GeoJSON  -> await source.getClusterExpansionZoom()
//   - precomputed vector tiles -> easeTo with zoom + 2
// Idempotent: handler refs are stored per layer id so remove_layer can
// tear them down, and re-calling attach on the same layer is a no-op.
function _mapglAttachClusterHandlers(map, layerId, sourceId) {
  if (!map._mapglClusterHandlers) map._mapglClusterHandlers = {};
  if (map._mapglClusterHandlers[layerId]) return;

  const click = async (e) => {
    const features = map.queryRenderedFeatures(e.point, {
      layers: [layerId],
    });
    if (!features.length) return;
    const feature = features[0];
    const source = map.getSource(sourceId);

    if (source && typeof source.getClusterExpansionZoom === "function") {
      // Native live-clustered GeoJSON source (MapLibre v5: Promise API).
      try {
        const clusterId = feature.properties.cluster_id;
        const zoom = await source.getClusterExpansionZoom(clusterId);
        map.easeTo({ center: feature.geometry.coordinates, zoom });
      } catch (err) {
        /* swallow: nothing to do if expansion zoom fails */
      }
    } else {
      // Pre-clustered vector tiles: no source-side cluster tree, so
      // step the zoom up by one. Tiles re-cluster at every level, so
      // +2 would traverse an intermediate level mid-ease and flash a
      // second regrouping — +1 gives a clean single break-apart.
      map.easeTo({
        center: feature.geometry.coordinates,
        zoom: Math.min(map.getZoom() + 1, 20),
      });
    }
  };
  const mouseenter = () => {
    map.getCanvas().style.cursor = "pointer";
  };
  const mouseleave = () => {
    map.getCanvas().style.cursor = "";
  };

  map.on("click", layerId, click);
  map.on("mouseenter", layerId, mouseenter);
  map.on("mouseleave", layerId, mouseleave);
  map._mapglClusterHandlers[layerId] = { click, mouseenter, mouseleave };
}

function _mapglDetachClusterHandlers(map, layerId) {
  if (!map._mapglClusterHandlers || !map._mapglClusterHandlers[layerId]) return;
  const h = map._mapglClusterHandlers[layerId];
  map.off("click", layerId, h.click);
  map.off("mouseenter", layerId, h.mouseenter);
  map.off("mouseleave", layerId, h.mouseleave);
  delete map._mapglClusterHandlers[layerId];
}

function _mapglPostDrawnFeatures(syncUrl, mapglId, features) {
  if (!syncUrl || !mapglId || typeof fetch !== "function") return;

  fetch(syncUrl, {
    method: "POST",
    body: JSON.stringify(features),
  }).catch((e) => {
    if (typeof console !== "undefined" && console.debug) {
      console.debug("mapgl draw sync failed", e);
    }
  });
}

function _mapglSyncDrawnFeatures(options) {
  const drawControl = options.drawControl;
  if (!drawControl) return;

  const drawnFeatures = drawControl.getAll();
  const widget = options.widget;

  if (HTMLWidgets.shinyMode && typeof Shiny !== "undefined") {
    Shiny.setInputValue(options.inputId + "_drawn_features", drawnFeatures, {
      priority: "event",
    });
  } else if (options.syncUrl && options.mapglId) {
    if (options.debounce && widget) {
      clearTimeout(widget._mapglDrawSyncTimer);
      widget._mapglDrawSyncTimer = setTimeout(() => {
        _mapglPostDrawnFeatures(
          options.syncUrl,
          options.mapglId,
          drawnFeatures,
        );
      }, 150);
    } else {
      _mapglPostDrawnFeatures(options.syncUrl, options.mapglId, drawnFeatures);
    }
  }

  if (widget) {
    widget.drawFeatures = drawnFeatures;
  }
}

function _mapglHasDrawAttributes(attributes) {
  return Array.isArray(attributes) && attributes.length > 0;
}

function _mapglAttributeDefaultValue(field) {
  if (Object.prototype.hasOwnProperty.call(field, "default")) {
    return field.default;
  }
  return undefined;
}

function _mapglEnsureDrawAttributeStyles() {
  if (document.querySelector("#mapgl-draw-attribute-editor-styles")) return;

  const style = document.createElement("style");
  style.id = "mapgl-draw-attribute-editor-styles";
  style.textContent = `
    .mapgl-draw-attribute-editor {
      position: absolute;
      z-index: 2;
      width: 260px;
      max-width: calc(100% - 20px);
      background: #ffffff;
      border-radius: 4px;
      box-shadow: 0 1px 4px rgba(0,0,0,0.28);
      color: #222;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
      font-size: 12px;
      display: none;
      overflow: hidden;
    }
    .mapgl-draw-attribute-editor.mapgl-draw-attribute-editor-visible {
      display: block;
    }
    .mapgl-draw-attribute-editor-header {
      padding: 9px 10px;
      border-bottom: 1px solid #e2e2e2;
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.02em;
      text-transform: uppercase;
    }
    .mapgl-draw-attribute-editor-body {
      padding: 10px;
    }
    .mapgl-draw-attribute-field {
      margin-bottom: 10px;
    }
    .mapgl-draw-attribute-field label {
      display: block;
      margin-bottom: 4px;
      font-weight: 600;
    }
    .mapgl-draw-attribute-field input,
    .mapgl-draw-attribute-field select,
    .mapgl-draw-attribute-field textarea {
      box-sizing: border-box;
      width: 100%;
      border: 1px solid #cfcfcf;
      border-radius: 3px;
      padding: 6px 7px;
      font: inherit;
    }
    .mapgl-draw-attribute-field input[type="checkbox"] {
      width: auto;
      margin-right: 6px;
    }
    .mapgl-draw-attribute-checkbox-label {
      display: flex !important;
      align-items: center;
      gap: 4px;
      margin-bottom: 0 !important;
    }
    .mapgl-draw-attribute-actions {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 8px;
      padding-top: 2px;
    }
    .mapgl-draw-attribute-save {
      border: 0;
      border-radius: 3px;
      background: #1f2937;
      color: #fff;
      cursor: pointer;
      font: inherit;
      font-weight: 600;
      padding: 6px 10px;
    }
    .mapgl-draw-attribute-message {
      color: #666;
      font-size: 11px;
    }
  `;
  document.head.appendChild(style);
}

function _mapglEditorPositionStyle(position) {
  const style = {};
  const vertical = position && position.indexOf("bottom") !== -1 ? "bottom" : "top";
  const horizontal = position && position.indexOf("right") !== -1 ? "left" : "right";
  style[vertical] = "10px";
  style[horizontal] = "10px";
  return style;
}

function _mapglApplyStyle(element, style) {
  Object.keys(style).forEach((key) => {
    element.style[key] = style[key];
  });
}

function formatDmsCoordinate(value, axis, precision) {
  const direction =
    axis === "lng" ? (value < 0 ? "W" : "E") : value < 0 ? "S" : "N";
  const absolute = Math.abs(value);
  let degrees = Math.floor(absolute);
  const minutesFloat = (absolute - degrees) * 60;
  let minutes = Math.floor(minutesFloat);
  let seconds = (minutesFloat - minutes) * 60;

  const factor = Math.pow(10, precision);
  seconds = Math.round(seconds * factor) / factor;
  if (seconds >= 60) {
    seconds = 0;
    minutes += 1;
  }
  if (minutes >= 60) {
    minutes = 0;
    degrees += 1;
  }

  const secondsText = seconds
    .toFixed(precision)
    .padStart(precision > 0 ? precision + 3 : 2, "0");
  return `${degrees}\u00b0${String(minutes).padStart(2, "0")}'${secondsText}"${direction}`;
}

function formatCoordinates(lngLat, format, precision) {
  if (format === "dms") {
    return `${formatDmsCoordinate(lngLat.lng, "lng", precision)}, ${formatDmsCoordinate(lngLat.lat, "lat", precision)}`;
  }
  return `${lngLat.lng.toFixed(precision)}, ${lngLat.lat.toFixed(precision)}`;
}

function createCoordinatesControl(options) {
  const controlOptions = options || {};
  const format = controlOptions.format || "decimal";
  const precisionValue = Number(controlOptions.precision);
  const precision = Number.isFinite(precisionValue)
    ? Math.min(20, Math.max(0, Math.floor(precisionValue)))
    : format === "dms" ? 1 : 5;
  const emptyText = controlOptions.empty_text || "Move cursor over map";
  const labelText = controlOptions.label || "";
  const wrapLongitude = controlOptions.wrap !== false;

  const container = document.createElement("div");
  container.className = "mapgl-coordinates-control maplibregl-ctrl";
  container.style.cssText = `
    background: #ffffff;
    padding: 8px 10px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
    color: #222;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 12px;
    line-height: 1.35;
    min-width: 142px;
    max-width: 240px;
    border: 1px solid rgba(0,0,0,0.1);
    pointer-events: none;
  `;

  if (labelText) {
    const label = document.createElement("div");
    label.className = "mapgl-coordinates-label";
    label.textContent = labelText;
    label.style.cssText = `
      margin-bottom: 2px;
      color: #666;
      font-size: 11px;
      font-weight: 600;
      letter-spacing: 0.02em;
      text-transform: uppercase;
    `;
    container.appendChild(label);
  }

  const value = document.createElement("div");
  value.className = "mapgl-coordinates-value";
  value.textContent = emptyText;
  value.style.cssText = `
    color: #111;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  `;
  container.appendChild(value);

  let mapRef = null;
  const update = (event) => {
    if (!event || !event.lngLat) return;
    const lngLat =
      wrapLongitude && typeof event.lngLat.wrap === "function"
        ? event.lngLat.wrap()
        : event.lngLat;
    value.textContent = formatCoordinates(lngLat, format, precision);
  };
  const clear = () => {
    value.textContent = emptyText;
  };

  return {
    onAdd: function (map) {
      mapRef = map;
      mapRef.on("mousemove", update);
      mapRef.getCanvas().addEventListener("mouseleave", clear);
      return container;
    },
    onRemove: function () {
      if (mapRef) {
        mapRef.off("mousemove", update);
        mapRef.getCanvas().removeEventListener("mouseleave", clear);
      }
      if (container.parentNode) {
        container.parentNode.removeChild(container);
      }
      mapRef = null;
    },
  };
}

function _mapglCurrentFieldValue(feature, field) {
  const properties = (feature && feature.properties) || {};
  if (Object.prototype.hasOwnProperty.call(properties, field.name)) {
    return properties[field.name];
  }
  const defaultValue = _mapglAttributeDefaultValue(field);
  if (defaultValue !== undefined) {
    return defaultValue;
  }
  return field.type === "checkbox" ? false : "";
}

function _mapglApplyAttributeDefaults(drawControl, feature, attributes) {
  const featureId = feature && feature.id;
  if (!featureId) return;

  const properties = feature.properties || {};
  attributes.forEach((field) => {
    if (Object.prototype.hasOwnProperty.call(properties, field.name)) return;
    const defaultValue = _mapglAttributeDefaultValue(field);
    if (defaultValue !== undefined) {
      drawControl.setFeatureProperty(featureId, field.name, defaultValue);
    }
  });
}

function _mapglCreateAttributeInput(field, value) {
  let input;

  if (field.type === "textarea") {
    input = document.createElement("textarea");
    input.rows = 3;
    input.value = value == null ? "" : value;
  } else if (field.type === "select") {
    input = document.createElement("select");
    const emptyOption = document.createElement("option");
    emptyOption.value = "";
    emptyOption.textContent = "";
    input.appendChild(emptyOption);
    (field.choices || []).forEach((choice, index) => {
      const option = document.createElement("option");
      option.value = String(index);
      option.textContent = choice.label == null ? String(choice.value) : choice.label;
      option.dataset.mapglValue = JSON.stringify(choice.value);
      if (value === choice.value || String(value) === String(choice.value)) {
        option.selected = true;
      }
      input.appendChild(option);
    });
  } else if (field.type === "number") {
    input = document.createElement("input");
    input.type = "number";
    input.value = value == null ? "" : value;
    ["min", "max", "step"].forEach((key) => {
      if (Object.prototype.hasOwnProperty.call(field, key)) {
        input.setAttribute(key, field[key]);
      }
    });
  } else if (field.type === "checkbox") {
    input = document.createElement("input");
    input.type = "checkbox";
    input.checked = value === true || value === "true" || value === 1;
  } else {
    input = document.createElement("input");
    input.type = "text";
    input.value = value == null ? "" : value;
  }

  if (field.placeholder && field.type !== "select" && field.type !== "checkbox") {
    input.placeholder = field.placeholder;
  }
  if (field.required) {
    input.required = true;
  }
  input.dataset.fieldName = field.name;
  input.dataset.fieldType = field.type;
  return input;
}

function _mapglInputValue(input, field) {
  if (field.type === "checkbox") {
    return input.checked;
  }
  if (field.type === "number") {
    return input.value === "" ? null : Number(input.value);
  }
  if (field.type === "select") {
    if (input.value === "") return null;
    const selected = input.options[input.selectedIndex];
    return selected && selected.dataset.mapglValue
      ? JSON.parse(selected.dataset.mapglValue)
      : input.value;
  }
  return input.value;
}

function initializeDrawAttributeEditor(map, drawControl, options) {
  const attributes = options.attributes || [];
  if (!_mapglHasDrawAttributes(attributes)) return null;

  _mapglEnsureDrawAttributeStyles();

  const container = document.createElement("div");
  container.className = "mapgl-draw-attribute-editor";
  _mapglApplyStyle(container, _mapglEditorPositionStyle(options.position));

  const header = document.createElement("div");
  header.className = "mapgl-draw-attribute-editor-header";
  header.textContent = "Feature attributes";

  const body = document.createElement("form");
  body.className = "mapgl-draw-attribute-editor-body";

  container.appendChild(header);
  container.appendChild(body);
  map.getContainer().appendChild(container);

  let selectedFeatureId = null;

  const hide = () => {
    selectedFeatureId = null;
    container.classList.remove("mapgl-draw-attribute-editor-visible");
    body.innerHTML = "";
  };

  const show = (feature) => {
    selectedFeatureId = feature && feature.id;
    if (!selectedFeatureId) {
      hide();
      return;
    }

    const currentFeature = drawControl.get(selectedFeatureId) || feature;
    body.innerHTML = "";

    attributes.forEach((field) => {
      const value = _mapglCurrentFieldValue(currentFeature, field);
      const wrapper = document.createElement("div");
      wrapper.className = "mapgl-draw-attribute-field";
      const input = _mapglCreateAttributeInput(field, value);

      if (field.type === "checkbox") {
        const label = document.createElement("label");
        label.className = "mapgl-draw-attribute-checkbox-label";
        label.appendChild(input);
        label.appendChild(document.createTextNode(field.label || field.name));
        wrapper.appendChild(label);
      } else {
        const label = document.createElement("label");
        label.textContent = field.label || field.name;
        wrapper.appendChild(label);
        wrapper.appendChild(input);
      }

      body.appendChild(wrapper);
    });

    const actions = document.createElement("div");
    actions.className = "mapgl-draw-attribute-actions";

    const save = document.createElement("button");
    save.type = "submit";
    save.className = "mapgl-draw-attribute-save";
    save.textContent = "Save";

    const message = document.createElement("span");
    message.className = "mapgl-draw-attribute-message";

    actions.appendChild(save);
    actions.appendChild(message);
    body.appendChild(actions);
    container.classList.add("mapgl-draw-attribute-editor-visible");
  };

  body.addEventListener("submit", (e) => {
    e.preventDefault();
    if (!selectedFeatureId) return;
    if (typeof body.reportValidity === "function" && !body.reportValidity()) {
      return;
    }

    attributes.forEach((field) => {
      const input = Array.from(
        body.querySelectorAll("[data-field-name]"),
      ).find((element) => element.dataset.fieldName === field.name);
      if (!input) return;
      drawControl.setFeatureProperty(
        selectedFeatureId,
        field.name,
        _mapglInputValue(input, field),
      );
    });

    const message = body.querySelector(".mapgl-draw-attribute-message");
    if (message) {
      message.textContent = "Saved";
      setTimeout(() => {
        message.textContent = "";
      }, 1200);
    }

    if (typeof options.onChange === "function") {
      options.onChange(false);
    }
  });

  map.on("draw.create", (e) => {
    if (e.features) {
      e.features.forEach((feature) => {
        _mapglApplyAttributeDefaults(drawControl, feature, attributes);
      });
    }
    if (e.features && e.features.length === 1) {
      show(e.features[0]);
    }
  });

  map.on("draw.selectionchange", (e) => {
    if (e.features && e.features.length === 1) {
      show(e.features[0]);
    } else {
      hide();
    }
  });

  map.on("draw.delete", hide);

  return {
    hide: hide,
    show: show,
  };
}

// Shared layer-state and filter-composition helpers. See the twin block
// in mapboxgl.js for the design notes.
function _mapglEnsureLayerState(map) {
  if (!window._mapglLayerState) window._mapglLayerState = {};
  const mapId = map.getContainer().id;
  const s =
    window._mapglLayerState[mapId] ||
    (window._mapglLayerState[mapId] = {});
  if (!s.filters) s.filters = {};
  if (!s.paintProperties) s.paintProperties = {};
  if (!s.layoutProperties) s.layoutProperties = {};
  if (!s.tooltips) s.tooltips = {};
  if (!s.popups) s.popups = {};
  // Parallel maps holding the (optional) tooltip/popup style spec for proxy
  // set_tooltip()/set_popup() so theming survives a style reload.
  if (!s.tooltipStyles) s.tooltipStyles = {};
  if (!s.popupStyles) s.popupStyles = {};
  if (!s.legends) s.legends = {};
  if (!s.interactiveFilters) s.interactiveFilters = {};
  if (!s.filterStack) s.filterStack = {};
  return s;
}

function _mapglComposeAndApplyFilter(map, layerId) {
  const state = _mapglEnsureLayerState(map);
  const stack = state.filterStack[layerId] || {};
  const active = [stack.base, stack.user, stack.legend, stack.slider].filter(
    (f) => f != null,
  );
  const composed =
    active.length === 0 ? null : active.length === 1 ? active[0] : ["all", ...active];
  if (map.getLayer && map.getLayer(layerId)) {
    map.setFilter(layerId, composed);
  }
  state.filters[layerId] = composed;
}

window._mapglEnsureLayerState = _mapglEnsureLayerState;
window._mapglComposeFilter = _mapglComposeAndApplyFilter;

// Measurement functionality
function createMeasurementBox(map) {
  const box = document.createElement("div");
  box.id = `measurement-box-${map._container.id}`;
  box.className = "mapgl-measurement-box";
  box.style.cssText = `
    position: absolute;
    bottom: 45px;
    left: 10px;
    background: white;
    padding: 10px 15px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 12px;
    line-height: 1.4;
    z-index: 1;
    display: none;
    min-width: 120px;
    max-width: 200px;
    border: 1px solid rgba(0,0,0,0.1);
  `;

  box.innerHTML = `
    <div style="font-weight: 600; margin-bottom: 5px; color: #333; font-size: 11px; text-transform: uppercase;">
      Measurement
    </div>
    <div class="measurement-content">
      <div id="measurement-primary" style="font-size: 14px; font-weight: 500; color: #000; margin-bottom: 2px;"></div>
      <div id="measurement-secondary" style="font-size: 11px; color: #666;"></div>
    </div>
  `;

  map.getContainer().appendChild(box);
  return box;
}

function calculateDrawingMeasurements(mode, state, coords) {
  try {
    if (mode === "draw_line_string" && coords && coords.length >= 2) {
      const line = turf.lineString(coords);
      const distance = turf.length(line, { units: "kilometers" });
      return { type: "distance", value: distance };
    } else if (
      (mode === "draw_polygon" || mode === "draw_freehand") &&
      coords &&
      coords.length >= 3
    ) {
      // Ensure polygon is closed by adding first point at end if needed
      const closedCoords = [...coords];
      if (
        closedCoords[0][0] !== closedCoords[closedCoords.length - 1][0] ||
        closedCoords[0][1] !== closedCoords[closedCoords.length - 1][1]
      ) {
        closedCoords.push(closedCoords[0]);
      }

      try {
        const polygon = turf.polygon([closedCoords]);
        const area = turf.area(polygon) / 1000000; // Convert to km²
        const perimeter = turf.length(turf.polygonToLine(polygon), {
          units: "kilometers",
        });
        return { type: "area", value: area, perimeter: perimeter };
      } catch (error) {
        return null;
      }
    } else if (mode === "draw_rectangle" && coords && coords.length >= 4) {
      const polygon = turf.polygon([coords]);
      const area = turf.area(polygon) / 1000000; // Convert to km²
      const perimeter = turf.length(turf.polygonToLine(polygon), {
        units: "kilometers",
      });
      return { type: "area", value: area, perimeter: perimeter };
    } else if (mode === "draw_radius" && coords && coords.length >= 2) {
      const center = turf.point(coords[0]);
      const edge = turf.point(coords[1]);
      const radius = turf.distance(center, edge, { units: "kilometers" });
      const area = Math.PI * radius * radius; // πr²
      return { type: "radius", value: radius, area: area };
    }
  } catch (e) {
    return null;
  }

  return null;
}

function formatMeasurements(measurements, units) {
  if (!measurements) return { primary: "", secondary: "" };

  const formatDistance = function (km) {
    let result = [];

    if (units === "metric" || units === "both") {
      if (km < 1) {
        result.push(`${(km * 1000).toFixed(0)} m`);
      } else {
        result.push(`${km.toFixed(2)} km`);
      }
    }

    if (units === "imperial" || units === "both") {
      const miles = km * 0.621371;
      if (miles < 0.1) {
        result.push(`${(miles * 5280).toFixed(0)} ft`);
      } else {
        result.push(`${miles.toFixed(2)} mi`);
      }
    }

    return result;
  };

  const formatArea = function (sqKm) {
    let result = [];

    if (units === "metric" || units === "both") {
      if (sqKm < 0.01) {
        result.push(`${(sqKm * 1000000).toFixed(0)} m²`);
      } else if (sqKm < 1) {
        result.push(`${(sqKm * 100).toFixed(2)} ha`);
      } else {
        result.push(`${sqKm.toFixed(2)} km²`);
      }
    }

    if (units === "imperial" || units === "both") {
      const sqMiles = sqKm * 0.386102;
      if (sqMiles < 0.001) {
        result.push(`${(sqMiles * 640).toFixed(2)} acres`);
      } else {
        result.push(`${sqMiles.toFixed(3)} mi²`);
      }
    }

    return result;
  };

  if (measurements.type === "distance") {
    const formatted = formatDistance(measurements.value);
    return {
      primary: formatted[0] || "",
      secondary: formatted[1] || "",
    };
  } else if (measurements.type === "area") {
    const areaFormatted = formatArea(measurements.value);
    const perimeterFormatted = formatDistance(measurements.perimeter);

    if (units === "both") {
      return {
        primary: areaFormatted[0] || "",
        secondary: `${areaFormatted[1] || ""} • ${perimeterFormatted[0] || ""}`,
      };
    } else {
      return {
        primary: areaFormatted[0] || "",
        secondary: `Perimeter: ${perimeterFormatted[0] || ""}`,
      };
    }
  } else if (measurements.type === "radius") {
    const distFormatted = formatDistance(measurements.value);
    const areaFormatted = formatArea(measurements.area);

    return {
      primary: `Radius: ${distFormatted[0] || ""}`,
      secondary:
        units === "both"
          ? `${distFormatted[1] || ""} • ${areaFormatted[0] || ""}`
          : `Area: ${areaFormatted[0] || ""}`,
    };
  }

  return { primary: "", secondary: "" };
}

function updateMeasurementDisplay(box, measurements, units) {
  const primary = box.querySelector("#measurement-primary");
  const secondary = box.querySelector("#measurement-secondary");

  const formatted = formatMeasurements(measurements, units);

  if (formatted.primary) {
    primary.textContent = formatted.primary;
    secondary.textContent = formatted.secondary;
    box.style.display = "block";
  } else {
    box.style.display = "none";
  }
}

function initializeMeasurements(map, draw, units) {
  const measurementBox = createMeasurementBox(map);
  const DRAWING_MODES = [
    "draw_line_string",
    "draw_polygon",
    "draw_rectangle",
    "draw_radius",
    "draw_freehand",
  ];

  // Store original handlers
  const originalHandlers = {};

  DRAWING_MODES.forEach((mode) => {
    const modeObj = MapboxDraw.modes[mode];
    if (!modeObj) return;

    // Wrap onClick for polygon mode (better for click-based drawing)
    if (modeObj.onClick && mode === "draw_polygon") {
      originalHandlers[mode + "_onClick"] = modeObj.onClick;
      modeObj.onClick = function (state, e) {
        const result = originalHandlers[mode + "_onClick"].call(this, state, e);

        // For polygon mode, show measurements after each click
        if (
          state.polygon &&
          state.polygon.coordinates &&
          state.polygon.coordinates[0].length >= 3
        ) {
          const coords = state.polygon.coordinates[0];
          const measurements = calculateDrawingMeasurements(
            mode,
            state,
            coords,
          );
          updateMeasurementDisplay(measurementBox, measurements, units);
        }

        return result;
      };
    }

    // Wrap onMouseMove for real-time updates (lines, rectangles, radius)
    if (modeObj.onMouseMove && mode !== "draw_polygon") {
      originalHandlers[mode + "_onMouseMove"] = modeObj.onMouseMove;
      modeObj.onMouseMove = function (state, e) {
        originalHandlers[mode + "_onMouseMove"].call(this, state, e);

        let coords = null;
        if (state.line && state.line.coordinates) {
          coords = [...state.line.coordinates, [e.lngLat.lng, e.lngLat.lat]];
        } else if (state.rectangle && state.rectangle.coordinates) {
          coords = state.rectangle.coordinates[0];
        }

        if (coords) {
          const measurements = calculateDrawingMeasurements(
            mode,
            state,
            coords,
          );
          updateMeasurementDisplay(measurementBox, measurements, units);
        }
      };
    }

    // Wrap onDrag for freehand mode
    if (modeObj.onDrag) {
      originalHandlers[mode + "_onDrag"] = modeObj.onDrag;
      modeObj.onDrag = function (state, e) {
        const result = originalHandlers[mode + "_onDrag"].call(this, state, e);

        if (state.polygon && state.polygon.coordinates) {
          const coords = state.polygon.coordinates[0];
          if (coords.length >= 3) {
            const measurements = calculateDrawingMeasurements(
              mode,
              state,
              coords,
            );
            updateMeasurementDisplay(measurementBox, measurements, units);
          }
        }

        return result;
      };
    }
  });

  // Hide measurement box when drawing stops and handle button states
  map.on("draw.modechange", (e) => {
    if (e.mode === "simple_select") {
      measurementBox.style.display = "none";
      // Reset button states when switching to select mode
      const drawControlGroup = map
        .getContainer()
        .querySelector(".maplibregl-ctrl-group");
      if (drawControlGroup) {
        drawControlGroup
          .querySelectorAll("button")
          .forEach((btn) => btn.classList.remove("active"));
      }
    }
  });

  map.on("draw.create", () => {
    measurementBox.style.display = "none";
    // Reset button states when drawing is completed
    const drawControlGroup = map
      .getContainer()
      .querySelector(".maplibregl-ctrl-group");
    if (drawControlGroup) {
      drawControlGroup
        .querySelectorAll("button")
        .forEach((btn) => btn.classList.remove("active"));
    }
  });

  map.on("draw.delete", () => {
    measurementBox.style.display = "none";
  });

  // Special handling for freehand mode using data update events
  map.on("draw.update", (e) => {
    const currentMode = draw.getMode();

    if (currentMode === "draw_freehand" && e.features && e.features[0]) {
      const feature = e.features[0];
      if (
        feature.geometry.type === "Polygon" &&
        feature.geometry.coordinates[0].length >= 3
      ) {
        const coords = feature.geometry.coordinates[0];
        const measurements = calculateDrawingMeasurements(
          "draw_freehand",
          {},
          coords,
        );
        updateMeasurementDisplay(measurementBox, measurements, units);
      }
    }

    // Also handle editing mode - when features are being edited
    if (currentMode === "direct_select" && e.features && e.features[0]) {
      const feature = e.features[0];
      if (
        feature.geometry.type === "Polygon" &&
        feature.geometry.coordinates[0].length >= 3
      ) {
        const coords = feature.geometry.coordinates[0];
        const measurements = calculateDrawingMeasurements(
          "draw_polygon",
          {},
          coords,
        );
        updateMeasurementDisplay(measurementBox, measurements, units);
      } else if (
        feature.geometry.type === "LineString" &&
        feature.geometry.coordinates.length >= 2
      ) {
        const coords = feature.geometry.coordinates;
        const measurements = calculateDrawingMeasurements(
          "draw_line_string",
          {},
          coords,
        );
        updateMeasurementDisplay(measurementBox, measurements, units);
      }
    }
  });

  // Show measurements when selecting features for editing
  map.on("draw.selectionchange", (e) => {
    if (e.features && e.features.length > 0) {
      const feature = e.features[0];
      if (
        feature.geometry.type === "Polygon" &&
        feature.geometry.coordinates[0].length >= 3
      ) {
        const coords = feature.geometry.coordinates[0];
        const measurements = calculateDrawingMeasurements(
          "draw_polygon",
          {},
          coords,
        );
        updateMeasurementDisplay(measurementBox, measurements, units);
      } else if (
        feature.geometry.type === "LineString" &&
        feature.geometry.coordinates.length >= 2
      ) {
        const coords = feature.geometry.coordinates;
        const measurements = calculateDrawingMeasurements(
          "draw_line_string",
          {},
          coords,
        );
        updateMeasurementDisplay(measurementBox, measurements, units);
      }
    } else {
      // No features selected, hide measurement box
      measurementBox.style.display = "none";
    }
  });
}

function evaluateExpression(expression, properties) {
  if (!Array.isArray(expression)) {
    return expression;
  }

  const operator = expression[0];

  switch (operator) {
    case "get":
      return properties[expression[1]];
    case "concat":
      return expression
        .slice(1)
        .map((item) => evaluateExpression(item, properties))
        .join("");
    case "to-string":
      return String(evaluateExpression(expression[1], properties));
    case "to-number":
      return Number(evaluateExpression(expression[1], properties));
    case "number-format":
      const value = evaluateExpression(expression[1], properties);
      const options = expression[2] || {};

      // Handle locale option
      const locale = options.locale || "en-US";

      // Build Intl.NumberFormat options
      const formatOptions = {};

      // Style options
      if (options.style) formatOptions.style = options.style; // 'decimal', 'currency', 'percent', 'unit'
      if (options.currency) formatOptions.currency = options.currency;
      if (options.unit) formatOptions.unit = options.unit;

      // Digit options
      if (options.hasOwnProperty("min-fraction-digits")) {
        formatOptions.minimumFractionDigits = options["min-fraction-digits"];
      }
      if (options.hasOwnProperty("max-fraction-digits")) {
        formatOptions.maximumFractionDigits = options["max-fraction-digits"];
      }
      if (options.hasOwnProperty("min-integer-digits")) {
        formatOptions.minimumIntegerDigits = options["min-integer-digits"];
      }

      // Notation options
      if (options.notation) formatOptions.notation = options.notation; // 'standard', 'scientific', 'engineering', 'compact'
      if (options.compactDisplay)
        formatOptions.compactDisplay = options.compactDisplay; // 'short', 'long'

      // Grouping
      if (options.hasOwnProperty("useGrouping")) {
        formatOptions.useGrouping = options.useGrouping;
      }

      return new Intl.NumberFormat(locale, formatOptions).format(value);
    default:
      // For literals and other simple values
      return expression;
  }
}

// Escape a value for safe insertion as tooltip/popup text. Used by the brace
// template renderer so substituted values cannot inject markup.
function escapeTemplateValue(value) {
  return String(value)
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
}

// Render a {brace} template against a properties object. Each {key} (dotted
// paths like {origin.id} supported) is replaced by the HTML-escaped value;
// literal text/markup in the template is emitted as-is. Shared, package-wide
// tooltip/popup syntax. NOTE: duplicated verbatim in mapboxgl.js,
// mapboxgl_compare.js, maplibregl_compare.js, and flowmap.js — keep in sync.
function renderTemplate(template, properties) {
  if (typeof template !== "string") {
    return template;
  }
  return template.replace(/\{([^}]+)\}/g, function (match, path) {
    const value = path
      .trim()
      .split(".")
      .reduce(function (acc, key) {
        return acc == null ? undefined : acc[key];
      }, properties);
    return value == null ? "" : escapeTemplateValue(value);
  });
}

// Resolve a tooltip/popup content spec against a feature's properties:
//   array  -> Mapbox-style expression (concat/number_format/get) via evaluateExpression
//   "{..}" -> brace template via renderTemplate
//   string -> a column name (direct property lookup)
function resolveTooltipContent(spec, properties) {
  if (Array.isArray(spec)) {
    return evaluateExpression(spec, properties);
  }
  if (typeof spec === "string" && spec.indexOf("{") !== -1) {
    return renderTemplate(spec, properties);
  }
  return properties[spec];
}

// Convert "#rgb"/"#rrggbb" + alpha to rgba(); pass other color strings through.
function tooltipHexToRgba(color, alpha) {
  if (typeof color !== "string" || color.charAt(0) !== "#") {
    return color;
  }
  let h = color.slice(1);
  if (h.length === 3) {
    h = h
      .split("")
      .map(function (c) {
        return c + c;
      })
      .join("");
  }
  const r = parseInt(h.slice(0, 2), 16);
  const g = parseInt(h.slice(2, 4), 16);
  const b = parseInt(h.slice(4, 6), 16);
  return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")";
}

// Build (and cache) a scoped CSS class from a tooltip/popup style spec. Returns
// null for an empty/absent spec (native appearance). One <style> per unique
// spec, shared via a window-level cache. NOTE: duplicated across the bindings
// and flowmap.js — keep in sync.
function tooltipStyleToClass(spec) {
  if (!spec || typeof spec !== "object") {
    return null;
  }
  if (!window._mapglTooltipStyleClasses) {
    window._mapglTooltipStyleClasses = {};
  }
  const cache = window._mapglTooltipStyleClasses;
  const key = JSON.stringify(spec);
  if (cache[key]) {
    return cache[key];
  }
  const cls = "mapgl-tooltip-style-" + (Object.keys(cache).length + 1);

  let bg = spec.background_color;
  if (bg != null && spec.background_opacity != null) {
    bg = tooltipHexToRgba(bg, spec.background_opacity);
  }

  const content = [];
  if (bg != null) content.push("background:" + bg + ";");
  if (spec.text_color != null) content.push("color:" + spec.text_color + ";");
  if (spec.border_color != null || spec.border_width != null) {
    const bw = spec.border_width == null ? 1 : spec.border_width;
    const bc = spec.border_color == null ? "transparent" : spec.border_color;
    content.push("border:" + bw + "px solid " + bc + ";");
  }
  if (spec.border_radius != null) {
    content.push("border-radius:" + spec.border_radius + "px;");
  }
  if (spec.font_family != null) {
    content.push("font-family:" + spec.font_family + ";");
  }
  if (spec.font_size != null) {
    content.push("font-size:" + spec.font_size + "px;");
  }
  if (spec.font_weight != null) {
    content.push("font-weight:" + spec.font_weight + ";");
  }
  if (spec.padding != null) content.push("padding:" + spec.padding + "px;");
  if (spec.max_width != null) {
    const mw =
      typeof spec.max_width === "number"
        ? spec.max_width + "px"
        : spec.max_width;
    content.push("max-width:" + mw + ";");
  }
  if (spec.shadow) {
    const ss = spec.shadow_size == null ? 8 : spec.shadow_size;
    const sc = spec.shadow_color == null ? "rgba(0, 0, 0, 0.2)" : spec.shadow_color;
    content.push("box-shadow:0 2px " + ss + "px " + sc + ";");
  }

  let css =
    "." +
    cls +
    " .mapboxgl-popup-content, ." +
    cls +
    " .maplibregl-popup-content {" +
    content.join("") +
    "}";
  if (bg != null) {
    css +=
      "." +
      cls +
      " .mapboxgl-popup-tip, ." +
      cls +
      " .maplibregl-popup-tip {border-top-color:" +
      bg +
      ";border-bottom-color:" +
      bg +
      ";}";
  }

  const styleEl = document.createElement("style");
  styleEl.textContent = css;
  document.head.appendChild(styleEl);
  cache[key] = cls;
  return cls;
}

// Apply a style spec's generated class to a popup. A tooltip's Popup is built
// lazily on addTo(), so its container does not exist at creation time and
// neither addClassName() nor (in Mapbox GL v3) a later options.className write
// reliably lands. Instead we (re)apply the class on every "open" event, when
// the container is guaranteed to exist — works for both Mapbox and MapLibre —
// and swap out any previously applied generated class so nothing accumulates.
function applyPopupClass(popup, spec) {
  if (!popup) {
    return;
  }
  const cls = tooltipStyleToClass(spec);
  const prev = popup._mapglStyleClass;
  if (popup._container && prev && prev !== cls) {
    popup._container.classList.remove(prev);
  }
  popup._mapglStyleClass = cls || null;
  if (popup._container && cls) {
    popup._container.classList.add(cls);
  }
  if (!popup._mapglClassHook && typeof popup.on === "function") {
    popup._mapglClassHook = true;
    popup.on("open", function () {
      if (popup._container && popup._mapglStyleClass) {
        popup._container.classList.add(popup._mapglStyleClass);
      }
    });
  }
}

function onMouseMoveTooltip(e, map, tooltipPopup, tooltipProperty, layerId) {
  if (e.features.length > 0) {
    // Query all features at this point to determine z-order
    // Features are returned in top-to-bottom rendering order
    const allFeatures = map.queryRenderedFeatures(e.point);

    // Find the topmost layer that has a tooltip
    let topmostLayerWithTooltip = null;
    for (let i = 0; i < allFeatures.length; i++) {
      const feature = allFeatures[i];
      const featureLayerId = feature.layer.id;

      // Check if this layer has a tooltip handler registered
      if (window._mapboxHandlers && window._mapboxHandlers[featureLayerId]) {
        topmostLayerWithTooltip = featureLayerId;
        break;
      }
    }

    // Only show tooltip if this is the topmost layer with a tooltip
    if (topmostLayerWithTooltip === layerId) {
      map.getCanvas().style.cursor = "pointer";

      // Clear any existing active tooltip first to prevent stacking
      if (window._activeTooltip && window._activeTooltip !== tooltipPopup) {
        window._activeTooltip.remove();
      }

      // tooltipProperty may be a column name, a {brace} template, or a
      // concat()/number_format() expression — resolveTooltipContent handles all.
      const description = resolveTooltipContent(
        tooltipProperty,
        e.features[0].properties,
      );

      tooltipPopup.setLngLat(e.lngLat).setHTML(description).addTo(map);

      // Store reference to currently active tooltip
      window._activeTooltip = tooltipPopup;
    } else {
      // This layer is not topmost, hide tooltip if it was showing
      tooltipPopup.remove();
      if (window._activeTooltip === tooltipPopup) {
        delete window._activeTooltip;
      }
    }
  } else {
    tooltipPopup.remove();
    // If this was the active tooltip, clear the reference
    if (window._activeTooltip === tooltipPopup) {
      delete window._activeTooltip;
    }
  }
}

function onMouseLeaveTooltip(map, tooltipPopup) {
  map.getCanvas().style.cursor = "";
  tooltipPopup.remove();
  if (window._activeTooltip === tooltipPopup) {
    delete window._activeTooltip;
  }
}

function onClickPopup(e, map, popupProperty, layerId, popupStyle) {
  if (e.features.length > 0) {
    // Query all features at this point to determine z-order
    const allFeatures = map.queryRenderedFeatures(e.point);

    // Find the topmost layer that has a popup
    let topmostLayerWithPopup = null;
    for (let i = 0; i < allFeatures.length; i++) {
      const feature = allFeatures[i];
      const featureLayerId = feature.layer.id;

      // Check if this layer has a popup handler registered
      if (
        window._mapboxClickHandlers &&
        window._mapboxClickHandlers[featureLayerId]
      ) {
        topmostLayerWithPopup = featureLayerId;
        break;
      }
    }

    // Only show popup if this is the topmost layer with a popup
    if (topmostLayerWithPopup === layerId) {
      // popupProperty may be a column name, a {brace} template, or a
      // concat()/number_format() expression.
      const description = resolveTooltipContent(
        popupProperty,
        e.features[0].properties,
      );

      // Remove any existing popup for this layer
      if (window._mapboxPopups && window._mapboxPopups[layerId]) {
        window._mapboxPopups[layerId].remove();
      }

      // Create and show the popup
      const popup = new maplibregl.Popup({ maxWidth: "400px" })
        .setLngLat(e.lngLat)
        .setHTML(description)
        .addTo(map);
      applyPopupClass(popup, popupStyle);

      // Store reference to this popup
      if (!window._mapboxPopups) {
        window._mapboxPopups = {};
      }
      window._mapboxPopups[layerId] = popup;

      // Remove reference when popup is closed
      popup.on("close", function () {
        if (window._mapboxPopups[layerId] === popup) {
          delete window._mapboxPopups[layerId];
        }
      });
    }
  }
}

// Helper function to generate draw styles based on parameters
function generateDrawStyles(styling) {
  if (!styling) return null;

  return [
    // Point styles
    {
      id: "gl-draw-point-active",
      type: "circle",
      filter: [
        "all",
        ["==", "$type", "Point"],
        ["==", "meta", "feature"],
        ["==", "active", "true"],
      ],
      paint: {
        "circle-radius": styling.vertex_radius + 2,
        "circle-color": styling.active_color,
      },
    },
    {
      id: "gl-draw-point",
      type: "circle",
      filter: [
        "all",
        ["==", "$type", "Point"],
        ["==", "meta", "feature"],
        ["==", "active", "false"],
      ],
      paint: {
        "circle-radius": styling.vertex_radius,
        "circle-color": styling.point_color,
      },
    },
    // Line styles
    {
      id: "gl-draw-line",
      type: "line",
      filter: ["all", ["==", "$type", "LineString"]],
      layout: {
        "line-cap": "round",
        "line-join": "round",
      },
      paint: {
        "line-color": [
          "case",
          ["==", ["get", "active"], "true"],
          styling.active_color,
          styling.line_color,
        ],
        "line-width": styling.line_width,
      },
    },
    // Polygon fill
    {
      id: "gl-draw-polygon-fill",
      type: "fill",
      filter: ["all", ["==", "$type", "Polygon"]],
      paint: {
        "fill-color": [
          "case",
          ["==", ["get", "active"], "true"],
          styling.active_color,
          styling.fill_color,
        ],
        "fill-outline-color": [
          "case",
          ["==", ["get", "active"], "true"],
          styling.active_color,
          styling.fill_color,
        ],
        "fill-opacity": styling.fill_opacity,
      },
    },
    // Polygon outline
    {
      id: "gl-draw-polygon-stroke",
      type: "line",
      filter: ["all", ["==", "$type", "Polygon"]],
      layout: {
        "line-cap": "round",
        "line-join": "round",
      },
      paint: {
        "line-color": [
          "case",
          ["==", ["get", "active"], "true"],
          styling.active_color,
          styling.line_color,
        ],
        "line-width": styling.line_width,
      },
    },
    // Midpoints
    {
      id: "gl-draw-polygon-midpoint",
      type: "circle",
      filter: ["all", ["==", "$type", "Point"], ["==", "meta", "midpoint"]],
      paint: {
        "circle-radius": 3,
        "circle-color": styling.active_color,
      },
    },
    // Vertex point halos
    {
      id: "gl-draw-vertex-halo-active",
      type: "circle",
      filter: ["all", ["==", "meta", "vertex"], ["==", "$type", "Point"]],
      paint: {
        "circle-radius": [
          "case",
          ["==", ["get", "active"], "true"],
          styling.vertex_radius + 4,
          styling.vertex_radius + 2,
        ],
        "circle-color": "#FFF",
      },
    },
    // Vertex points
    {
      id: "gl-draw-vertex-active",
      type: "circle",
      filter: ["all", ["==", "meta", "vertex"], ["==", "$type", "Point"]],
      paint: {
        "circle-radius": [
          "case",
          ["==", ["get", "active"], "true"],
          styling.vertex_radius + 2,
          styling.vertex_radius,
        ],
        "circle-color": styling.active_color,
      },
    },
  ];
}

function addBezierDrawStyles(styles, styling) {
  const activeColor = styling && styling.active_color ? styling.active_color : "#fbb03b";
  const baseStyles = styles || (MapboxDraw.lib && MapboxDraw.lib.theme) || [];
  const bezierStyles = [
    {
      id: "gl-draw-bezier-handle-line-active",
      type: "line",
      filter: [
        "all",
        ["==", "$type", "LineString"],
        ["==", "meta2", "handle-line"],
      ],
      layout: {
        "line-cap": "round",
        "line-join": "round",
      },
      paint: {
        "line-color": activeColor,
        "line-width": 1,
      },
    },
    {
      id: "gl-draw-bezier-handle-stroke-inactive",
      type: "circle",
      filter: [
        "all",
        ["==", "meta", "vertex"],
        ["==", "meta2", "handle"],
        ["==", "$type", "Point"],
        ["!=", "mode", "static"],
      ],
      paint: {
        "circle-radius": 5,
        "circle-color": "#fff",
      },
    },
    {
      id: "gl-draw-bezier-handle-inactive",
      type: "circle",
      filter: [
        "all",
        ["==", "meta", "vertex"],
        ["==", "meta2", "handle"],
        ["==", "$type", "Point"],
        ["!=", "mode", "static"],
      ],
      paint: {
        "circle-radius": 4,
        "circle-color": activeColor,
      },
    },
  ];

  return baseStyles.concat(bezierStyles);
}

function sanitizeBezierDisplayFeature(feature) {
  if (!feature || !feature.properties) return feature;

  const sanitized = {
    type: feature.type,
    properties: {},
    geometry: feature.geometry,
  };

  if (Object.prototype.hasOwnProperty.call(feature, "id")) {
    sanitized.id = feature.id;
  }

  Object.keys(feature.properties).forEach((key) => {
    if (
      key === "bezierGroup" ||
      key === "user_bezierGroup" ||
      key === "bezierCurve"
    ) {
      return;
    }
    sanitized.properties[key] = feature.properties[key];
  });

  return sanitized;
}

function wrapBezierDisplayModeForMapLibre(mode) {
  if (!mode || typeof mode.toDisplayFeatures !== "function") return mode;

  const wrappedMode = Object.assign({}, mode);
  const originalToDisplayFeatures = mode.toDisplayFeatures;
  wrappedMode.toDisplayFeatures = function (state, geojson, display) {
    return originalToDisplayFeatures.call(
      this,
      state,
      geojson,
      function (feature) {
        display(sanitizeBezierDisplayFeature(feature));
      },
    );
  };

  return wrappedMode;
}

function wrapBezierToolbarMode(mode) {
  if (!mode || typeof mode.onSetup !== "function") return mode;

  const wrappedMode = Object.assign({}, mode);
  const originalOnSetup = mode.onSetup;
  wrappedMode.onSetup = function (options) {
    const activateUIButton = this.activateUIButton;
    this.activateUIButton = function () {};

    try {
      return originalOnSetup.call(this, options);
    } finally {
      this.activateUIButton = activateUIButton;
    }
  };

  return wrappedMode;
}

function enableBezierDrawMode(drawOptions, styling) {
  if (!window.MapglBezierDraw) {
    console.warn("Bezier draw mode dependency is not available.");
    return drawOptions;
  }

  drawOptions.modes = Object.assign({}, drawOptions.modes || MapboxDraw.modes, {
    simple_select: wrapBezierDisplayModeForMapLibre(
      window.MapglBezierDraw.SimpleSelectModeBezierOverride,
    ),
    direct_select: wrapBezierDisplayModeForMapLibre(
      window.MapglBezierDraw.DirectModeBezierOverride,
    ),
    draw_bezier_curve: wrapBezierDisplayModeForMapLibre(
      wrapBezierToolbarMode(window.MapglBezierDraw.DrawBezierCurve),
    ),
  });
  drawOptions.userProperties = true;
  drawOptions.styles = addBezierDrawStyles(drawOptions.styles, styling);

  return drawOptions;
}

function addBezierButtonStyles() {
  if (document.querySelector("#mapgl-bezier-styles")) return;

  const style = document.createElement("style");
  style.id = "mapgl-bezier-styles";
  style.textContent = `
    .mapbox-gl-draw_bezier {
      background: transparent;
      background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"%3E%3Cpath d="M3 15 C7 3, 13 17, 17 5" fill="none" stroke="%23000000" stroke-width="2" stroke-linecap="round"/%3E%3Ccircle cx="3" cy="15" r="1.5" fill="%23000000"/%3E%3Ccircle cx="17" cy="5" r="1.5" fill="%23000000"/%3E%3C/svg%3E') !important;
      background-repeat: no-repeat !important;
      background-position: center !important;
    }
    .mapbox-gl-draw_bezier_polygon {
      background: transparent;
      background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"%3E%3Cpath d="M4 14 C5 4, 15 4, 16 14 C12 17, 8 17, 4 14 Z" fill="none" stroke="%23000000" stroke-width="2" stroke-linejoin="round"/%3E%3C/svg%3E') !important;
      background-repeat: no-repeat !important;
      background-position: center !important;
    }
    .mapbox-gl-draw_bezier:hover,
    .mapbox-gl-draw_bezier_polygon:hover,
    .mapbox-gl-draw_bezier.active,
    .mapbox-gl-draw_bezier_polygon.active {
      background-color: rgba(0, 0, 0, 0.05);
    }
  `;
  document.head.appendChild(style);
}

function setActiveBezierButton(drawControlGroup, className) {
  if (!drawControlGroup || !className) return;

  drawControlGroup
    .querySelectorAll(".active")
    .forEach((btn) => btn.classList.remove("active"));

  const button = drawControlGroup.querySelector("." + className);
  if (button) button.classList.add("active");
}

function clearActiveBezierButton(drawControlGroup) {
  if (!drawControlGroup) return;

  drawControlGroup._mapglActiveBezierButton = null;
  drawControlGroup
    .querySelectorAll(
      ".mapbox-gl-draw_bezier.active, .mapbox-gl-draw_bezier_polygon.active",
    )
    .forEach((btn) => btn.classList.remove("active"));
}

function addBezierButtons(map, drawControl, options) {
  if (!drawControl || !(options.bezier || options.bezierPolygon)) return;

  addBezierButtonStyles();

  setTimeout(() => {
    const drawControlGroup = map
      .getContainer()
      .querySelector(options.controlGroupSelector);
    if (!drawControlGroup) return;

    const trashBtn = drawControlGroup.querySelector(".mapbox-gl-draw_trash");
    const iconClass = options.iconClass || "";

    if (!drawControlGroup._mapglBezierNativeClickHandler) {
      drawControlGroup._mapglBezierNativeClickHandler = (e) => {
        if (
          e.target.closest(
            ".mapbox-gl-draw_bezier, .mapbox-gl-draw_bezier_polygon",
          )
        ) {
          return;
        }
        clearActiveBezierButton(drawControlGroup);
      };
      drawControlGroup.addEventListener(
        "click",
        drawControlGroup._mapglBezierNativeClickHandler,
        true,
      );
    }

    const addButton = (className, title, modeOptions) => {
      if (drawControlGroup.querySelector("." + className)) return;

      const button = document.createElement("button");
      button.className = `${className} ${iconClass}`.trim();
      button.title = title;
      button.type = "button";
      button.addEventListener("click", () => {
        drawControlGroup._mapglActiveBezierButton = className;
        drawControl.changeMode("draw_bezier_curve", modeOptions || {});
        setActiveBezierButton(drawControlGroup, className);
        requestAnimationFrame(() => {
          if (drawControlGroup._mapglActiveBezierButton === className) {
            setActiveBezierButton(drawControlGroup, className);
          }
        });
      });

      if (trashBtn) {
        drawControlGroup.insertBefore(button, trashBtn);
      } else {
        drawControlGroup.appendChild(button);
      }
    };

    if (options.bezier) {
      addButton("mapbox-gl-draw_bezier", "Bezier curve tool", {});
    }
    if (options.bezierPolygon) {
      addButton("mapbox-gl-draw_bezier_polygon", "Bezier polygon tool", {
        isPolygon: true,
      });
    }

    map.on("draw.modechange", (e) => {
      if (e && e.mode === "draw_bezier_curve") {
        setActiveBezierButton(
          drawControlGroup,
          drawControlGroup._mapglActiveBezierButton,
        );
      } else {
        clearActiveBezierButton(drawControlGroup);
      }
    });
  }, 100);
}

// Helper function to add features from a source to draw
function addSourceFeaturesToDraw(draw, sourceId, map) {
  const mapId = map.getContainer().id;

  // First try to get data from our registry (more reliable across MapLibre/Mapbox)
  const storedData = getStoredSourceData(mapId, sourceId);
  if (storedData) {
    draw.add(storedData);
    return;
  }

  // Fallback to internal _data property (for backwards compatibility with Mapbox)
  const source = map.getSource(sourceId);
  if (source && source._data) {
    draw.add(source._data);
  } else {
    console.warn("Source not found or has no data:", sourceId);
  }
}

// Global registries for tracking user-added images and pending operations during style changes
if (!window._mapgl) {
  window._mapgl = {
    // Registry of user-added images per map: { mapId: { imageId: { url, options } } }
    userImages: {},
    // Queue of pending operations during style loading: { mapId: [] }
    pendingOperations: {},
    // Track which maps are currently loading a style: { mapId: true/false }
    styleLoading: {},
    // Registry of GeoJSON source data per map: { mapId: { sourceId: geojsonData } }
    sourceData: {}
  };
}

// Helper to store GeoJSON source data for later retrieval
function storeSourceData(mapId, sourceId, data) {
  if (!window._mapgl.sourceData[mapId]) {
    window._mapgl.sourceData[mapId] = {};
  }
  window._mapgl.sourceData[mapId][sourceId] = data;
}

// Helper to get stored GeoJSON source data
function getStoredSourceData(mapId, sourceId) {
  if (window._mapgl.sourceData[mapId]) {
    return window._mapgl.sourceData[mapId][sourceId];
  }
  return null;
}

// Helper to queue an operation or execute it immediately
function queueOrExecute(mapId, operation) {
  if (window._mapgl.styleLoading[mapId]) {
    if (!window._mapgl.pendingOperations[mapId]) {
      window._mapgl.pendingOperations[mapId] = [];
    }
    window._mapgl.pendingOperations[mapId].push(operation);
    console.log("[MapGL Debug] Queued operation during style load for map:", mapId);
  } else {
    operation();
  }
}

// Helper to execute all pending operations for a map
function executePendingOperations(mapId) {
  const pending = window._mapgl.pendingOperations[mapId];
  if (pending && pending.length > 0) {
    console.log("[MapGL Debug] Executing", pending.length, "pending operations for map:", mapId);
    pending.forEach(function(op) {
      try {
        op();
      } catch (err) {
        console.error("[MapGL Debug] Error executing pending operation:", err);
      }
    });
    window._mapgl.pendingOperations[mapId] = [];
  }
}

// Helper to register a user image
function registerUserImage(mapId, imageId, url, options) {
  if (!window._mapgl.userImages[mapId]) {
    window._mapgl.userImages[mapId] = {};
  }
  window._mapgl.userImages[mapId][imageId] = { url: url, options: options };
  console.log("[MapGL Debug] Registered user image:", imageId, "for map:", mapId);
}

// Helper to re-add all user images after style change
async function reAddUserImages(map, mapId) {
  const images = window._mapgl.userImages[mapId];
  if (!images) return;

  for (const imageId in images) {
    const imageInfo = images[imageId];
    try {
      const image = await map.loadImage(imageInfo.url);
      if (!map.hasImage(imageId)) {
        map.addImage(imageId, image.data, imageInfo.options);
        console.log("[MapGL Debug] Re-added user image after style change:", imageId);
      }
    } catch (error) {
      console.error("[MapGL Debug] Error re-adding image:", imageId, error);
    }
  }
}

// Screenshot capture functionality
// Screenshot functions are now in screenshot.js (shared module)

HTMLWidgets.widget({
  name: "maplibregl",

  type: "output",

  factory: function (el, width, height) {
    let map;
    let draw;

    return {
      renderValue: function (x) {
        if (typeof maplibregl === "undefined") {
          console.error("Maplibre GL JS is not loaded.");
          return;
        }

        // Clean up existing map if present to prevent control stacking on re-render
        if (map) {
          // Remove all controls from the old map
          if (map.controls && map.controls.length > 0) {
            map.controls.forEach(function (controlObj) {
              try {
                if (controlObj.control) {
                  map.removeControl(controlObj.control);
                }
              } catch (e) {
                // Control may already be removed
              }
            });
          }
          // Remove the old map
          try {
            map.remove();
          } catch (e) {
            // Map may already be removed
          }
          map = null;
        }

        let protocol = new pmtiles.Protocol({ metadata: true });
        maplibregl.addProtocol("pmtiles", protocol.tile);

        map = new maplibregl.Map({
          container: el.id,
          style: x.style,
          center: x.center,
          zoom: x.zoom,
          bearing: x.bearing,
          pitch: x.pitch,
          ...x.additional_params,
        });

        map.controls = [];
        map._initialStyleLoaded = false;

        map.on("style.load", async function () {
          // Store basemap layer IDs before user layers are added
          if (!map._basemapLayerIds) {
            map._basemapLayerIds = new Set(
              map.getStyle().layers.map(l => l.id)
            );
          }

          if (x.projection) {
            map.setProjection({ type: x.projection });
          }

          map.resize();

          if (HTMLWidgets.shinyMode) {
            map.on("load", function () {
              var bounds = map.getBounds();
              var center = map.getCenter();
              var zoom = map.getZoom();

              Shiny.setInputValue(el.id + "_zoom", zoom);
              Shiny.setInputValue(el.id + "_center", {
                lng: center.lng,
                lat: center.lat,
              });
              Shiny.setInputValue(el.id + "_bbox", {
                xmin: bounds.getWest(),
                ymin: bounds.getSouth(),
                xmax: bounds.getEast(),
                ymax: bounds.getNorth(),
              });
            });

            map.on("moveend", function (e) {
              var map = e.target;
              var bounds = map.getBounds();
              var center = map.getCenter();
              var zoom = map.getZoom();

              Shiny.onInputChange(el.id + "_zoom", zoom);
              Shiny.onInputChange(el.id + "_center", {
                lng: center.lng,
                lat: center.lat,
              });
              Shiny.onInputChange(el.id + "_bbox", {
                xmin: bounds.getWest(),
                ymin: bounds.getSouth(),
                xmax: bounds.getEast(),
                ymax: bounds.getNorth(),
              });
            });
          }

          // Set config properties if provided
          if (x.config_properties) {
            x.config_properties.forEach(function (config) {
              map.setConfigProperty(
                config.importId,
                config.configName,
                config.value,
              );
            });
          }

          if (x.markers) {
            if (!window.maplibreglMarkers) {
              window.maplibreglMarkers = [];
            }
            x.markers.forEach(function (marker) {
              const markerOptions = {
                color: marker.color,
                rotation: marker.rotation,
                draggable: marker.options.draggable || false,
                ...marker.options,
              };
              const mapMarker = new maplibregl.Marker(markerOptions)
                .setLngLat([marker.lng, marker.lat])
                .addTo(map);

              if (marker.popup) {
                mapMarker.setPopup(
                  new maplibregl.Popup({
                    offset: 25,
                    maxWidth: "400px",
                  }).setHTML(marker.popup),
                );
              }

              if (HTMLWidgets.shinyMode) {
                const markerId = marker.id;
                if (markerId) {
                  const lngLat = mapMarker.getLngLat();
                  Shiny.setInputValue(el.id + "_marker_" + markerId, {
                    id: markerId,
                    lng: lngLat.lng,
                    lat: lngLat.lat,
                  });

                  mapMarker.on("dragend", function () {
                    const lngLat = mapMarker.getLngLat();
                    Shiny.setInputValue(el.id + "_marker_" + markerId, {
                      id: markerId,
                      lng: lngLat.lng,
                      lat: lngLat.lat,
                    });
                  });
                }
              }

              window.maplibreglMarkers.push(mapMarker);
            });
          }

          // Add sources if provided
          if (x.sources) {
            for (const source of x.sources) {
              if (source.type === "vector") {
                const sourceOptions = {
                  type: "vector",
                };
                // Add url or tiles
                if (source.url) {
                  sourceOptions.url = source.url;
                  // Auto-detect MLT encoding for PMTiles sources
                  if (
                    source.url.startsWith("pmtiles://") &&
                    typeof pmtiles !== "undefined" &&
                    !source.encoding
                  ) {
                    try {
                      const rawUrl = source.url.replace("pmtiles://", "");
                      const p = new pmtiles.PMTiles(rawUrl);
                      const header = await p.getHeader();
                      if (header.tileType === pmtiles.TileType.Mlt) {
                        sourceOptions.encoding = "mlt";
                      }
                    } catch (e) {
                      console.warn("Failed to detect PMTiles tile type:", e);
                    }
                  }
                }
                if (source.tiles) {
                  sourceOptions.tiles = source.tiles;
                }
                // Add promoteId if provided
                if (source.promoteId) {
                  sourceOptions.promoteId = source.promoteId;
                }
                // Add any other additional options
                for (const [key, value] of Object.entries(source)) {
                  if (
                    !["id", "type", "url", "tiles", "promoteId"].includes(key)
                  ) {
                    sourceOptions[key] = value;
                  }
                }
                map.addSource(source.id, sourceOptions);
              } else if (source.type === "geojson") {
                const geojsonData = source.data;
                const sourceOptions = {
                  type: "geojson",
                  data: geojsonData,
                  generateId: source.generateId,
                };

                // Add additional options
                for (const [key, value] of Object.entries(source)) {
                  if (!["id", "type", "data", "generateId"].includes(key)) {
                    sourceOptions[key] = value;
                  }
                }

                map.addSource(source.id, sourceOptions);
                // Store GeoJSON data for later retrieval (e.g., for draw control)
                storeSourceData(el.id, source.id, geojsonData);
              } else if (source.type === "raster") {
                if (source.url) {
                  map.addSource(source.id, {
                    type: "raster",
                    url: source.url,
                    tileSize: source.tileSize,
                    maxzoom: source.maxzoom,
                  });
                } else if (source.tiles) {
                  map.addSource(source.id, {
                    type: "raster",
                    tiles: source.tiles,
                    tileSize: source.tileSize,
                    maxzoom: source.maxzoom,
                  });
                }
              } else if (source.type === "raster-dem") {
                map.addSource(source.id, {
                  type: "raster-dem",
                  url: source.url,
                  tileSize: source.tileSize,
                  maxzoom: source.maxzoom,
                });
              } else if (source.type === "image") {
                map.addSource(source.id, {
                  type: "image",
                  url: source.url,
                  coordinates: source.coordinates,
                });
              } else if (source.type === "video") {
                map.addSource(source.id, {
                  type: "video",
                  urls: source.urls,
                  coordinates: source.coordinates,
                });
              }
            }
          }

          function add_my_layers(layer) {
            try {
              const layerConfig = {
                id: layer.id,
                type: layer.type,
                source: layer.source,
                layout: layer.layout || {},
                paint: layer.paint || {},
              };

              // Check if source is an object and set generateId if source type is 'geojson'
              if (
                typeof layer.source === "object" &&
                layer.source.type === "geojson"
              ) {
                layerConfig.source.generateId = true;
              } else if (typeof layer.source === "string") {
                // Handle string source if needed
                layerConfig.source = layer.source;
              }

              if (layer.source_layer) {
                layerConfig["source-layer"] = layer.source_layer;
              }

              if (layer.slot) {
                layerConfig["slot"] = layer.slot;
              }

              if (layer.minzoom) {
                layerConfig["minzoom"] = layer.minzoom;
              }

              if (layer.maxzoom) {
                layerConfig["maxzoom"] = layer.maxzoom;
              }

              if (layer.filter) {
                layerConfig["filter"] = layer.filter;
              }

              if (layer.before_id) {
                map.addLayer(layerConfig, layer.before_id);
              } else {
                map.addLayer(layerConfig);
              }

              // Seed the filter registry with this layer's initial filter
              // so later filter sources compose with it rather than clobber it.
              (function () {
                const _s = _mapglEnsureLayerState(map);
                _s.filterStack[layer.id] = _s.filterStack[layer.id] || {};
                _s.filterStack[layer.id].base = layer.filter || null;
                _s.filters[layer.id] = layer.filter || null;
              })();

              // Add popups or tooltips if provided
              if (layer.popup) {
                // Initialize popup tracking if it doesn't exist
                if (!window._mapboxPopups) {
                  window._mapboxPopups = {};
                }

                // Create click handler for this layer
                const clickHandler = function (e) {
                  onClickPopup(e, map, layer.popup, layer.id, layer.popup_style);
                };

                // Store these handler references so we can remove them later if needed
                if (!window._mapboxClickHandlers) {
                  window._mapboxClickHandlers = {};
                }
                window._mapboxClickHandlers[layer.id] = clickHandler;

                // Add the click handler
                map.on("click", layer.id, clickHandler);

                // Change cursor to pointer when hovering over the layer
                map.on("mouseenter", layer.id, function () {
                  map.getCanvas().style.cursor = "pointer";
                });

                // Change cursor back to default when leaving the layer
                map.on("mouseleave", layer.id, function () {
                  map.getCanvas().style.cursor = "";
                });
              }

              if (layer.tooltip) {
                const tooltip = new maplibregl.Popup({
                  closeButton: false,
                  closeOnClick: false,
                  maxWidth: "400px",
                });
                applyPopupClass(tooltip, layer.tooltip_style);

                // Create a reference to the mousemove handler function.
                // We need to pass 'e', 'map', 'tooltip', 'layer.tooltip', and 'layer.id' to onMouseMoveTooltip.
                const mouseMoveHandler = function (e) {
                  onMouseMoveTooltip(e, map, tooltip, layer.tooltip, layer.id);
                };

                // Create a reference to the mouseleave handler function.
                // We need to pass 'map' and 'tooltip' to onMouseLeaveTooltip.
                const mouseLeaveHandler = function () {
                  onMouseLeaveTooltip(map, tooltip);
                };

                // Attach the named handler references, not anonymous functions.
                map.on("mousemove", layer.id, mouseMoveHandler);
                map.on("mouseleave", layer.id, mouseLeaveHandler);

                // Store these handler references so you can remove them later if needed
                if (!window._mapboxHandlers) {
                  window._mapboxHandlers = {};
                }
                window._mapboxHandlers[layer.id] = {
                  mousemove: mouseMoveHandler,
                  mouseleave: mouseLeaveHandler,
                };
              }

              // Add hover effect if provided
              if (layer.hover_options) {
                const jsHoverOptions = {};
                for (const [key, value] of Object.entries(
                  layer.hover_options,
                )) {
                  const jsKey = key.replace(/_/g, "-");
                  jsHoverOptions[jsKey] = value;
                }

                let hoveredFeatureId = null;

                map.on("mousemove", layer.id, function (e) {
                  if (e.features.length > 0) {
                    // Check if the feature has an id
                    const featureId = e.features[0].id;

                    // Only proceed if the feature has an id
                    if (featureId !== undefined && featureId !== null) {
                      if (hoveredFeatureId !== null) {
                        const featureState = {
                          source:
                            typeof layer.source === "string"
                              ? layer.source
                              : layer.id,
                          id: hoveredFeatureId,
                        };
                        if (layer.source_layer) {
                          featureState.sourceLayer = layer.source_layer;
                        }
                        map.setFeatureState(featureState, { hover: false });
                      }
                      hoveredFeatureId = featureId;
                      const featureState = {
                        source:
                          typeof layer.source === "string"
                            ? layer.source
                            : layer.id,
                        id: hoveredFeatureId,
                      };
                      if (layer.source_layer) {
                        featureState.sourceLayer = layer.source_layer;
                      }
                      map.setFeatureState(featureState, { hover: true });
                    }
                  }
                });

                map.on("mouseleave", layer.id, function () {
                  if (hoveredFeatureId !== null) {
                    const featureState = {
                      source:
                        typeof layer.source === "string"
                          ? layer.source
                          : layer.id,
                      id: hoveredFeatureId,
                    };
                    if (layer.source_layer) {
                      featureState.sourceLayer = layer.source_layer;
                    }
                    map.setFeatureState(featureState, { hover: false });
                  }
                  hoveredFeatureId = null;
                });

                Object.keys(jsHoverOptions).forEach(function (key) {
                  const originalPaint =
                    map.getPaintProperty(layer.id, key) || layer.paint[key];
                  map.setPaintProperty(layer.id, key, [
                    "case",
                    ["boolean", ["feature-state", "hover"], false],
                    jsHoverOptions[key],
                    originalPaint,
                  ]);
                });
              }
            } catch (e) {
              console.error("Failed to add layer: ", layer, e);
            }
          }
          if (x.h3j_sources) {
            x.h3j_sources.forEach(async function (source) {
              await map.addH3JSource(source.id, {
                data: source.url,
              });

              // A bit hacky?
              if (x.layers) {
                x.layers.forEach((layer) => add_my_layers(layer));
              }
            });
          }
          if (x.h3t_sources) {
            x.h3t_sources.forEach(function (source) {
              map.addH3TSource(source.id, {
                tiles: source.tiles,
                sourcelayer: source.sourcelayer,
                geometry_type: source.geometry_type,
                minzoom: source.minzoom,
                maxzoom: source.maxzoom,
                promoteId: source.promoteId,
                debug: source.debug,
              });
              if (x.layers) {
                x.layers.forEach((layer) => add_my_layers(layer));
              }
            });
          }

          // Add layers if provided
          if (x.layers) {
            x.layers.forEach((layer) => add_my_layers(layer));
          }

          if (window.MapGLFlowmapPlugin) {
            window.MapGLFlowmapPlugin.init(map, x, el, HTMLWidgets);
          }

          // Apply setFilter if provided
          if (x.setFilter) {
            x.setFilter.forEach(function (filter) {
              map.setFilter(filter.layer, filter.filter);
            });
          }

          // Apply moveLayer operations if provided
          if (x.moveLayer) {
            x.moveLayer.forEach(function (moveOp) {
              if (map.getLayer(moveOp.layer)) {
                if (moveOp.before) {
                  map.moveLayer(moveOp.layer, moveOp.before);
                } else {
                  map.moveLayer(moveOp.layer);
                }
              }
            });
          }

          // Set terrain if provided
          if (x.terrain) {
            map.setTerrain({
              source: x.terrain.source,
              exaggeration: x.terrain.exaggeration,
            });
          }

          // Set fog
          if (x.fog) {
            map.setFog(x.fog);
          }

          if (x.fitBounds) {
            map.fitBounds(x.fitBounds.bounds, x.fitBounds.options);
          }
          if (x.flyTo) {
            map.flyTo(x.flyTo);
          }
          if (x.easeTo) {
            map.easeTo(x.easeTo);
          }
          if (x.setCenter) {
            map.setCenter(x.setCenter);
          }
          if (x.setZoom) {
            map.setZoom(x.setZoom);
          }
          if (x.jumpTo) {
            map.jumpTo(x.jumpTo);
          }

          // Add controls only on initial style load to prevent duplication when set_style() is called
          if (!map._initialStyleLoaded) {
            // Add scale control if enabled
            if (x.scale_control) {
            const scaleControl = new maplibregl.ScaleControl({
              maxWidth: x.scale_control.maxWidth,
              unit: x.scale_control.unit,
            });
            map.addControl(scaleControl, x.scale_control.position);
            map.controls.push({ type: "scale", control: scaleControl });
          }

          // Add globe control if enabled
          if (x.globe_control) {
            const globeControl = new maplibregl.GlobeControl();
            map.addControl(globeControl, x.globe_control.position);
            map.controls.push({ type: "globe", control: globeControl });
          }

          // Add custom controls if any are defined
          if (x.custom_controls) {
            Object.keys(x.custom_controls).forEach(function (key) {
              const controlOptions = x.custom_controls[key];
              const customControlContainer = document.createElement("div");

              if (controlOptions.className) {
                customControlContainer.className = controlOptions.className;
              } else {
                customControlContainer.className =
                  "maplibregl-ctrl maplibregl-ctrl-group";
              }

              customControlContainer.innerHTML = controlOptions.html;

              const customControl = {
                onAdd: function () {
                  return customControlContainer;
                },
                onRemove: function () {
                  if (customControlContainer.parentNode) {
                    customControlContainer.parentNode.removeChild(
                      customControlContainer,
                    );
                  }
                },
              };

              map.addControl(
                customControl,
                controlOptions.position || "top-right",
              );
              map.controls.push({ type: key, control: customControl });
            });
          }

          // Add globe minimap if enabled
          if (x.globe_minimap && x.globe_minimap.enabled) {
            const globeMinimapOptions = {
              globeSize: x.globe_minimap.globe_size,
              landColor: x.globe_minimap.land_color,
              waterColor: x.globe_minimap.water_color,
              markerColor: x.globe_minimap.marker_color,
              markerSize: x.globe_minimap.marker_size,
            };
            const globeMinimap = new GlobeMinimap(globeMinimapOptions);
            map.addControl(globeMinimap, x.globe_minimap.position);
            map.controls.push({ type: "globe_minimap", control: globeMinimap });
          }

          if (x.setProjection) {
            x.setProjection.forEach(function (projectionConfig) {
              if (projectionConfig.projection) {
                const projection =
                  typeof projectionConfig.projection === "string"
                    ? { type: projectionConfig.projection }
                    : projectionConfig.projection;
                map.setProjection(projection);
              }
            });
          }

          // Add geocoder control if enabled
          if (x.geocoder_control) {
            const provider = x.geocoder_control.provider || "osm";
            let geocoder;

            if (provider === "maptiler") {
              // MapTiler geocoder
              const maptilerOptions = {
                apiKey: x.geocoder_control.api_key,
                maplibregl: maplibregl,
                ...x.geocoder_control,
              };

              // Create MapTiler geocoder
              geocoder = new maplibreglMaptilerGeocoder.GeocodingControl(
                maptilerOptions,
              );
            } else {
              // OSM/Nominatim geocoder (default)
              const geocoderApi = {
                forwardGeocode: async (config) => {
                  const features = [];
                  try {
                    const request = `https://nominatim.openstreetmap.org/search?q=${
                      config.query
                    }&format=geojson&polygon_geojson=1&addressdetails=1`;
                    const response = await fetch(request);
                    const geojson = await response.json();
                    for (const feature of geojson.features) {
                      const center = [
                        feature.bbox[0] +
                          (feature.bbox[2] - feature.bbox[0]) / 2,
                        feature.bbox[1] +
                          (feature.bbox[3] - feature.bbox[1]) / 2,
                      ];
                      const point = {
                        type: "Feature",
                        geometry: {
                          type: "Point",
                          coordinates: center,
                        },
                        place_name: feature.properties.display_name,
                        properties: feature.properties,
                        text: feature.properties.display_name,
                        place_type: ["place"],
                        center,
                      };
                      features.push(point);
                    }
                  } catch (e) {
                    console.error(`Failed to forwardGeocode with error: ${e}`);
                  }

                  return {
                    features,
                  };
                },
              };
              const geocoderOptions = {
                maplibregl: maplibregl,
                ...x.geocoder_control,
              };

              // Set default values if not provided
              if (!geocoderOptions.placeholder)
                geocoderOptions.placeholder = "Search";
              if (typeof geocoderOptions.collapsed === "undefined")
                geocoderOptions.collapsed = false;

              geocoder = new MaplibreGeocoder(geocoderApi, geocoderOptions);
            }

            map.addControl(
              geocoder,
              x.geocoder_control.position || "top-right",
            );
            map.controls.push({ type: "geocoder", control: geocoder });

            // Apply CSS fix for MapTiler geocoder to prevent cutoff
            if (provider === "maptiler") {
              setTimeout(() => {
                const controlContainer = document.querySelector(
                  ".maplibregl-ctrl-geocoder",
                );
                if (controlContainer) {
                  controlContainer.style.maxWidth = "300px";
                  controlContainer.style.width = "auto";
                }
              }, 100);
            }

            // Handle geocoder results in Shiny mode
            if (HTMLWidgets.shinyMode) {
              if (provider === "maptiler") {
                // MapTiler uses different event names
                geocoder.on("pick", function (e) {
                  Shiny.setInputValue(el.id + "_geocoder", {
                    result: e,
                    time: new Date(),
                  });
                });
              } else {
                // OSM geocoder
                geocoder.on("results", function (e) {
                  Shiny.setInputValue(el.id + "_geocoder", {
                    result: e,
                    time: new Date(),
                  });
                });
              }
            }
          }

          if (x.draw_control && x.draw_control.enabled) {
            MapboxDraw.constants.classes.CONTROL_BASE = "maplibregl-ctrl";
            MapboxDraw.constants.classes.CONTROL_PREFIX = "maplibregl-ctrl-";
            MapboxDraw.constants.classes.CONTROL_GROUP =
              "maplibregl-ctrl-group";

            let drawOptions = x.draw_control.options || {};

            // Generate styles if styling parameters provided
            if (x.draw_control.styling) {
              const generatedStyles = generateDrawStyles(
                x.draw_control.styling,
              );
              if (generatedStyles) {
                drawOptions.styles = generatedStyles;
              }
            }

            if (x.draw_control.freehand) {
              drawOptions = Object.assign({}, drawOptions, {
                modes: Object.assign({}, MapboxDraw.modes, {
                  draw_polygon: Object.assign(
                    {},
                    MapboxDraw.modes.draw_freehand,
                    {
                      // Store the simplify_freehand option on the map object
                      onSetup: function (opts) {
                        const state =
                          MapboxDraw.modes.draw_freehand.onSetup.call(
                            this,
                            opts,
                          );
                        this.map.simplify_freehand =
                          x.draw_control.simplify_freehand;
                        return state;
                      },
                    },
                  ),
                }),
                // defaultMode: 'draw_polygon' # Don't set the default yet
              });
            }

            // Add rectangle mode if enabled
            if (x.draw_control.rectangle) {
              if (!drawOptions.modes) {
                drawOptions.modes = Object.assign({}, MapboxDraw.modes);
              }
              drawOptions.modes.draw_rectangle =
                MapboxDraw.modes.draw_rectangle;
            }

            // Add radius mode if enabled
            if (x.draw_control.radius) {
              if (!drawOptions.modes) {
                drawOptions.modes = Object.assign({}, MapboxDraw.modes);
              }
              drawOptions.modes.draw_radius = MapboxDraw.modes.draw_radius;
            }

            // Fix MapLibre compatibility - ensure we always have custom styles
            if (!drawOptions.styles) {
              drawOptions.styles = generateDrawStyles({
                vertex_radius: 5,
                active_color: "#fbb03b",
                point_color: "#3bb2d0",
                line_color: "#3bb2d0",
                fill_color: "#3bb2d0",
                fill_opacity: 0.1,
                line_width: 2,
              });
            }

            if (x.draw_control.bezier || x.draw_control.bezier_polygon) {
              drawOptions = enableBezierDrawMode(
                drawOptions,
                x.draw_control.styling,
              );
            }

            if (_mapglHasDrawAttributes(x.draw_control.attributes)) {
              drawOptions = Object.assign({}, drawOptions, {
                userProperties: true,
              });
            }

            draw = new MapboxDraw(drawOptions);
            map.addControl(draw, x.draw_control.position);
            map.controls.push({ type: "draw", control: draw });

            // Add lasso icon CSS for freehand mode
            if (x.draw_control.freehand) {
              if (!document.querySelector("#mapgl-freehand-lasso-styles")) {
                const style = document.createElement("style");
                style.id = "mapgl-freehand-lasso-styles";
                style.textContent = `
                  .mapbox-gl-draw_polygon {
                    background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"%3E%3Cpath d="M 7 3 C 5 2.5, 3.5 3, 3 5 C 2.5 7, 3 8.5, 4 9.5 C 5 10.5, 5.5 11.5, 5 13 C 4.5 14.5, 5 15.5, 6.5 16 C 8 16.5, 9.5 16, 11 15 C 12.5 14, 13.5 13, 14.5 11.5 C 15.5 10, 16 8.5, 15.5 7 C 15 5.5, 14 4.5, 12.5 3.5 C 11 2.5, 9 2.5, 7 3 Z" fill="none" stroke="%23000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/%3E%3C/svg%3E') !important;
                  }
                `;
                document.head.appendChild(style);
              }

              // Update tooltip for freehand mode
              setTimeout(() => {
                const polygonButton = map
                  .getContainer()
                  .querySelector(".mapbox-gl-draw_polygon");
                if (polygonButton) {
                  polygonButton.title = "Freehand polygon tool (p)";
                }
              }, 100);
            }

            // Add rectangle icon CSS if rectangle mode is enabled
            if (x.draw_control.rectangle) {
              if (!document.querySelector("#mapgl-rectangle-styles")) {
                const style = document.createElement("style");
                style.id = "mapgl-rectangle-styles";
                style.textContent = `
                  .mapbox-gl-draw_rectangle {
                    background: transparent;
                    border: none;
                    cursor: pointer;
                    display: block;
                    height: 30px;
                    width: 30px;
                    padding: 0;
                    outline: none;
                    background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"%3E%3Crect x="4" y="5" width="12" height="10" fill="none" stroke="%23000000" stroke-width="2"/%3E%3C/svg%3E') !important;
                    background-repeat: no-repeat !important;
                    background-position: center !important;
                  }
                  .mapbox-gl-draw_rectangle:hover {
                    background-color: rgba(0, 0, 0, 0.05);
                  }
                  .mapbox-gl-draw_rectangle.active {
                    background-color: rgba(0, 0, 0, 0.05);
                  }
                `;
                document.head.appendChild(style);
              }
            }

            // Add radius/circle icon CSS if radius mode is enabled
            if (x.draw_control.radius) {
              if (!document.querySelector("#mapgl-radius-styles")) {
                const style = document.createElement("style");
                style.id = "mapgl-radius-styles";
                style.textContent = `
                  .mapbox-gl-draw_radius {
                    background: transparent;
                    border: none;
                    cursor: pointer;
                    display: block;
                    height: 30px;
                    width: 30px;
                    padding: 0;
                    outline: none;
                    background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"%3E%3Ccircle cx="10" cy="10" r="7" fill="none" stroke="%23000000" stroke-width="2"/%3E%3Ccircle cx="10" cy="10" r="1.5" fill="%23000000"/%3E%3C/svg%3E') !important;
                    background-repeat: no-repeat !important;
                    background-position: center !important;
                  }
                  .mapbox-gl-draw_radius:hover {
                    background-color: rgba(0, 0, 0, 0.05);
                  }
                  .mapbox-gl-draw_radius.active {
                    background-color: rgba(0, 0, 0, 0.05);
                  }
                `;
                document.head.appendChild(style);
              }
            }

            addBezierButtons(map, draw, {
              bezier: x.draw_control.bezier,
              bezierPolygon: x.draw_control.bezier_polygon,
              controlGroupSelector:
                ".maplibregl-ctrl-group:has(.mapbox-gl-draw_polygon)",
            });

            initializeDrawAttributeEditor(map, draw, {
              attributes: x.draw_control.attributes,
              position: x.draw_control.position,
              onChange: updateDrawnFeatures,
            });

            // Add event listeners
            map.on("draw.create", () => updateDrawnFeatures(false));
            map.on("draw.delete", () => updateDrawnFeatures(false));
            map.on("draw.update", () => updateDrawnFeatures(true));

            // Add measurement functionality if enabled
            if (x.draw_control.show_measurements) {
              initializeMeasurements(
                map,
                draw,
                x.draw_control.measurement_units,
              );
            }

            // Add initial features if provided
            if (x.draw_control.source) {
              addSourceFeaturesToDraw(draw, x.draw_control.source, map);
              updateDrawnFeatures(false);
            }

            // Process any queued features
            if (x.draw_features_queue) {
              x.draw_features_queue.forEach(function (data) {
                if (data.clear_existing) {
                  draw.deleteAll();
                }
                addSourceFeaturesToDraw(draw, data.source, map);
              });
              updateDrawnFeatures(false);
            }

            // Add custom mode buttons
            setTimeout(() => {
              const drawControlGroup = map
                .getContainer()
                .querySelector(".maplibregl-ctrl-group");

              if (drawControlGroup) {
                // Find the trash button to insert before it
                const trashBtn = drawControlGroup.querySelector(
                  ".mapbox-gl-draw_trash",
                );

                if (x.draw_control.rectangle) {
                  const rectangleBtn = document.createElement("button");
                  rectangleBtn.className = "mapbox-gl-draw_rectangle";
                  rectangleBtn.title = "Rectangle tool";
                  rectangleBtn.type = "button";
                  rectangleBtn.onclick = function () {
                    draw.changeMode("draw_rectangle");
                    // Update active state
                    drawControlGroup
                      .querySelectorAll("button")
                      .forEach((btn) => btn.classList.remove("active"));
                    rectangleBtn.classList.add("active");
                  };
                  // Insert before trash button if it exists, otherwise append
                  if (trashBtn) {
                    drawControlGroup.insertBefore(rectangleBtn, trashBtn);
                  } else {
                    drawControlGroup.appendChild(rectangleBtn);
                  }
                }

                if (x.draw_control.radius) {
                  const radiusBtn = document.createElement("button");
                  radiusBtn.className = "mapbox-gl-draw_radius";
                  radiusBtn.title = "Radius/Circle tool";
                  radiusBtn.type = "button";
                  radiusBtn.onclick = function () {
                    draw.changeMode("draw_radius");
                    // Update active state
                    drawControlGroup
                      .querySelectorAll("button")
                      .forEach((btn) => btn.classList.remove("active"));
                    radiusBtn.classList.add("active");
                  };
                  // Insert before trash button if it exists, otherwise append
                  if (trashBtn) {
                    drawControlGroup.insertBefore(radiusBtn, trashBtn);
                  } else {
                    drawControlGroup.appendChild(radiusBtn);
                  }
                }
              }
            }, 100);

            // Apply orientation styling
            if (x.draw_control.orientation === "horizontal") {
              const drawBar = map
                .getContainer()
                .querySelector(".maplibregl-ctrl-group");
              if (drawBar) {
                drawBar.style.display = "flex";
                drawBar.style.flexDirection = "row";
              }
            }

            // Add download button if requested
            if (x.draw_control.download_button) {
              // Add CSS for download button if not already added
              if (!document.querySelector("#mapgl-draw-download-styles")) {
                const style = document.createElement("style");
                style.id = "mapgl-draw-download-styles";
                style.textContent = `
                  .mapbox-gl-draw_download {
                    background: transparent;
                    border: none;
                    cursor: pointer;
                    display: block;
                    height: 30px;
                    width: 30px;
                    padding: 0;
                    outline: none;
                  }
                  .mapbox-gl-draw_download:hover {
                    background-color: rgba(0, 0, 0, 0.05);
                  }
                  .mapbox-gl-draw_download svg {
                    width: 20px;
                    height: 20px;
                    margin: 5px;
                    fill: #333;
                  }
                `;
                document.head.appendChild(style);
              }

              // Small delay to ensure Draw control is fully rendered
              setTimeout(() => {
                // Find the Draw control button group
                const drawButtons = map
                  .getContainer()
                  .querySelector(
                    ".maplibregl-ctrl-group:has(.mapbox-gl-draw_polygon)",
                  );

                if (drawButtons) {
                  // Create download button
                  const downloadBtn = document.createElement("button");
                  downloadBtn.className = "mapbox-gl-draw_download";
                  downloadBtn.title = "Download drawn features as GeoJSON";

                  // Add SVG download icon
                  downloadBtn.innerHTML = `
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                      <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
                    </svg>
                  `;

                  downloadBtn.addEventListener("click", () => {
                    // Get all drawn features
                    const data = draw.getAll();

                    if (data.features.length === 0) {
                      alert(
                        "No features to download. Please draw something first!",
                      );
                      return;
                    }

                    // Convert to string with nice formatting
                    const dataStr = JSON.stringify(data, null, 2);

                    // Create blob and download
                    const blob = new Blob([dataStr], {
                      type: "application/json",
                    });
                    const url = URL.createObjectURL(blob);

                    const a = document.createElement("a");
                    a.href = url;
                    a.download = `${x.draw_control.download_filename}.geojson`;
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url);
                  });

                  // Append to the Draw control button group
                  drawButtons.appendChild(downloadBtn);
                }
              }, 100);
            }
          }

          function updateDrawnFeatures(debounce) {
            _mapglSyncDrawnFeatures({
              inputId: el.id,
              drawControl: draw,
              widget: HTMLWidgets.find("#" + el.id),
              syncUrl: x.sync_url,
              mapglId: x.mapgl_id,
              debounce: debounce,
            });
          }

          if (!x.add) {
            const existingLegends = el.querySelectorAll(".mapboxgl-legend");
            existingLegends.forEach((legend) => legend.remove());
          }

          if (x.legend_html && x.legend_css) {
            const legendCss = document.createElement("style");
            legendCss.innerHTML = x.legend_css;
            document.head.appendChild(legendCss);

            const legend = document.createElement("div");
            legend.innerHTML = x.legend_html;
            legend.classList.add("mapboxgl-legend");
            el.appendChild(legend);
          }

          // Initialize legend interactivity if configured
          if (x.legend_interactivity && x.legend_interactivity.length > 0) {
            x.legend_interactivity.forEach(function(config) {
              if (typeof initializeLegendInteractivity === "function") {
                initializeLegendInteractivity(map, el.id, config);
              }
            });
          }

          // Initialize draggable legends
          if (typeof initializeDraggableLegends === "function") {
            initializeDraggableLegends(el);
          }

          // Add fullscreen control if enabled
          if (x.fullscreen_control && x.fullscreen_control.enabled) {
            const position = x.fullscreen_control.position || "top-right";
            const fullscreen = new maplibregl.FullscreenControl();
            map.addControl(fullscreen, position);
            map.controls.push({ type: "fullscreen", control: fullscreen });
          }

          // Add slider control if configured
          if (
            x.slider_control &&
            typeof window.MapglSliderControl === "function"
          ) {
            const _tsCfg = x.slider_control;
            const _ts = new window.MapglSliderControl(_tsCfg);
            map.addControl(_ts, _tsCfg.position || "top-left");
            map.controls.push({ type: "slider", control: _ts });
          }

          // Add geolocate control if enabled
          if (x.geolocate_control) {
            const geolocate = new maplibregl.GeolocateControl({
              positionOptions: x.geolocate_control.positionOptions,
              trackUserLocation: x.geolocate_control.trackUserLocation,
              showAccuracyCircle: x.geolocate_control.showAccuracyCircle,
              showUserLocation: x.geolocate_control.showUserLocation,
              showUserHeading: x.geolocate_control.showUserHeading,
              fitBoundsOptions: x.geolocate_control.fitBoundsOptions,
            });
            map.addControl(geolocate, x.geolocate_control.position);
            map.controls.push({ type: "geolocate", control: geolocate });

            if (HTMLWidgets.shinyMode) {
              geolocate.on("geolocate", function (event) {
                Shiny.setInputValue(el.id + "_geolocate", {
                  coords: event.coords,
                  time: new Date(),
                });
              });

              geolocate.on("trackuserlocationstart", function () {
                Shiny.setInputValue(el.id + "_geolocate_tracking", {
                  status: "start",
                  time: new Date(),
                });
              });

              geolocate.on("trackuserlocationend", function () {
                Shiny.setInputValue(el.id + "_geolocate_tracking", {
                  status: "end",
                  time: new Date(),
                });
              });

              geolocate.on("error", function (error) {
                if (error.error.code === 1) {
                  Shiny.setInputValue(el.id + "_geolocate_error", {
                    message: "Location permission denied",
                    time: new Date(),
                  });
                }
              });
            }
          }

          // Add navigation control if enabled
          if (x.navigation_control) {
            const nav = new maplibregl.NavigationControl({
              showCompass: x.navigation_control.show_compass,
              showZoom: x.navigation_control.show_zoom,
              visualizePitch: x.navigation_control.visualize_pitch,
            });
            map.addControl(nav, x.navigation_control.position);
            map.controls.push({ type: "navigation", control: nav });

            if (x.navigation_control.orientation === "horizontal") {
              const navBar = map
                .getContainer()
                .querySelector(
                  ".maplibregl-ctrl-group:not(.mapbox-gl-draw_ctrl-draw-btn)",
                );
              if (navBar) {
                navBar.style.display = "flex";
                navBar.style.flexDirection = "row";
              }
            }
          }

          // Add reset control if enabled
          if (x.reset_control) {
            const resetControl = document.createElement("button");
            resetControl.className =
              "maplibregl-ctrl-icon maplibregl-ctrl-reset";
            resetControl.type = "button";
            resetControl.setAttribute("aria-label", "Reset");
            resetControl.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>';
            resetControl.style.cssText = "display:flex;justify-content:center;align-items:center;cursor:pointer;";

            const resetContainer = document.createElement("div");
            resetContainer.className = "maplibregl-ctrl maplibregl-ctrl-group";
            resetContainer.appendChild(resetControl);

            // Initialize with empty object, will be populated after map loads
            let initialView = {};

            // Capture the initial view after the map has loaded and all view operations are complete
            map.once("load", function () {
              initialView = {
                center: map.getCenter(),
                zoom: map.getZoom(),
                pitch: map.getPitch(),
                bearing: map.getBearing(),
                animate: x.reset_control.animate,
              };

              if (x.reset_control.duration) {
                initialView.duration = x.reset_control.duration;
              }
            });

            resetControl.onclick = function () {
              // Only reset if we have captured the initial view
              if (initialView.center) {
                map.easeTo(initialView);
              }
            };

            const resetControlObj = {
              onAdd: function () {
                return resetContainer;
              },
              onRemove: function () {
                resetContainer.parentNode.removeChild(resetContainer);
              },
            };

            map.addControl(resetControlObj, x.reset_control.position);

            map.controls.push({ type: "reset", control: resetControlObj });
          }

          // Add screenshot control if enabled
          if (x.screenshot_control) {
            const screenshotControlObj = createScreenshotControl(map, x.screenshot_control, true);
            map.addControl(screenshotControlObj, x.screenshot_control.position || "top-right");
            map.controls.push({ type: "screenshot", control: screenshotControlObj });
          }

          // Add coordinates control if enabled
          if (x.coordinates_control) {
            const coordinatesControlObj = createCoordinatesControl(x.coordinates_control);
            map.addControl(
              coordinatesControlObj,
              x.coordinates_control.position || "bottom-right",
            );
            map.controls.push({ type: "coordinates", control: coordinatesControlObj });
          }

          if (x.images && Array.isArray(x.images)) {
            const mapId = el.id;
            x.images.forEach(async function (imageInfo) {
              try {
                // Register the image for potential re-adding after style changes
                registerUserImage(mapId, imageInfo.id, imageInfo.url, imageInfo.options);
                const image = await map.loadImage(imageInfo.url);
                if (!map.hasImage(imageInfo.id)) {
                  map.addImage(imageInfo.id, image.data, imageInfo.options);
                }
              } catch (error) {
                console.error("Error loading image:", error);
              }
            });
          } else if (x.images) {
            console.error("x.images is not an array:", x.images);
          }

          // Add the layers control if provided
          if (x.layers_control) {
            const layersControl = document.createElement("div");
            layersControl.id = x.layers_control.control_id;
            layersControl.className = x.layers_control.collapsible
              ? "layers-control collapsible"
              : "layers-control";
            layersControl.style.position = "absolute";

            // Set the position correctly - fix position bug by using correct CSS positioning
            const position = x.layers_control.position || "top-left";
            if (position === "top-left") {
              layersControl.style.top =
                (x.layers_control.margin_top || 10) + "px";
              layersControl.style.left =
                (x.layers_control.margin_left || 10) + "px";
            } else if (position === "top-right") {
              layersControl.style.top =
                (x.layers_control.margin_top || 10) + "px";
              layersControl.style.right =
                (x.layers_control.margin_right || 10) + "px";
            } else if (position === "bottom-left") {
              layersControl.style.bottom =
                (x.layers_control.margin_bottom || 10) + "px";
              layersControl.style.left =
                (x.layers_control.margin_left || 10) + "px";
            } else if (position === "bottom-right") {
              layersControl.style.bottom =
                (x.layers_control.margin_bottom || 40) + "px";
              layersControl.style.right =
                (x.layers_control.margin_right || 10) + "px";
            }

            // Apply custom colors if provided
            if (x.layers_control.custom_colors) {
              const colors = x.layers_control.custom_colors;

              // Create a style element for custom colors
              const styleEl = document.createElement("style");
              let css = "";

              if (colors.background) {
                css += `#${x.layers_control.control_id} { background-color: ${colors.background}; }\n`;
              }

              if (colors.text) {
                css += `#${x.layers_control.control_id} a { color: ${colors.text}; }\n`;
              }

              if (colors.active) {
                css += `#${x.layers_control.control_id} a.active { background-color: ${colors.active}; }\n`;
                css += `#${x.layers_control.control_id} .toggle-button { background-color: ${colors.active}; }\n`;
              }

              if (colors.activeText) {
                css += `#${x.layers_control.control_id} a.active { color: ${colors.activeText}; }\n`;
                css += `#${x.layers_control.control_id} .toggle-button { color: ${colors.activeText}; }\n`;
              }

              if (colors.hover) {
                css += `#${x.layers_control.control_id} a:hover { background-color: ${colors.hover}; }\n`;
                css += `#${x.layers_control.control_id} .toggle-button:hover { background-color: ${colors.hover}; }\n`;
              }

              styleEl.textContent = css;
              document.head.appendChild(styleEl);
            }

            el.appendChild(layersControl);

            const layersList = document.createElement("div");
            layersList.className = "layers-list";
            layersControl.appendChild(layersList);

            // Fetch layers to be included in the control
            let layers =
              x.layers_control.layers ||
              map.getStyle().layers.map((layer) => layer.id);
            let layersConfig = x.layers_control.layers_config;
            const getLayerControlVisibility = (layerId) => {
              if (
                window.MapGLFlowmapPlugin &&
                window.MapGLFlowmapPlugin.hasLayer(map, layerId)
              ) {
                return window.MapGLFlowmapPlugin.getVisibility(map, layerId);
              }
              return map.getLayoutProperty(layerId, "visibility") || "visible";
            };
            const setLayerControlVisibility = (layerId, visibility) => {
              if (
                window.MapGLFlowmapPlugin &&
                window.MapGLFlowmapPlugin.setVisibility(map, layerId, visibility)
              ) {
                return;
              }
              if (map.getLayer(layerId)) {
                map.setLayoutProperty(layerId, "visibility", visibility);
              }
            };

            // If we have a layers_config, use that; otherwise fall back to original behavior
            if (layersConfig && Array.isArray(layersConfig)) {
              layersConfig.forEach((config, index) => {
                const link = document.createElement("a");
                // Ensure config.ids is always an array
                const layerIds = Array.isArray(config.ids)
                  ? config.ids
                  : [config.ids];
                link.id = layerIds.join("-");
                link.href = "#";
                link.textContent = config.label;
                link.setAttribute("data-layer-ids", JSON.stringify(layerIds));
                link.setAttribute("data-layer-type", config.type);

                // Check if the first layer's visibility is set to "none" initially
                const firstLayerId = layerIds[0];
                const initialVisibility =
                  getLayerControlVisibility(firstLayerId);
                link.className = initialVisibility === "none" ? "" : "active";

                // Also hide any associated legends if the layer is initially hidden
                if (initialVisibility === "none") {
                  layerIds.forEach((layerId) => {
                    const associatedLegends = document.querySelectorAll(
                      `.mapboxgl-legend[data-layer-id="${layerId}"]`,
                    );
                    associatedLegends.forEach((legend) => {
                      legend.style.display = "none";
                    });
                  });
                }

                // Show or hide layer(s) when the toggle is clicked
                link.onclick = function (e) {
                  e.preventDefault();
                  e.stopPropagation();

                  const layerIds = JSON.parse(
                    this.getAttribute("data-layer-ids"),
                  );
                  const firstLayerId = layerIds[0];
                  const visibility = getLayerControlVisibility(firstLayerId);

                  // Toggle visibility for all layer IDs in the group
                  if (visibility === "visible") {
                    layerIds.forEach((layerId) => {
                      setLayerControlVisibility(layerId, "none");
                      // Hide associated legends
                      const associatedLegends = document.querySelectorAll(
                        `.mapboxgl-legend[data-layer-id="${layerId}"]`,
                      );
                      associatedLegends.forEach((legend) => {
                        legend.style.display = "none";
                      });
                    });
                    this.className = "";
                  } else {
                    layerIds.forEach((layerId) => {
                      setLayerControlVisibility(layerId, "visible");
                      // Show associated legends
                      const associatedLegends = document.querySelectorAll(
                        `.mapboxgl-legend[data-layer-id="${layerId}"]`,
                      );
                      associatedLegends.forEach((legend) => {
                        legend.style.display = "";
                      });
                    });
                    this.className = "active";
                  }
                };

                layersList.appendChild(link);
              });
            } else {
              // Fallback to original behavior for simple layer arrays
              // Ensure layers is always an array
              if (!Array.isArray(layers)) {
                layers = [layers];
              }

              layers.forEach((layerId, index) => {
                const link = document.createElement("a");
                link.id = layerId;
                link.href = "#";
                link.textContent = layerId;

                // Check if the layer visibility is set to "none" initially
                const initialVisibility = getLayerControlVisibility(layerId);
                link.className = initialVisibility === "none" ? "" : "active";

                // Also hide any associated legends if the layer is initially hidden
                if (initialVisibility === "none") {
                  const associatedLegends = document.querySelectorAll(
                    `.mapboxgl-legend[data-layer-id="${layerId}"]`,
                  );
                  associatedLegends.forEach((legend) => {
                    legend.style.display = "none";
                  });
                }

                // Show or hide layer when the toggle is clicked
                link.onclick = function (e) {
                  const clickedLayer = this.textContent;
                  e.preventDefault();
                  e.stopPropagation();

                  const visibility = getLayerControlVisibility(clickedLayer);

                  // Toggle layer visibility by changing the layout object's visibility property
                  if (visibility === "visible") {
                    setLayerControlVisibility(clickedLayer, "none");
                    this.className = "";

                    // Hide associated legends
                    const associatedLegends = document.querySelectorAll(
                      `.mapboxgl-legend[data-layer-id="${clickedLayer}"]`,
                    );
                    associatedLegends.forEach((legend) => {
                      legend.style.display = "none";
                    });
                  } else {
                    this.className = "active";
                    setLayerControlVisibility(clickedLayer, "visible");

                    // Show associated legends
                    const associatedLegends = document.querySelectorAll(
                      `.mapboxgl-legend[data-layer-id="${clickedLayer}"]`,
                    );
                    associatedLegends.forEach((legend) => {
                      legend.style.display = "";
                    });
                  }
                };

                layersList.appendChild(link);
              });
            }

            // Handle collapsible behavior
            if (x.layers_control.collapsible) {
              const toggleButton = document.createElement("div");
              toggleButton.className = "toggle-button";

              // Use stacked layers icon instead of text if requested
              if (x.layers_control.use_icon) {
                // Add icon-only class to the control for compact styling
                layersControl.classList.add("icon-only");

                // More GIS-like layers stack icon
                toggleButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                    <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                                    <polyline points="2 17 12 22 22 17"></polyline>
                                    <polyline points="2 12 12 17 22 12"></polyline>
                                </svg>`;
                toggleButton.style.display = "flex";
                toggleButton.style.alignItems = "center";
                toggleButton.style.justifyContent = "center";
              } else {
                toggleButton.textContent = "Layers";
              }

              toggleButton.onclick = function () {
                layersControl.classList.toggle("open");
              };
              layersControl.insertBefore(toggleButton, layersList);
            }
          }

            // Mark initial style as loaded to prevent control duplication on subsequent set_style() calls
            map._initialStyleLoaded = true;
          }

          // If clusters are present, attach event handling. Helper
          // auto-branches on source capability (native vs precomputed).
          map.getStyle().layers.forEach((layer) => {
            if (layer.id.includes("-clusters")) {
              _mapglAttachClusterHandlers(map, layer.id, layer.source);
            }
          });

          // Add click event listener in shinyMode
          if (HTMLWidgets.shinyMode) {
            map.on("click", function (e) {
              // Check if draw control is active and in a drawing mode
              let isDrawing = false;
              if (typeof draw !== "undefined" && draw) {
                const mode = draw.getMode();
                isDrawing =
                  mode === "draw_point" ||
                  mode === "draw_line_string" ||
                  mode === "draw_polygon";
              }

              // Only process feature clicks if not actively drawing
              if (!isDrawing) {
                const features = map.queryRenderedFeatures(e.point);

                if (features.length > 0) {
                  const feature = features[0];
                  Shiny.onInputChange(el.id + "_feature_click", {
                    id: feature.id,
                    properties: feature.properties,
                    layer: feature.layer.id,
                    lng: e.lngLat.lng,
                    lat: e.lngLat.lat,
                    time: new Date(),
                  });
                } else {
                  Shiny.onInputChange(el.id + "_feature_click", null);
                }
              }

              // Event listener for the map (always fire this)
              Shiny.onInputChange(el.id + "_click", {
                lng: e.lngLat.lng,
                lat: e.lngLat.lat,
                time: new Date(),
              });
            });

            // add hover listener for shinyMode if enabled
            if (x.hover_events && x.hover_events.enabled) {
              map.on("mousemove", function (e) {
                // Feature hover events
                if (x.hover_events.features) {
                  const options = x.hover_events.layer_id
                    ? {
                        layers: Array.isArray(x.hover_events.layer_id)
                          ? x.hover_events.layer_id
                          : x.hover_events.layer_id
                              .split(",")
                              .map((id) => id.trim()),
                      }
                    : undefined;
                  const features = map.queryRenderedFeatures(e.point, options);

                  if (features.length > 0) {
                    const feature = features[0];
                    Shiny.onInputChange(el.id + "_feature_hover", {
                      id: feature.id,
                      properties: feature.properties,
                      layer: feature.layer.id,
                      lng: e.lngLat.lng,
                      lat: e.lngLat.lat,
                      time: new Date(),
                    });
                  } else {
                    Shiny.onInputChange(el.id + "_feature_hover", null);
                  }
                }

                // Coordinate hover events
                if (x.hover_events.coordinates) {
                  Shiny.onInputChange(el.id + "_hover", {
                    lng: e.lngLat.lng,
                    lat: e.lngLat.lat,
                    time: new Date(),
                  });
                }
              });
            }
          }

          // Process turf operations for static maps
          if (x.turf_operations) {
            processTurfOperationsOnLoad(map, x.turf_operations, el.id);
          }

          el.map = map;
        });
        el.map = map;
      },

      getMap: function () {
        return map; // Return the map instance
      },

      getDraw: function () {
        return draw; // Return the draw instance
      },

      getDrawnFeatures: function () {
        return (
          this.drawFeatures || {
            type: "FeatureCollection",
            features: [],
          }
        );
      },

      resize: function (width, height) {
        if (map) {
          map.resize();
        }
      },
    };
  },
});

if (HTMLWidgets.shinyMode) {
  Shiny.addCustomMessageHandler("maplibre-proxy", async function (data) {
    var widget = HTMLWidgets.find("#" + data.id);
    if (!widget) return;
    var map = widget.getMap();
    if (map) {
      var message = data.message;

      // Initialize (or upgrade) layer state tracking via the shared helper.
      const mapId = map.getContainer().id;
      const layerState = _mapglEnsureLayerState(map);

      // Helper function to update drawn features
      function updateDrawnFeatures(debounce) {
        var drawControl = widget.drawControl || widget.getDraw();
        _mapglSyncDrawnFeatures({
          inputId: data.id,
          drawControl: drawControl,
          widget: widget,
          debounce: debounce,
        });
      }
      if (message.type === "set_filter") {
        // Route through the filter registry so `user` composes with
        // base/legend/slider slots.
        layerState.filterStack[message.layer] =
          layerState.filterStack[message.layer] || {};
        layerState.filterStack[message.layer].user = message.filter || null;
        _mapglComposeAndApplyFilter(map, message.layer);
      } else if (message.type === "add_h3t_sources") {
        (message.h3t_sources || []).forEach(function (source) {
          try {
            map.addH3TSource(source.id, {
              tiles: source.tiles,
              sourcelayer: source.sourcelayer,
              geometry_type: source.geometry_type,
              minzoom: source.minzoom,
              maxzoom: source.maxzoom,
              promoteId: source.promoteId,
              debug: source.debug,
            });
          } catch (e) {
            console.error("addH3TSource failed for", source.id, e);
          }
        });
      } else if (message.type === "add_h3j_sources") {
        (message.h3j_sources || []).forEach(async function (source) {
          try {
            await map.addH3JSource(source.id, { data: source.url });
          } catch (e) {
            console.error("addH3JSource failed for", source.id, e);
          }
        });
      } else if (message.type === "add_source") {
        if (message.source.type === "vector") {
          const sourceConfig = {
            type: "vector",
          };
          // Add url or tiles
          if (message.source.url) {
            sourceConfig.url = message.source.url;
            // Auto-detect MLT encoding for PMTiles sources
            if (
              message.source.url.startsWith("pmtiles://") &&
              typeof pmtiles !== "undefined" &&
              !message.source.encoding
            ) {
              try {
                const rawUrl = message.source.url.replace("pmtiles://", "");
                const p = new pmtiles.PMTiles(rawUrl);
                const header = await p.getHeader();
                if (header.tileType === pmtiles.TileType.Mlt) {
                  sourceConfig.encoding = "mlt";
                }
              } catch (e) {
                console.warn("Failed to detect PMTiles tile type:", e);
              }
            }
          }
          if (message.source.tiles) {
            sourceConfig.tiles = message.source.tiles;
          }
          // Add promoteId if provided
          if (message.source.promoteId) {
            sourceConfig.promoteId = message.source.promoteId;
          }
          // Add any other properties from the source object
          Object.keys(message.source).forEach(function (key) {
            if (
              key !== "id" &&
              key !== "type" &&
              key !== "url" &&
              key !== "tiles" &&
              key !== "promoteId"
            ) {
              sourceConfig[key] = message.source[key];
            }
          });
          map.addSource(message.source.id, sourceConfig);
        } else if (message.source.type === "geojson") {
          const sourceConfig = {
            type: "geojson",
            data: message.source.data,
          };
          // Add any other properties
          Object.keys(message.source).forEach(function (key) {
            if (key !== "id" && key !== "type" && key !== "data") {
              sourceConfig[key] = message.source[key];
            }
          });
          map.addSource(message.source.id, sourceConfig);
          // Store GeoJSON data for later retrieval (e.g., for draw control)
          storeSourceData(mapId, message.source.id, message.source.data);
        } else {
          // For other source types, pass through remaining properties
          const sourceConfig = { type: message.source.type };
          Object.keys(message.source).forEach(function (key) {
            if (key !== "id") {
              sourceConfig[key] = message.source[key];
            }
          });
          map.addSource(message.source.id, sourceConfig);
        }
      } else if (message.type === "add_layer") {
        try {
          // Ensure paint and layout are objects, not null
          if (message.layer.paint === null) {
            message.layer.paint = {};
          }
          if (message.layer.layout === null) {
            message.layer.layout = {};
          }
          if (message.layer.before_id) {
            map.addLayer(message.layer, message.layer.before_id);
          } else {
            map.addLayer(message.layer);
          }

          // Cluster click/cursor parity for layers added via proxy.
          if (
            message.layer.id &&
            message.layer.id.includes("-clusters")
          ) {
            _mapglAttachClusterHandlers(
              map,
              message.layer.id,
              message.layer.source,
            );
          }

          // Seed the filter registry for this late-added layer. If an
          // active slider targets this layer id, compose its filter
          // in immediately.
          layerState.filterStack[message.layer.id] =
            layerState.filterStack[message.layer.id] || {};
          layerState.filterStack[message.layer.id].base =
            message.layer.filter || null;
          const _ts = map._mapglSliderControl;
          if (
            _ts &&
            _ts.targetsLayer &&
            _ts.targetsLayer(message.layer.id)
          ) {
            layerState.filterStack[message.layer.id].slider =
              _ts.currentFilter();
            if (typeof _ts.captureAndApplyPaintForLayer === "function") {
              _ts.captureAndApplyPaintForLayer(message.layer.id);
            }
          }
          _mapglComposeAndApplyFilter(map, message.layer.id);

          // Add popups or tooltips if provided
          if (message.layer.popup) {
            // Initialize popup tracking if it doesn't exist
            if (!window._mapboxPopups) {
              window._mapboxPopups = {};
            }

            // Create click handler for this layer
            const clickHandler = function (e) {
              onClickPopup(
                e,
                map,
                message.layer.popup,
                message.layer.id,
                message.layer.popup_style,
              );
            };

            // Store these handler references so we can remove them later if needed
            if (!window._mapboxClickHandlers) {
              window._mapboxClickHandlers = {};
            }
            window._mapboxClickHandlers[message.layer.id] = clickHandler;

            // Add the click handler
            map.on("click", message.layer.id, clickHandler);

            // Change cursor to pointer when hovering over the layer
            map.on("mouseenter", message.layer.id, function () {
              map.getCanvas().style.cursor = "pointer";
            });

            // Change cursor back to default when leaving the layer
            map.on("mouseleave", message.layer.id, function () {
              map.getCanvas().style.cursor = "";
            });
          }

          if (message.layer.tooltip) {
            const tooltip = new maplibregl.Popup({
              closeButton: false,
              closeOnClick: false,
              maxWidth: "400px",
            });
            applyPopupClass(tooltip, message.layer.tooltip_style);

            // Define named handler functions:
            const mouseMoveHandler = function (e) {
              onMouseMoveTooltip(
                e,
                map,
                tooltip,
                message.layer.tooltip,
                message.layer.id,
              );
            };

            const mouseLeaveHandler = function () {
              onMouseLeaveTooltip(map, tooltip);
            };

            // Attach handlers by reference:
            map.on("mousemove", message.layer.id, mouseMoveHandler);
            map.on("mouseleave", message.layer.id, mouseLeaveHandler);

            // Store these handler references for later removal:
            if (!window._mapboxHandlers) {
              window._mapboxHandlers = {};
            }
            window._mapboxHandlers[message.layer.id] = {
              mousemove: mouseMoveHandler,
              mouseleave: mouseLeaveHandler,
            };
          }

          // Add hover effect if provided
          if (message.layer.hover_options) {
            const jsHoverOptions = {};
            for (const [key, value] of Object.entries(
              message.layer.hover_options,
            )) {
              const jsKey = key.replace(/_/g, "-");
              jsHoverOptions[jsKey] = value;
            }

            let hoveredFeatureId = null;

            map.on("mousemove", message.layer.id, function (e) {
              if (e.features.length > 0) {
                // Check if the feature has an id
                const featureId = e.features[0].id;

                // Only proceed if the feature has an id
                if (featureId !== undefined && featureId !== null) {
                  if (hoveredFeatureId !== null) {
                    const featureState = {
                      source:
                        typeof message.layer.source === "string"
                          ? message.layer.source
                          : message.layer.id,
                      id: hoveredFeatureId,
                    };
                    if (message.layer.source_layer) {
                      featureState.sourceLayer = message.layer.source_layer;
                    }
                    map.setFeatureState(featureState, { hover: false });
                  }
                  hoveredFeatureId = featureId;
                  const featureState = {
                    source:
                      typeof message.layer.source === "string"
                        ? message.layer.source
                        : message.layer.id,
                    id: hoveredFeatureId,
                  };
                  if (message.layer.source_layer) {
                    featureState.sourceLayer = message.layer.source_layer;
                  }
                  map.setFeatureState(featureState, { hover: true });
                }
              }
            });

            map.on("mouseleave", message.layer.id, function () {
              if (hoveredFeatureId !== null) {
                const featureState = {
                  source:
                    typeof message.layer.source === "string"
                      ? message.layer.source
                      : message.layer.id,
                  id: hoveredFeatureId,
                };
                if (message.layer.source_layer) {
                  featureState.sourceLayer = message.layer.source_layer;
                }
                map.setFeatureState(featureState, { hover: false });
              }
              hoveredFeatureId = null;
            });

            Object.keys(jsHoverOptions).forEach(function (key) {
              const originalPaint =
                map.getPaintProperty(message.layer.id, key) ||
                message.layer.paint[key];
              map.setPaintProperty(message.layer.id, key, [
                "case",
                ["boolean", ["feature-state", "hover"], false],
                jsHoverOptions[key],
                originalPaint,
              ]);
            });
          }
        } catch (e) {
          console.error("Failed to add layer via proxy: ", message.layer, e);
        }
      } else if (message.type === "remove_layer") {
        // If there's an active tooltip, remove it first
        if (window._activeTooltip) {
          window._activeTooltip.remove();
          delete window._activeTooltip;
        }

        // If there's an active popup for this layer, remove it
        // Check both message.layer and message.layer.id as keys due to different message formats
        if (window._mapboxPopups) {
          // First check if we have a popup stored with message.layer key
          if (window._mapboxPopups[message.layer]) {
            window._mapboxPopups[message.layer].remove();
            delete window._mapboxPopups[message.layer];
          }

          // Also check if we have a popup stored with message.layer.id key, which happens when added via add_layer
          if (
            message.layer &&
            message.layer.id &&
            window._mapboxPopups[message.layer.id]
          ) {
            window._mapboxPopups[message.layer.id].remove();
            delete window._mapboxPopups[message.layer.id];
          }
        }

        // Cascade: if this layer is the parent of a cluster_options
        // shortcut (siblings `-clusters` and `-cluster-count` exist),
        // remove those too. The shared source drops with the parent
        // layer below.
        ["-clusters", "-cluster-count"].forEach((suffix) => {
          const siblingId = message.layer + suffix;
          if (map.getLayer(siblingId)) {
            _mapglDetachClusterHandlers(map, siblingId);
            map.removeLayer(siblingId);
          }
        });

        if (map.getLayer(message.layer)) {
          // Remove tooltip handlers
          if (window._mapboxHandlers && window._mapboxHandlers[message.layer]) {
            const handlers = window._mapboxHandlers[message.layer];
            if (handlers.mousemove) {
              map.off("mousemove", message.layer, handlers.mousemove);
            }
            if (handlers.mouseleave) {
              map.off("mouseleave", message.layer, handlers.mouseleave);
            }
            // Clean up the reference
            delete window._mapboxHandlers[message.layer];
          }

          // Remove click handlers for popups
          if (window._mapboxClickHandlers) {
            // First check for handlers stored with message.layer key
            if (window._mapboxClickHandlers[message.layer]) {
              map.off(
                "click",
                message.layer,
                window._mapboxClickHandlers[message.layer],
              );
              delete window._mapboxClickHandlers[message.layer];
            }

            // Also check for handlers stored with message.layer.id key from add_layer
            if (
              message.layer &&
              message.layer.id &&
              window._mapboxClickHandlers[message.layer.id]
            ) {
              map.off(
                "click",
                message.layer,
                window._mapboxClickHandlers[message.layer.id],
              );
              delete window._mapboxClickHandlers[message.layer.id];
            }
          }

          // Tear down cluster click/cursor handlers if any were attached.
          _mapglDetachClusterHandlers(map, message.layer);

          // Remove the layer
          map.removeLayer(message.layer);
        }
        if (map.getSource(message.layer)) {
          map.removeSource(message.layer);
        }

        // Clean up tracked layer state
        if (window._mapglLayerState && window._mapglLayerState[mapId]) {
          const _ls = window._mapglLayerState[mapId];
          delete _ls.filters[message.layer];
          delete _ls.paintProperties[message.layer];
          delete _ls.layoutProperties[message.layer];
          delete _ls.tooltips[message.layer];
          delete _ls.popups[message.layer];
          delete _ls.filterStack[message.layer];
          // Note: legends are not tied to specific layers, so we don't clear them here
        }
      } else if (message.type === "fit_bounds") {
        map.fitBounds(message.bounds, message.options);
      } else if (message.type === "fly_to") {
        map.flyTo(message.options);
      } else if (message.type === "ease_to") {
        map.easeTo(message.options);
      } else if (message.type === "set_center") {
        map.setCenter(message.center);
      } else if (message.type === "set_zoom") {
        map.setZoom(message.zoom);
      } else if (message.type === "jump_to") {
        map.jumpTo(message.options);
      } else if (message.type === "set_layout_property") {
        map.setLayoutProperty(message.layer, message.name, message.value);
        // Track layout property state for layer restoration
        if (!layerState.layoutProperties[message.layer]) {
          layerState.layoutProperties[message.layer] = {};
        }
        layerState.layoutProperties[message.layer][message.name] =
          message.value;
      } else if (message.type === "set_flowmap_filter") {
        if (window.MapGLFlowmapPlugin) {
          window.MapGLFlowmapPlugin.setFilter(map, message.id, message.filter);
        }
      } else if (message.type === "set_flowmap_settings") {
        if (window.MapGLFlowmapPlugin) {
          window.MapGLFlowmapPlugin.setSettings(
            map,
            message.id,
            message.settings,
          );
        }
      } else if (message.type === "set_paint_property") {
        const layerId = message.layer;
        const propertyName = message.name;
        const newValue = message.value;

        // Check if the layer has hover options
        const layerStyle = map
          .getStyle()
          .layers.find((layer) => layer.id === layerId);
        const currentPaintProperty = map.getPaintProperty(
          layerId,
          propertyName,
        );

        if (
          currentPaintProperty &&
          Array.isArray(currentPaintProperty) &&
          currentPaintProperty[0] === "case"
        ) {
          // This property has hover options, so we need to preserve them
          const hoverValue = currentPaintProperty[2];
          const newPaintProperty = [
            "case",
            ["boolean", ["feature-state", "hover"], false],
            hoverValue,
            newValue,
          ];
          map.setPaintProperty(layerId, propertyName, newPaintProperty);
        } else {
          // No hover options, just set the new value directly
          map.setPaintProperty(layerId, propertyName, newValue);
        }
        // Track paint property state for layer restoration
        if (!layerState.paintProperties[layerId]) {
          layerState.paintProperties[layerId] = {};
        }
        layerState.paintProperties[layerId][propertyName] = newValue;
      } else if (message.type === "query_rendered_features") {
        // Query rendered features
        let queryOptions = {};
        if (message.layers) {
          // Ensure layers is always an array
          queryOptions.layers = Array.isArray(message.layers)
            ? message.layers
            : [message.layers];
        }
        if (message.filter) queryOptions.filter = message.filter;

        let features;
        if (message.geometry) {
          features = map.queryRenderedFeatures(message.geometry, queryOptions);
        } else {
          // No geometry specified - query entire viewport
          features = map.queryRenderedFeatures(queryOptions);
        }

        // Deduplicate features by id or by properties if no id
        const uniqueFeatures = new Map();
        features.forEach(function (feature) {
          let key;
          if (feature.id !== undefined && feature.id !== null) {
            key = feature.id;
          } else {
            // Create a key from properties if no id available
            key = JSON.stringify(feature.properties);
          }

          if (!uniqueFeatures.has(key)) {
            uniqueFeatures.set(key, feature);
          }
        });

        // Convert to GeoJSON FeatureCollection
        const deduplicatedFeatures = Array.from(uniqueFeatures.values());
        const featureCollection = {
          type: "FeatureCollection",
          features: deduplicatedFeatures,
        };

        Shiny.setInputValue(
          data.id + "_queried_features",
          JSON.stringify(featureCollection),
        );
      } else if (message.type === "add_legend") {
        // Extract legend ID from HTML to track it
        const legendIdMatch = message.html.match(/id="([^"]+)"/);
        const legendId = legendIdMatch ? legendIdMatch[1] : null;

        if (!message.add) {
          const existingLegends = document.querySelectorAll(
            `#${data.id} .mapboxgl-legend`,
          );
          existingLegends.forEach((legend) => legend.remove());

          // Clean up any existing legend styles that might have been added
          const legendStyles = document.querySelectorAll(
            `style[data-mapgl-legend-css="${data.id}"]`,
          );
          legendStyles.forEach((style) => style.remove());

          // Clear legend state when replacing all legends
          layerState.legends = {};
        }

        // Track legend state
        if (legendId) {
          layerState.legends[legendId] = {
            html: message.html,
            css: message.legend_css,
          };
        }

        const legendCss = document.createElement("style");
        legendCss.innerHTML = message.legend_css;
        legendCss.setAttribute("data-mapgl-legend-css", data.id); // Mark this style for later cleanup
        document.head.appendChild(legendCss);

        const legend = document.createElement("div");
        legend.innerHTML = message.html;
        legend.classList.add("mapboxgl-legend");
        document.getElementById(data.id).appendChild(legend);

        // Initialize legend interactivity if configured
        if (message.interactivity && typeof initializeLegendInteractivity === "function") {
          initializeLegendInteractivity(map, data.id, message.interactivity);
        }
      } else if (message.type === "set_config_property") {
        map.setConfigProperty(
          message.importId,
          message.configName,
          message.value,
        );
      } else if (message.type === "set_style") {
        // Default preserve_layers to true if not specified
        const preserveLayers = message.preserve_layers !== false;
        const mapId = map.getContainer().id;

        // Mark style as loading to queue any incoming operations
        window._mapgl.styleLoading[mapId] = true;
        console.log("[MapGL Debug] Style loading started for map:", mapId);

        console.log(
          "[MapGL Debug] set_style called with preserve_layers:",
          preserveLayers,
        );
        console.log(
          "[MapGL Debug] message.preserve_layers:",
          message.preserve_layers,
        );

        // If we should preserve layers and sources
        if (preserveLayers) {
          // Store the current style before changing it
          const currentStyle = map.getStyle();
          const userSourceIds = [];
          const userLayers = [];

          console.log(
            "[MapGL Debug] Current style sources:",
            Object.keys(currentStyle.sources),
          );
          console.log(
            "[MapGL Debug] Current style layers:",
            currentStyle.layers.map((l) => l.id),
          );

          // Store layer IDs we know were added by the user via R code
          // This is the most reliable way to identify user-added layers
          const knownUserLayerIds = [];

          // For each layer in the current style, determine if it's a user-added layer
          currentStyle.layers.forEach(function (layer) {
            const layerId = layer.id;

            // Critical: Check for nc_counties specifically since we know that's used in the test app
            if (layerId === "nc_counties") {
              console.log("[MapGL Debug] Found explicit test layer:", layerId);
              knownUserLayerIds.push(layerId);
              if (layer.source && !userSourceIds.includes(layer.source)) {
                console.log(
                  "[MapGL Debug] Found source from test layer:",
                  layer.source,
                );
                userSourceIds.push(layer.source);
              }
              return; // Skip other checks for this layer
            }

            // These are common patterns for user-added layers from R code
            if (
              // Specific layer IDs from the R package
              layerId.endsWith("_counties") ||
              layerId.endsWith("_label") ||
              layerId.endsWith("_layer") ||
              // Look for hover handlers - only user-added layers have these
              (window._mapboxHandlers && window._mapboxHandlers[layerId]) ||
              // If the layer ID contains these strings, it's likely user-added
              layerId.includes("user") ||
              layerId.includes("custom") ||
              // If the paint property has a hover case, it's user-added
              (layer.paint &&
                Object.values(layer.paint).some(
                  (value) =>
                    Array.isArray(value) &&
                    value[0] === "case" &&
                    Array.isArray(value[1]) &&
                    value[1][1] &&
                    Array.isArray(value[1][1]) &&
                    value[1][1][0] === "feature-state" &&
                    value[1][1][1] === "hover",
                ))
            ) {
              console.log("[MapGL Debug] Found user layer:", layerId);
              knownUserLayerIds.push(layerId);
              // Only include its source if it's not a base map source
              if (layer.source && !userSourceIds.includes(layer.source)) {
                const layerSource = currentStyle.sources[layer.source];
                const isBaseMapSource =
                  layerSource &&
                  layerSource.type === "vector" &&
                  (layer.source === "composite" ||
                    layer.source === "mapbox" ||
                    layer.source.startsWith("mapbox-") ||
                    layer.source === "openmaptiles" ||
                    layer.source.startsWith("carto") ||
                    layer.source.startsWith("maptiler"));

                if (!isBaseMapSource) {
                  console.log(
                    "[MapGL Debug] Found user source from layer:",
                    layer.source,
                  );
                  userSourceIds.push(layer.source);
                } else {
                  console.log(
                    "[MapGL Debug] Not adding base map source from layer:",
                    layer.source,
                  );
                }
              }
            }
          });

          // For each source, determine if it's a user-added source
          for (const sourceId in currentStyle.sources) {
            const source = currentStyle.sources[sourceId];

            console.log(
              "[MapGL Debug] Examining source:",
              sourceId,
              "type:",
              source.type,
            );

            // Strategy 1: All GeoJSON sources are likely user-added
            if (source.type === "geojson") {
              console.log("[MapGL Debug] Found user GeoJSON source:", sourceId);
              if (!userSourceIds.includes(sourceId)) {
                userSourceIds.push(sourceId);
              }
            }
            // Strategy 2: Check for source data URL patterns typical of R-generated data
            else if (
              source.url &&
              typeof source.url === "string" &&
              (source.url.includes("data:application/json") ||
                source.url.includes("blob:"))
            ) {
              console.log(
                "[MapGL Debug] Found user source with data URL:",
                sourceId,
              );
              if (!userSourceIds.includes(sourceId)) {
                userSourceIds.push(sourceId);
              }
            }
            // Strategy 3: Standard filtering - exclude common base map sources
            else if (
              sourceId !== "composite" &&
              sourceId !== "mapbox" &&
              !sourceId.startsWith("mapbox-") &&
              sourceId !== "openmaptiles" && // Common in MapLibre styles
              !(sourceId.startsWith("carto") && sourceId !== "carto-source") && // Filter CARTO base sources but keep user ones
              !(
                sourceId.startsWith("maptiler") && !sourceId.includes("user")
              ) && // Filter MapTiler sources but keep user ones
              !sourceId.includes("terrain") && // Common terrain sources
              !sourceId.includes("hillshade") && // Common hillshade sources
              !(sourceId.includes("basemap") && !sourceId.includes("user")) && // Filter basemap sources but keep user ones
              sourceId !== "satellite" && // Filter MapTiler satellite source specifically
              sourceId !== "aerial" // Filter aerial imagery sources
            ) {
              console.log(
                "[MapGL Debug] Found user source via filtering:",
                sourceId,
              );
              if (!userSourceIds.includes(sourceId)) {
                userSourceIds.push(sourceId);
              }
            } else {
              console.log(
                "[MapGL Debug] Filtered out base map source:",
                sourceId,
              );
            }

            // Store layer-specific handler references
            if (window._mapboxHandlers) {
              const handlers = window._mapboxHandlers;
              for (const layerId in handlers) {
                // Find layers associated with this source
                const layer = currentStyle.layers.find((l) => l.id === layerId);
                if (layer && layer.source === sourceId) {
                  layer._handlers = handlers[layerId];
                }
              }
            }
          }

          // Identify layers using user-added sources or known user layer IDs
          // ONLY include layers that use genuinely user-added sources (not base map sources)
          currentStyle.layers.forEach(function (layer) {
            // Check if this layer uses a genuine user source (not filtered out base map sources)
            const usesUserSource = userSourceIds.includes(layer.source);
            const isKnownUserLayer = knownUserLayerIds.includes(layer.id);

            // Additional check: exclude layers that use base map sources even if they were temporarily added to userSourceIds
            const layerSource = currentStyle.sources[layer.source];
            const isBaseMapSource =
              layerSource &&
              layerSource.type === "vector" &&
              (layer.source === "composite" ||
                layer.source === "mapbox" ||
                layer.source.startsWith("mapbox-") ||
                layer.source === "openmaptiles" ||
                layer.source.startsWith("carto") ||
                layer.source.startsWith("maptiler"));

            if ((usesUserSource || isKnownUserLayer) && !isBaseMapSource) {
              // Capture current visibility state (may differ from layer definition)
              const currentVisibility = map.getLayoutProperty(layer.id, 'visibility');
              if (currentVisibility !== undefined) {
                if (!layer.layout) {
                  layer.layout = {};
                }
                layer.layout.visibility = currentVisibility;
              }
              userLayers.push(layer);
              console.log(
                "[MapGL Debug] Including user layer:",
                layer.id,
                "source:",
                layer.source,
              );
            } else if (isBaseMapSource) {
              console.log(
                "[MapGL Debug] Excluding base map layer:",
                layer.id,
                "source:",
                layer.source,
              );
            }
          });

          // Log detected user sources and layers
          console.log("[MapGL Debug] Detected user sources:", userSourceIds);
          console.log(
            "[MapGL Debug] Detected user layers:",
            userLayers.map((l) => l.id),
          );
          console.log(
            "[MapGL Debug] Will preserve",
            userLayers.length,
            "user layers",
          );

          // Store them for potential use outside the onStyleLoad event
          // This helps in case the event timing is different in MapLibre
          if (!window._mapglPreservedData) {
            window._mapglPreservedData = {};
          }
          window._mapglPreservedData[map.getContainer().id] = {
            sources: userSourceIds.map((id) => ({
              id,
              source: currentStyle.sources[id],
            })),
            layers: userLayers,
          };

          // Set up event listener to re-add sources and layers after style loads
          const onStyleLoad = function () {
            console.log("[MapGL Debug] style.load event fired");

            // HACK: Reset layers control UI to show all layers as active
            const layersControl = document.querySelector('.layers-control');
            if (layersControl) {
              const layerLinks = layersControl.querySelectorAll('a');
              layerLinks.forEach(link => {
                link.className = 'active';
              });
            }

            try {
              // Re-add user sources
              userSourceIds.forEach(function (sourceId) {
                try {
                  if (!map.getSource(sourceId)) {
                    const source = currentStyle.sources[sourceId];
                    console.log("[MapGL Debug] Re-adding source:", sourceId);
                    map.addSource(sourceId, source);
                  }
                } catch (err) {
                  console.error(
                    "[MapGL Debug] Error re-adding source:",
                    sourceId,
                    err,
                  );
                }
              });

              // Re-add user layers
              userLayers.forEach(function (layer) {
                try {
                  if (!map.getLayer(layer.id)) {
                    console.log("[MapGL Debug] Re-adding layer:", layer.id);
                    map.addLayer(layer);

                    // Explicitly set visibility if it was set to 'none'
                    if (layer.layout && layer.layout.visibility === 'none') {
                      map.setLayoutProperty(layer.id, 'visibility', 'none');
                      console.log(`[MapGL Debug] Explicitly set ${layer.id} visibility to none`);
                    }

                    // Re-add event handlers for tooltips and hover effects
                    if (layer._handlers) {
                      const handlers = layer._handlers;

                      if (handlers.mousemove) {
                        console.log(
                          "[MapGL Debug] Re-adding mousemove handler for:",
                          layer.id,
                        );
                        map.on("mousemove", layer.id, handlers.mousemove);
                      }

                      if (handlers.mouseleave) {
                        console.log(
                          "[MapGL Debug] Re-adding mouseleave handler for:",
                          layer.id,
                        );
                        map.on("mouseleave", layer.id, handlers.mouseleave);
                      }
                    }

                    // Check if we need to restore tooltip handlers
                    const layerId = layer.id;
                    if (layerId === "nc_counties" || layer.tooltip) {
                      console.log(
                        "[MapGL Debug] Restoring tooltip for:",
                        layerId,
                      );

                      // Create a new tooltip popup
                      const tooltip = new maplibregl.Popup({
                        closeButton: false,
                        closeOnClick: false,
                        maxWidth: "400px",
                      });
                      applyPopupClass(tooltip, layer.tooltip_style);

                      // Re-add tooltip handlers
                      const tooltipProperty = layer.tooltip || "NAME";

                      const mouseMoveHandler = function (e) {
                        map.getCanvas().style.cursor = "pointer";
                        if (e.features.length > 0) {
                          // Use the shared resolver so {brace} templates and
                          // concat()/number_format() expressions keep working.
                          const description = resolveTooltipContent(
                            tooltipProperty,
                            e.features[0].properties,
                          );
                          tooltip
                            .setLngLat(e.lngLat)
                            .setHTML(description)
                            .addTo(map);
                        }
                      };

                      const mouseLeaveHandler = function () {
                        map.getCanvas().style.cursor = "";
                        tooltip.remove();
                      };

                      map.on("mousemove", layerId, mouseMoveHandler);
                      map.on("mouseleave", layerId, mouseLeaveHandler);

                      // Store these handlers
                      if (!window._mapboxHandlers) {
                        window._mapboxHandlers = {};
                      }
                      window._mapboxHandlers[layerId] = {
                        mousemove: mouseMoveHandler,
                        mouseleave: mouseLeaveHandler,
                      };
                    }

                    // Recreate hover states if needed
                    if (layer.paint) {
                      for (const key in layer.paint) {
                        const value = layer.paint[key];
                        if (
                          Array.isArray(value) &&
                          value[0] === "case" &&
                          Array.isArray(value[1]) &&
                          value[1][0] === "boolean" &&
                          value[1][1][0] === "feature-state" &&
                          value[1][1][1] === "hover"
                        ) {
                          // This is a hover-enabled paint property
                          map.setPaintProperty(layer.id, key, value);
                        }
                      }
                    }
                  }
                } catch (err) {
                  console.error(
                    "[MapGL Debug] Error re-adding layer:",
                    layer.id,
                    err,
                  );
                }
              });
            } catch (err) {
              console.error("[MapGL Debug] Error in style.load handler:", err);
            }

            // Clear any active tooltips before restoration to prevent stacking
            if (window._activeTooltip) {
              window._activeTooltip.remove();
              delete window._activeTooltip;
            }

            // Restore tracked layer modifications
            const mapId = map.getContainer().id;
            const savedLayerState =
              window._mapglLayerState && window._mapglLayerState[mapId];
            if (savedLayerState) {
              console.log(
                "[MapGL Debug] Restoring tracked layer modifications",
              );

              // Restore filters
              for (const layerId in savedLayerState.filters) {
                if (map.getLayer(layerId)) {
                  console.log(
                    "[MapGL Debug] Restoring filter for layer:",
                    layerId,
                  );
                  map.setFilter(layerId, savedLayerState.filters[layerId]);
                }
              }

              // Restore paint properties
              for (const layerId in savedLayerState.paintProperties) {
                if (map.getLayer(layerId)) {
                  const properties = savedLayerState.paintProperties[layerId];
                  for (const propertyName in properties) {
                    const savedValue = properties[propertyName];

                    console.log(
                      "[MapGL Debug] Restoring paint property:",
                      layerId,
                      propertyName,
                      savedValue,
                    );

                    // Check if layer has hover effects that need to be preserved
                    const currentValue = map.getPaintProperty(
                      layerId,
                      propertyName,
                    );
                    if (
                      currentValue &&
                      Array.isArray(currentValue) &&
                      currentValue[0] === "case"
                    ) {
                      // Preserve hover effects while updating base value
                      const hoverValue = currentValue[2];
                      const newPaintProperty = [
                        "case",
                        ["boolean", ["feature-state", "hover"], false],
                        hoverValue,
                        savedValue,
                      ];
                      map.setPaintProperty(
                        layerId,
                        propertyName,
                        newPaintProperty,
                      );
                    } else {
                      map.setPaintProperty(layerId, propertyName, savedValue);
                    }
                  }
                }
              }

              // Restore layout properties
              for (const layerId in savedLayerState.layoutProperties) {
                if (map.getLayer(layerId)) {
                  const properties = savedLayerState.layoutProperties[layerId];
                  for (const propertyName in properties) {
                    console.log(
                      "[MapGL Debug] Restoring layout property:",
                      layerId,
                      propertyName,
                      properties[propertyName],
                    );
                    map.setLayoutProperty(
                      layerId,
                      propertyName,
                      properties[propertyName],
                    );
                  }
                }
              }

              // Restore tooltips
              for (const layerId in savedLayerState.tooltips) {
                if (map.getLayer(layerId)) {
                  const tooltipProperty = savedLayerState.tooltips[layerId];
                  console.log(
                    "[MapGL Debug] Restoring tooltip:",
                    layerId,
                    tooltipProperty,
                  );

                  // Remove existing tooltip handlers first
                  if (
                    window._mapboxHandlers &&
                    window._mapboxHandlers[layerId]
                  ) {
                    if (window._mapboxHandlers[layerId].mousemove) {
                      map.off(
                        "mousemove",
                        layerId,
                        window._mapboxHandlers[layerId].mousemove,
                      );
                    }
                    if (window._mapboxHandlers[layerId].mouseleave) {
                      map.off(
                        "mouseleave",
                        layerId,
                        window._mapboxHandlers[layerId].mouseleave,
                      );
                    }
                  }

                  // Create new tooltip
                  const tooltip = new maplibregl.Popup({
                    closeButton: false,
                    closeOnClick: false,
                    maxWidth: "400px",
                  });
                  applyPopupClass(
                    tooltip,
                    (savedLayerState.tooltipStyles &&
                      savedLayerState.tooltipStyles[layerId]) ||
                      null,
                  );

                  const mouseMoveHandler = function (e) {
                    onMouseMoveTooltip(
                      e,
                      map,
                      tooltip,
                      tooltipProperty,
                      layerId,
                    );
                  };

                  const mouseLeaveHandler = function () {
                    onMouseLeaveTooltip(map, tooltip);
                  };

                  map.on("mousemove", layerId, mouseMoveHandler);
                  map.on("mouseleave", layerId, mouseLeaveHandler);

                  // Store handler references
                  if (!window._mapboxHandlers) {
                    window._mapboxHandlers = {};
                  }
                  window._mapboxHandlers[layerId] = {
                    mousemove: mouseMoveHandler,
                    mouseleave: mouseLeaveHandler,
                  };
                }
              }

              // Restore popups
              for (const layerId in savedLayerState.popups) {
                if (map.getLayer(layerId)) {
                  const popupProperty = savedLayerState.popups[layerId];
                  console.log(
                    "[MapGL Debug] Restoring popup:",
                    layerId,
                    popupProperty,
                  );

                  // Remove existing popup handlers first
                  if (
                    window._mapboxClickHandlers &&
                    window._mapboxClickHandlers[layerId]
                  ) {
                    map.off(
                      "click",
                      layerId,
                      window._mapboxClickHandlers[layerId],
                    );
                  }

                  // Create new popup handler
                  const clickHandler = function (e) {
                    onClickPopup(
                      e,
                      map,
                      popupProperty,
                      layerId,
                      (savedLayerState.popupStyles &&
                        savedLayerState.popupStyles[layerId]) ||
                        null,
                    );
                  };

                  map.on("click", layerId, clickHandler);

                  // Add hover effects for cursor
                  map.on("mouseenter", layerId, function () {
                    map.getCanvas().style.cursor = "pointer";
                  });
                  map.on("mouseleave", layerId, function () {
                    map.getCanvas().style.cursor = "";
                  });

                  // Store handler reference
                  if (!window._mapboxClickHandlers) {
                    window._mapboxClickHandlers = {};
                  }
                  window._mapboxClickHandlers[layerId] = clickHandler;
                }
              }

              // Restore legends
              if (Object.keys(savedLayerState.legends).length > 0) {
                // Clear any existing legends first to prevent stacking
                const existingLegends = document.querySelectorAll(
                  `#${mapId} .mapboxgl-legend`,
                );
                existingLegends.forEach((legend) => legend.remove());

                // Clear existing legend styles
                const legendStyles = document.querySelectorAll(
                  `style[data-mapgl-legend-css="${mapId}"]`,
                );
                legendStyles.forEach((style) => style.remove());

                // Restore each legend
                for (const legendId in savedLayerState.legends) {
                  const legendData = savedLayerState.legends[legendId];
                  console.log("[MapGL Debug] Restoring legend:", legendId);

                  // Add legend CSS
                  const legendCss = document.createElement("style");
                  legendCss.innerHTML = legendData.css;
                  legendCss.setAttribute("data-mapgl-legend-css", mapId);
                  document.head.appendChild(legendCss);

                  // Add legend HTML
                  const legend = document.createElement("div");
                  legend.innerHTML = legendData.html;
                  legend.classList.add("mapboxgl-legend");
                  const mapContainer = document.getElementById(mapId);
                  if (mapContainer) {
                    mapContainer.appendChild(legend);
                  }
                }
              }
            }

            // Re-add user images after style change
            reAddUserImages(map, mapId);

            // Mark style loading as complete and execute any pending operations
            window._mapgl.styleLoading[mapId] = false;
            console.log("[MapGL Debug] Style loading completed for map:", mapId);
            executePendingOperations(mapId);

          };

          map.once("style.load", function() {
            // Wait for map to be fully idle before adding layers
            map.once("idle", onStyleLoad);
          });

          // Add a backup mechanism specific to MapLibre
          // Some MapLibre styles or versions may have different event timing
          if (userLayers.length > 0) {
            // Set a timeout to check if layers were added after a reasonable delay
            setTimeout(function () {
              try {
                console.log("[MapGL Debug] Running backup layer check");
                const mapId = map.getContainer().id;
                const preserved =
                  window._mapglPreservedData &&
                  window._mapglPreservedData[mapId];

                if (preserved) {
                  // Check if user layers were successfully restored
                  const firstLayerId = preserved.layers[0]?.id;
                  if (firstLayerId && !map.getLayer(firstLayerId)) {
                    console.log(
                      "[MapGL Debug] Backup restoration needed for layers",
                    );

                    // Re-add sources first
                    preserved.sources.forEach(function (src) {
                      try {
                        if (!map.getSource(src.id)) {
                          console.log(
                            "[MapGL Debug] Backup: adding source",
                            src.id,
                          );
                          map.addSource(src.id, src.source);
                        }
                      } catch (err) {
                        console.error(
                          "[MapGL Debug] Backup: error adding source",
                          src.id,
                          err,
                        );
                      }
                    });

                    // Then re-add layers
                    preserved.layers.forEach(function (layer) {
                      try {
                        if (!map.getLayer(layer.id)) {
                          console.log(
                            "[MapGL Debug] Backup: adding layer",
                            layer.id,
                          );
                          map.addLayer(layer);

                          // Check for nc_counties layer to restore tooltip
                          if (layer.id === "nc_counties") {
                            console.log(
                              "[MapGL Debug] Backup: restoring tooltip for",
                              layer.id,
                            );

                            // Create a new tooltip popup
                            const tooltip = new maplibregl.Popup({
                              closeButton: false,
                              closeOnClick: false,
                              maxWidth: "400px",
                            });

                            // Re-add tooltip handlers
                            const tooltipProperty = "NAME";

                            const mouseMoveHandler = function (e) {
                              map.getCanvas().style.cursor = "pointer";
                              if (e.features.length > 0) {
                                const description =
                                  e.features[0].properties[tooltipProperty];
                                tooltip
                                  .setLngLat(e.lngLat)
                                  .setHTML(description)
                                  .addTo(map);
                              }
                            };

                            const mouseLeaveHandler = function () {
                              map.getCanvas().style.cursor = "";
                              tooltip.remove();
                            };

                            map.on("mousemove", layer.id, mouseMoveHandler);
                            map.on("mouseleave", layer.id, mouseLeaveHandler);

                            // Store these handlers
                            if (!window._mapboxHandlers) {
                              window._mapboxHandlers = {};
                            }
                            window._mapboxHandlers[layer.id] = {
                              mousemove: mouseMoveHandler,
                              mouseleave: mouseLeaveHandler,
                            };
                          }

                          // Restore hover states
                          if (layer.paint) {
                            for (const key in layer.paint) {
                              const value = layer.paint[key];
                              if (
                                Array.isArray(value) &&
                                value[0] === "case" &&
                                Array.isArray(value[1]) &&
                                value[1][0] === "boolean" &&
                                value[1][1] &&
                                Array.isArray(value[1][1]) &&
                                value[1][1][0] === "feature-state" &&
                                value[1][1][1] === "hover"
                              ) {
                                // This is a hover-enabled paint property
                                console.log(
                                  "[MapGL Debug] Backup: restoring hover style for",
                                  layer.id,
                                  key,
                                );
                                map.setPaintProperty(layer.id, key, value);
                              }
                            }
                          }
                        }
                      } catch (err) {
                        console.error(
                          "[MapGL Debug] Backup: error adding layer",
                          layer.id,
                          err,
                        );
                      }
                    });

                    // Restore tracked layer modifications in backup
                    const mapId = map.getContainer().id;
                    const savedLayerState =
                      window._mapglLayerState && window._mapglLayerState[mapId];
                    if (savedLayerState) {
                      console.log(
                        "[MapGL Debug] Backup: restoring tracked layer modifications",
                      );

                      // Restore filters
                      for (const layerId in savedLayerState.filters) {
                        if (map.getLayer(layerId)) {
                          console.log(
                            "[MapGL Debug] Backup: restoring filter for layer:",
                            layerId,
                          );
                          map.setFilter(
                            layerId,
                            savedLayerState.filters[layerId],
                          );
                        }
                      }

                      // Restore paint properties
                      for (const layerId in savedLayerState.paintProperties) {
                        if (map.getLayer(layerId)) {
                          const properties =
                            savedLayerState.paintProperties[layerId];
                          for (const propertyName in properties) {
                            const savedValue = properties[propertyName];
                            console.log(
                              "[MapGL Debug] Backup: restoring paint property:",
                              layerId,
                              propertyName,
                              savedValue,
                            );

                            // Check if layer has hover effects that need to be preserved
                            const currentValue = map.getPaintProperty(
                              layerId,
                              propertyName,
                            );
                            if (
                              currentValue &&
                              Array.isArray(currentValue) &&
                              currentValue[0] === "case"
                            ) {
                              // Preserve hover effects while updating base value
                              const hoverValue = currentValue[2];
                              const newPaintProperty = [
                                "case",
                                ["boolean", ["feature-state", "hover"], false],
                                hoverValue,
                                savedValue,
                              ];
                              map.setPaintProperty(
                                layerId,
                                propertyName,
                                newPaintProperty,
                              );
                            } else {
                              map.setPaintProperty(
                                layerId,
                                propertyName,
                                savedValue,
                              );
                            }
                          }
                        }
                      }

                      // Restore layout properties
                      for (const layerId in savedLayerState.layoutProperties) {
                        if (map.getLayer(layerId)) {
                          const properties =
                            savedLayerState.layoutProperties[layerId];
                          for (const propertyName in properties) {
                            console.log(
                              "[MapGL Debug] Backup: restoring layout property:",
                              layerId,
                              propertyName,
                              properties[propertyName],
                            );
                            map.setLayoutProperty(
                              layerId,
                              propertyName,
                              properties[propertyName],
                            );
                          }
                        }
                      }

                      // Restore tooltips
                      for (const layerId in savedLayerState.tooltips) {
                        if (map.getLayer(layerId)) {
                          const tooltipProperty =
                            savedLayerState.tooltips[layerId];
                          console.log(
                            "[MapGL Debug] Backup: restoring tooltip:",
                            layerId,
                            tooltipProperty,
                          );

                          if (
                            window._mapboxHandlers &&
                            window._mapboxHandlers[layerId]
                          ) {
                            if (window._mapboxHandlers[layerId].mousemove) {
                              map.off(
                                "mousemove",
                                layerId,
                                window._mapboxHandlers[layerId].mousemove,
                              );
                            }
                            if (window._mapboxHandlers[layerId].mouseleave) {
                              map.off(
                                "mouseleave",
                                layerId,
                                window._mapboxHandlers[layerId].mouseleave,
                              );
                            }
                          }

                          const tooltip = new maplibregl.Popup({
                            closeButton: false,
                            closeOnClick: false,
                            maxWidth: "400px",
                          });
                          applyPopupClass(
                            tooltip,
                            (savedLayerState.tooltipStyles &&
                              savedLayerState.tooltipStyles[layerId]) ||
                              null,
                          );

                          const mouseMoveHandler = function (e) {
                            onMouseMoveTooltip(
                              e,
                              map,
                              tooltip,
                              tooltipProperty,
                              layerId,
                            );
                          };

                          const mouseLeaveHandler = function () {
                            onMouseLeaveTooltip(map, tooltip);
                          };

                          map.on("mousemove", layerId, mouseMoveHandler);
                          map.on("mouseleave", layerId, mouseLeaveHandler);

                          if (!window._mapboxHandlers) {
                            window._mapboxHandlers = {};
                          }
                          window._mapboxHandlers[layerId] = {
                            mousemove: mouseMoveHandler,
                            mouseleave: mouseLeaveHandler,
                          };
                        }
                      }

                      // Restore popups
                      for (const layerId in savedLayerState.popups) {
                        if (map.getLayer(layerId)) {
                          const popupProperty = savedLayerState.popups[layerId];
                          console.log(
                            "[MapGL Debug] Backup: restoring popup:",
                            layerId,
                            popupProperty,
                          );

                          if (
                            window._mapboxClickHandlers &&
                            window._mapboxClickHandlers[layerId]
                          ) {
                            map.off(
                              "click",
                              layerId,
                              window._mapboxClickHandlers[layerId],
                            );
                          }

                          const clickHandler = function (e) {
                            onClickPopup(
                              e,
                              map,
                              popupProperty,
                              layerId,
                              (savedLayerState.popupStyles &&
                                savedLayerState.popupStyles[layerId]) ||
                                null,
                            );
                          };

                          map.on("click", layerId, clickHandler);
                          map.on("mouseenter", layerId, function () {
                            map.getCanvas().style.cursor = "pointer";
                          });
                          map.on("mouseleave", layerId, function () {
                            map.getCanvas().style.cursor = "";
                          });

                          if (!window._mapboxClickHandlers) {
                            window._mapboxClickHandlers = {};
                          }
                          window._mapboxClickHandlers[layerId] = clickHandler;
                        }
                      }

                      // Restore legends
                      if (Object.keys(savedLayerState.legends).length > 0) {
                        // Clear any existing legends first to prevent stacking
                        const existingLegends = document.querySelectorAll(
                          `#${mapId} .mapboxgl-legend`,
                        );
                        existingLegends.forEach((legend) => legend.remove());

                        // Clear existing legend styles
                        const legendStyles = document.querySelectorAll(
                          `style[data-mapgl-legend-css="${mapId}"]`,
                        );
                        legendStyles.forEach((style) => style.remove());

                        // Restore each legend
                        for (const legendId in savedLayerState.legends) {
                          const legendData = savedLayerState.legends[legendId];
                          console.log(
                            "[MapGL Debug] Backup: restoring legend:",
                            legendId,
                          );

                          // Add legend CSS
                          const legendCss = document.createElement("style");
                          legendCss.innerHTML = legendData.css;
                          legendCss.setAttribute(
                            "data-mapgl-legend-css",
                            mapId,
                          );
                          document.head.appendChild(legendCss);

                          // Add legend HTML
                          const legend = document.createElement("div");
                          legend.innerHTML = legendData.html;
                          legend.classList.add("mapboxgl-legend");
                          const mapContainer = document.getElementById(mapId);
                          if (mapContainer) {
                            mapContainer.appendChild(legend);
                          }
                        }
                      }
                    }
                  } else {
                    console.log(
                      "[MapGL Debug] Backup check: layers already restored properly",
                    );
                  }
                }
              } catch (err) {
                console.error(
                  "[MapGL Debug] Error in backup restoration:",
                  err,
                );
              }
            }, 500); // 500ms delay - faster recovery

            // Add a second backup with a bit more delay in case the first one fails
            setTimeout(function () {
              try {
                console.log("[MapGL Debug] Running second backup layer check");
                const mapId = map.getContainer().id;
                const preserved =
                  window._mapglPreservedData &&
                  window._mapglPreservedData[mapId];

                if (preserved) {
                  // Check if user layers were successfully restored
                  const firstLayerId = preserved.layers[0]?.id;
                  if (firstLayerId && !map.getLayer(firstLayerId)) {
                    console.log(
                      "[MapGL Debug] Second backup restoration needed",
                    );

                    // Re-add sources first
                    preserved.sources.forEach(function (src) {
                      try {
                        if (!map.getSource(src.id)) {
                          console.log(
                            "[MapGL Debug] Second backup: adding source",
                            src.id,
                          );
                          map.addSource(src.id, src.source);
                        }
                      } catch (err) {
                        console.error(
                          "[MapGL Debug] Second backup: error adding source",
                          src.id,
                          err,
                        );
                      }
                    });

                    // Then re-add layers
                    preserved.layers.forEach(function (layer) {
                      try {
                        if (!map.getLayer(layer.id)) {
                          console.log(
                            "[MapGL Debug] Second backup: adding layer",
                            layer.id,
                          );
                          map.addLayer(layer);

                          // Check for nc_counties layer to restore tooltip
                          if (layer.id === "nc_counties") {
                            console.log(
                              "[MapGL Debug] Second backup: restoring tooltip for",
                              layer.id,
                            );

                            // Create a new tooltip popup
                            const tooltip = new maplibregl.Popup({
                              closeButton: false,
                              closeOnClick: false,
                              maxWidth: "400px",
                            });

                            // Re-add tooltip handlers
                            const tooltipProperty = "NAME";

                            const mouseMoveHandler = function (e) {
                              map.getCanvas().style.cursor = "pointer";
                              if (e.features.length > 0) {
                                const description =
                                  e.features[0].properties[tooltipProperty];
                                tooltip
                                  .setLngLat(e.lngLat)
                                  .setHTML(description)
                                  .addTo(map);
                              }
                            };

                            const mouseLeaveHandler = function () {
                              map.getCanvas().style.cursor = "";
                              tooltip.remove();
                            };

                            map.on("mousemove", layer.id, mouseMoveHandler);
                            map.on("mouseleave", layer.id, mouseLeaveHandler);

                            // Store these handlers
                            if (!window._mapboxHandlers) {
                              window._mapboxHandlers = {};
                            }
                            window._mapboxHandlers[layer.id] = {
                              mousemove: mouseMoveHandler,
                              mouseleave: mouseLeaveHandler,
                            };
                          }

                          // Restore hover states
                          if (layer.paint) {
                            for (const key in layer.paint) {
                              const value = layer.paint[key];
                              if (
                                Array.isArray(value) &&
                                value[0] === "case" &&
                                Array.isArray(value[1]) &&
                                value[1][0] === "boolean" &&
                                value[1][1] &&
                                Array.isArray(value[1][1]) &&
                                value[1][1][0] === "feature-state" &&
                                value[1][1][1] === "hover"
                              ) {
                                // This is a hover-enabled paint property
                                console.log(
                                  "[MapGL Debug] Second backup: restoring hover style for",
                                  layer.id,
                                  key,
                                );
                                map.setPaintProperty(layer.id, key, value);
                              }
                            }
                          }
                        }
                      } catch (err) {
                        console.error(
                          "[MapGL Debug] Second backup: error adding layer",
                          layer.id,
                          err,
                        );
                      }
                    });

                    // Restore tracked layer modifications in second backup
                    const mapId = map.getContainer().id;
                    const savedLayerState =
                      window._mapglLayerState && window._mapglLayerState[mapId];
                    if (savedLayerState) {
                      console.log(
                        "[MapGL Debug] Second backup: restoring tracked layer modifications",
                      );

                      // Restore filters
                      for (const layerId in savedLayerState.filters) {
                        if (map.getLayer(layerId)) {
                          console.log(
                            "[MapGL Debug] Second backup: restoring filter for layer:",
                            layerId,
                          );
                          map.setFilter(
                            layerId,
                            savedLayerState.filters[layerId],
                          );
                        }
                      }

                      // Restore paint properties
                      for (const layerId in savedLayerState.paintProperties) {
                        if (map.getLayer(layerId)) {
                          const properties =
                            savedLayerState.paintProperties[layerId];
                          for (const propertyName in properties) {
                            const savedValue = properties[propertyName];
                            console.log(
                              "[MapGL Debug] Second backup: restoring paint property:",
                              layerId,
                              propertyName,
                              savedValue,
                            );

                            // Check if layer has hover effects that need to be preserved
                            const currentValue = map.getPaintProperty(
                              layerId,
                              propertyName,
                            );
                            if (
                              currentValue &&
                              Array.isArray(currentValue) &&
                              currentValue[0] === "case"
                            ) {
                              // Preserve hover effects while updating base value
                              const hoverValue = currentValue[2];
                              const newPaintProperty = [
                                "case",
                                ["boolean", ["feature-state", "hover"], false],
                                hoverValue,
                                savedValue,
                              ];
                              map.setPaintProperty(
                                layerId,
                                propertyName,
                                newPaintProperty,
                              );
                            } else {
                              map.setPaintProperty(
                                layerId,
                                propertyName,
                                savedValue,
                              );
                            }
                          }
                        }
                      }

                      // Restore layout properties
                      for (const layerId in savedLayerState.layoutProperties) {
                        if (map.getLayer(layerId)) {
                          const properties =
                            savedLayerState.layoutProperties[layerId];
                          for (const propertyName in properties) {
                            console.log(
                              "[MapGL Debug] Second backup: restoring layout property:",
                              layerId,
                              propertyName,
                              properties[propertyName],
                            );
                            map.setLayoutProperty(
                              layerId,
                              propertyName,
                              properties[propertyName],
                            );
                          }
                        }
                      }

                      // Restore tooltips
                      for (const layerId in savedLayerState.tooltips) {
                        if (map.getLayer(layerId)) {
                          const tooltipProperty =
                            savedLayerState.tooltips[layerId];
                          console.log(
                            "[MapGL Debug] Second backup: restoring tooltip:",
                            layerId,
                            tooltipProperty,
                          );

                          if (
                            window._mapboxHandlers &&
                            window._mapboxHandlers[layerId]
                          ) {
                            if (window._mapboxHandlers[layerId].mousemove) {
                              map.off(
                                "mousemove",
                                layerId,
                                window._mapboxHandlers[layerId].mousemove,
                              );
                            }
                            if (window._mapboxHandlers[layerId].mouseleave) {
                              map.off(
                                "mouseleave",
                                layerId,
                                window._mapboxHandlers[layerId].mouseleave,
                              );
                            }
                          }

                          const tooltip = new maplibregl.Popup({
                            closeButton: false,
                            closeOnClick: false,
                            maxWidth: "400px",
                          });
                          applyPopupClass(
                            tooltip,
                            (savedLayerState.tooltipStyles &&
                              savedLayerState.tooltipStyles[layerId]) ||
                              null,
                          );

                          const mouseMoveHandler = function (e) {
                            onMouseMoveTooltip(
                              e,
                              map,
                              tooltip,
                              tooltipProperty,
                              layerId,
                            );
                          };

                          const mouseLeaveHandler = function () {
                            onMouseLeaveTooltip(map, tooltip);
                          };

                          map.on("mousemove", layerId, mouseMoveHandler);
                          map.on("mouseleave", layerId, mouseLeaveHandler);

                          if (!window._mapboxHandlers) {
                            window._mapboxHandlers = {};
                          }
                          window._mapboxHandlers[layerId] = {
                            mousemove: mouseMoveHandler,
                            mouseleave: mouseLeaveHandler,
                          };
                        }
                      }

                      // Restore popups
                      for (const layerId in savedLayerState.popups) {
                        if (map.getLayer(layerId)) {
                          const popupProperty = savedLayerState.popups[layerId];
                          console.log(
                            "[MapGL Debug] Second backup: restoring popup:",
                            layerId,
                            popupProperty,
                          );

                          if (
                            window._mapboxClickHandlers &&
                            window._mapboxClickHandlers[layerId]
                          ) {
                            map.off(
                              "click",
                              layerId,
                              window._mapboxClickHandlers[layerId],
                            );
                          }

                          const clickHandler = function (e) {
                            onClickPopup(
                              e,
                              map,
                              popupProperty,
                              layerId,
                              (savedLayerState.popupStyles &&
                                savedLayerState.popupStyles[layerId]) ||
                                null,
                            );
                          };

                          map.on("click", layerId, clickHandler);
                          map.on("mouseenter", layerId, function () {
                            map.getCanvas().style.cursor = "pointer";
                          });
                          map.on("mouseleave", layerId, function () {
                            map.getCanvas().style.cursor = "";
                          });

                          if (!window._mapboxClickHandlers) {
                            window._mapboxClickHandlers = {};
                          }
                          window._mapboxClickHandlers[layerId] = clickHandler;
                        }
                      }

                      // Restore legends
                      if (Object.keys(savedLayerState.legends).length > 0) {
                        // Clear any existing legends first to prevent stacking
                        const existingLegends = document.querySelectorAll(
                          `#${mapId} .mapboxgl-legend`,
                        );
                        existingLegends.forEach((legend) => legend.remove());

                        // Clear existing legend styles
                        const legendStyles = document.querySelectorAll(
                          `style[data-mapgl-legend-css="${mapId}"]`,
                        );
                        legendStyles.forEach((style) => style.remove());

                        // Restore each legend
                        for (const legendId in savedLayerState.legends) {
                          const legendData = savedLayerState.legends[legendId];
                          console.log(
                            "[MapGL Debug] Second backup: restoring legend:",
                            legendId,
                          );

                          // Add legend CSS
                          const legendCss = document.createElement("style");
                          legendCss.innerHTML = legendData.css;
                          legendCss.setAttribute(
                            "data-mapgl-legend-css",
                            mapId,
                          );
                          document.head.appendChild(legendCss);

                          // Add legend HTML
                          const legend = document.createElement("div");
                          legend.innerHTML = legendData.html;
                          legend.classList.add("mapboxgl-legend");
                          const mapContainer = document.getElementById(mapId);
                          if (mapContainer) {
                            mapContainer.appendChild(legend);
                          }
                        }
                      }
                    }
                  }
                }
              } catch (err) {
                console.error("[MapGL Debug] Error in second backup:", err);
              }
            }, 1000); // 1 second delay for second backup
          }
        }

        // Change the style
        console.log(
          "[MapGL Debug] About to call setStyle with:",
          message.style,
        );
        console.log("[MapGL Debug] setStyle diff option:", message.diff);
        map.setStyle(message.style, { diff: message.diff });

        if (message.config) {
          Object.keys(message.config).forEach(function (key) {
            map.setConfigProperty("basemap", key, message.config[key]);
          });
        }

        // For non-preserve mode, still need to handle style loading completion
        // to re-add images and execute pending operations
        if (!preserveLayers) {
          map.once("style.load", function() {
            map.once("idle", function() {
              // Re-add user images after style change
              reAddUserImages(map, mapId);

              // Mark style loading as complete and execute any pending operations
              window._mapgl.styleLoading[mapId] = false;
              console.log("[MapGL Debug] Style loading completed (non-preserve) for map:", mapId);
              executePendingOperations(mapId);
            });
          });
        }
      } else if (message.type === "add_navigation_control") {
        const nav = new maplibregl.NavigationControl({
          showCompass: message.options.show_compass,
          showZoom: message.options.show_zoom,
          visualizePitch: message.options.visualize_pitch,
        });
        map.addControl(nav, message.position);
        map.controls.push({ type: "navigation", control: nav });

        if (message.orientation === "horizontal") {
          const navBar = map
            .getContainer()
            .querySelector(
              ".maplibregl-ctrl-group:not(.mapbox-gl-draw_ctrl-draw-btn)",
            );
          if (navBar) {
            navBar.style.display = "flex";
            navBar.style.flexDirection = "row";
          }
        }
      } else if (message.type === "add_draw_control") {
        MapboxDraw.constants.classes.CONTROL_BASE = "maplibregl-ctrl";
        MapboxDraw.constants.classes.CONTROL_PREFIX = "maplibregl-ctrl-";
        MapboxDraw.constants.classes.CONTROL_GROUP = "maplibregl-ctrl-group";

        let drawOptions = message.options || {};

        // Generate styles if styling parameters provided
        if (message.styling) {
          const generatedStyles = generateDrawStyles(message.styling);
          if (generatedStyles) {
            drawOptions.styles = generatedStyles;
          }
        }

        if (message.freehand) {
          drawOptions = Object.assign({}, drawOptions, {
            modes: Object.assign({}, MapboxDraw.modes, {
              draw_polygon: MapboxDraw.modes.draw_freehand,
            }),
            // defaultMode: 'draw_polygon' # Don't set the default yet
          });
        }

        // Add rectangle mode if enabled
        if (message.rectangle) {
          drawOptions.modes = Object.assign(
            {},
            drawOptions.modes || MapboxDraw.modes,
            {
              draw_rectangle: MapboxDraw.modes.draw_rectangle,
            },
          );
        }

        // Add radius mode if enabled
        if (message.radius) {
          drawOptions.modes = Object.assign(
            {},
            drawOptions.modes || MapboxDraw.modes,
            {
              draw_radius: MapboxDraw.modes.draw_radius,
            },
          );
        }

        if (message.bezier || message.bezier_polygon) {
          drawOptions = enableBezierDrawMode(drawOptions, message.styling);
        }

        if (_mapglHasDrawAttributes(message.attributes)) {
          drawOptions = Object.assign({}, drawOptions, {
            userProperties: true,
          });
        }

        // Create the draw control
        var drawControl = new MapboxDraw(drawOptions);
        map.addControl(drawControl, message.position);
        map.controls.push({ type: "draw", control: drawControl });

        // Store the draw control on the widget for later access
        widget.drawControl = drawControl;

        // Add lasso icon CSS for freehand mode
        if (message.freehand) {
          if (!document.querySelector("#mapgl-freehand-lasso-styles")) {
            const style = document.createElement("style");
            style.id = "mapgl-freehand-lasso-styles";
            style.textContent = `
              .mapbox-gl-draw_polygon {
                background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"%3E%3Cpath d="M 7 3 C 5 2.5, 3.5 3, 3 5 C 2.5 7, 3 8.5, 4 9.5 C 5 10.5, 5.5 11.5, 5 13 C 4.5 14.5, 5 15.5, 6.5 16 C 8 16.5, 9.5 16, 11 15 C 12.5 14, 13.5 13, 14.5 11.5 C 15.5 10, 16 8.5, 15.5 7 C 15 5.5, 14 4.5, 12.5 3.5 C 11 2.5, 9 2.5, 7 3 Z" fill="none" stroke="%23000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/%3E%3C/svg%3E') !important;
              }
            `;
            document.head.appendChild(style);
          }

          // Update tooltip for freehand mode
          setTimeout(() => {
            const polygonButton = map
              .getContainer()
              .querySelector(".mapbox-gl-draw_polygon");
            if (polygonButton) {
              polygonButton.title = "Freehand polygon tool (p)";
            }
          }, 100);
        }

        // Add rectangle icon CSS if rectangle mode is enabled
        if (message.rectangle) {
          if (!document.querySelector("#mapgl-rectangle-styles")) {
            const style = document.createElement("style");
            style.id = "mapgl-rectangle-styles";
            style.textContent = `
              .mapbox-gl-draw_rectangle {
                background: transparent;
                border: none;
                cursor: pointer;
                display: block;
                height: 30px;
                width: 30px;
                padding: 0;
                outline: none;
                background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"%3E%3Crect x="4" y="5" width="12" height="10" fill="none" stroke="%23000000" stroke-width="2"/%3E%3C/svg%3E') !important;
                background-repeat: no-repeat !important;
                background-position: center !important;
              }
              .mapbox-gl-draw_rectangle:hover {
                background-color: rgba(0, 0, 0, 0.05);
              }
              .mapbox-gl-draw_rectangle.active {
                background-color: rgba(0, 0, 0, 0.05);
              }
            `;
            document.head.appendChild(style);
          }
        }

        // Add radius/circle icon CSS if radius mode is enabled
        if (message.radius) {
          if (!document.querySelector("#mapgl-radius-styles")) {
            const style = document.createElement("style");
            style.id = "mapgl-radius-styles";
            style.textContent = `
              .mapbox-gl-draw_radius {
                background: transparent;
                border: none;
                cursor: pointer;
                display: block;
                height: 30px;
                width: 30px;
                padding: 0;
                outline: none;
                background-image: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"%3E%3Ccircle cx="10" cy="10" r="7" fill="none" stroke="%23000000" stroke-width="2"/%3E%3Ccircle cx="10" cy="10" r="1.5" fill="%23000000"/%3E%3C/svg%3E') !important;
                background-repeat: no-repeat !important;
                background-position: center !important;
              }
              .mapbox-gl-draw_radius:hover {
                background-color: rgba(0, 0, 0, 0.05);
              }
              .mapbox-gl-draw_radius.active {
                background-color: rgba(0, 0, 0, 0.05);
              }
            `;
            document.head.appendChild(style);
          }
        }

        addBezierButtons(map, drawControl, {
          bezier: message.bezier,
          bezierPolygon: message.bezier_polygon,
          controlGroupSelector:
            ".maplibregl-ctrl-group:has(.mapbox-gl-draw_polygon)",
          iconClass: "maplibregl-ctrl-icon",
        });

        initializeDrawAttributeEditor(map, drawControl, {
          attributes: message.attributes,
          position: message.position,
          onChange: updateDrawnFeatures,
        });

        // Add event listeners
        map.on("draw.create", () => updateDrawnFeatures(false));
        map.on("draw.delete", () => updateDrawnFeatures(false));
        map.on("draw.update", () => updateDrawnFeatures(true));

        // Add measurement functionality if enabled
        if (message.show_measurements) {
          initializeMeasurements(map, drawControl, message.measurement_units);
        }

        // Add initial features if provided
        if (message.source) {
          addSourceFeaturesToDraw(drawControl, message.source, map);
          updateDrawnFeatures(false);
        }

        // Add rectangle and radius buttons if enabled
        setTimeout(() => {
          const drawControlGroup = map
            .getContainer()
            .querySelector(
              ".maplibregl-ctrl-group:has(.mapbox-gl-draw_polygon)",
            );

          if (drawControlGroup) {
            // Find the trash button to insert before it
            const trashBtn = drawControlGroup.querySelector(
              ".mapbox-gl-draw_trash",
            );

            if (message.rectangle) {
              const rectangleBtn = document.createElement("button");
              rectangleBtn.className =
                "mapbox-gl-draw_rectangle maplibregl-ctrl-icon";
              rectangleBtn.title = "Rectangle tool";
              rectangleBtn.type = "button";
              rectangleBtn.onclick = function () {
                drawControl.changeMode("draw_rectangle");
                // Remove active class from all buttons and add to this one
                drawControlGroup
                  .querySelectorAll("button")
                  .forEach((b) => b.classList.remove("active"));
                rectangleBtn.classList.add("active");
              };
              // Insert before trash button if it exists, otherwise append
              if (trashBtn) {
                drawControlGroup.insertBefore(rectangleBtn, trashBtn);
              } else {
                drawControlGroup.appendChild(rectangleBtn);
              }
            }

            if (message.radius) {
              const radiusBtn = document.createElement("button");
              radiusBtn.className =
                "mapbox-gl-draw_radius maplibregl-ctrl-icon";
              radiusBtn.title = "Radius/Circle tool";
              radiusBtn.type = "button";
              radiusBtn.onclick = function () {
                drawControl.changeMode("draw_radius");
                // Remove active class from all buttons and add to this one
                drawControlGroup
                  .querySelectorAll("button")
                  .forEach((b) => b.classList.remove("active"));
                radiusBtn.classList.add("active");
              };
              // Insert before trash button if it exists, otherwise append
              if (trashBtn) {
                drawControlGroup.insertBefore(radiusBtn, trashBtn);
              } else {
                drawControlGroup.appendChild(radiusBtn);
              }
            }
          }
        }, 100);

        // Apply orientation styling
        if (message.orientation === "horizontal") {
          const drawBar = map
            .getContainer()
            .querySelector(".maplibregl-ctrl-group");
          if (drawBar) {
            drawBar.style.display = "flex";
            drawBar.style.flexDirection = "row";
          }
        }

        // Add download button if requested
        if (message.download_button) {
          // Add CSS for download button if not already added
          if (!document.querySelector("#mapgl-draw-download-styles")) {
            const style = document.createElement("style");
            style.id = "mapgl-draw-download-styles";
            style.textContent = `
              .mapbox-gl-draw_download {
                background: transparent;
                border: none;
                cursor: pointer;
                display: block;
                height: 30px;
                width: 30px;
                padding: 0;
                outline: none;
              }
              .mapbox-gl-draw_download:hover {
                background-color: rgba(0, 0, 0, 0.05);
              }
              .mapbox-gl-draw_download svg {
                width: 20px;
                height: 20px;
                margin: 5px;
                fill: #333;
              }
            `;
            document.head.appendChild(style);
          }

          // Small delay to ensure Draw control is fully rendered
          setTimeout(() => {
            // Find the Draw control button group
            const drawButtons = map
              .getContainer()
              .querySelector(
                ".maplibregl-ctrl-group:has(.mapbox-gl-draw_polygon)",
              );

            if (drawButtons) {
              // Create download button
              const downloadBtn = document.createElement("button");
              downloadBtn.className = "mapbox-gl-draw_download";
              downloadBtn.title = "Download drawn features as GeoJSON";

              // Add SVG download icon
              downloadBtn.innerHTML = `
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                  <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
                </svg>
              `;

              downloadBtn.addEventListener("click", () => {
                // Get all drawn features
                const data = drawControl.getAll();

                if (data.features.length === 0) {
                  alert(
                    "No features to download. Please draw something first!",
                  );
                  return;
                }

                // Convert to string with nice formatting
                const dataStr = JSON.stringify(data, null, 2);

                // Create blob and download
                const blob = new Blob([dataStr], { type: "application/json" });
                const url = URL.createObjectURL(blob);

                const a = document.createElement("a");
                a.href = url;
                a.download = `${message.download_filename || "drawn-features"}.geojson`;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);
              });

              // Append to the Draw control button group
              drawButtons.appendChild(downloadBtn);
            }
          }, 100);
        }
      } else if (message.type === "get_drawn_features") {
        var drawControl = widget.drawControl || widget.getDraw();
        if (drawControl) {
          const features = drawControl.getAll();
          Shiny.setInputValue(data.id + "_drawn_features", features, {
            priority: "event",
          });
        } else {
          Shiny.setInputValue(data.id + "_drawn_features", null, {
            priority: "event",
          });
        }
      } else if (message.type === "clear_drawn_features") {
        var drawControl = widget.drawControl || widget.getDraw();
        if (drawControl) {
          drawControl.deleteAll();
          // Update the drawn features
          updateDrawnFeatures();
        }
      } else if (message.type.startsWith("turf_")) {
        // Delegate to shared turf operations module
        handleTurfOperation(map, message, data.id);
      } else if (message.type === "add_features_to_draw") {
        var drawControl = widget.drawControl || widget.getDraw();
        if (drawControl) {
          if (message.data.clear_existing) {
            drawControl.deleteAll();
          }
          addSourceFeaturesToDraw(drawControl, message.data.source, map);
          // Update the drawn features
          updateDrawnFeatures();
        } else {
          console.warn("Draw control not initialized");
        }
      } else if (message.type === "add_markers") {
        if (!window.maplibreMarkers) {
          window.maplibreMarkers = [];
        }
        message.markers.forEach(function (marker) {
          const markerOptions = {
            color: marker.color,
            rotation: marker.rotation,
            draggable: marker.options.draggable || false,
            ...marker.options,
          };
          const mapMarker = new maplibregl.Marker(markerOptions)
            .setLngLat([marker.lng, marker.lat])
            .addTo(map);

          if (marker.popup) {
            mapMarker.setPopup(
              new maplibregl.Popup({ offset: 25, maxWidth: "400px" }).setHTML(
                marker.popup,
              ),
            );
          }

          const markerId = marker.id;
          if (markerId) {
            const lngLat = mapMarker.getLngLat();
            Shiny.setInputValue(data.id + "_marker_" + markerId, {
              id: markerId,
              lng: lngLat.lng,
              lat: lngLat.lat,
            });

            mapMarker.on("dragend", function () {
              const lngLat = mapMarker.getLngLat();
              Shiny.setInputValue(data.id + "_marker_" + markerId, {
                id: markerId,
                lng: lngLat.lng,
                lat: lngLat.lat,
              });
            });
          }

          window.maplibreMarkers.push(mapMarker);
        });
      } else if (message.type === "clear_markers") {
        if (window.maplibreMarkers) {
          window.maplibreMarkers.forEach(function (marker) {
            marker.remove();
          });
          window.maplibreglMarkers = [];
        }
      } else if (message.type === "add_fullscreen_control") {
        const position = message.position || "top-right";
        const fullscreen = new maplibregl.FullscreenControl();
        map.addControl(fullscreen, position);
        map.controls.push({ type: "fullscreen", control: fullscreen });
      } else if (message.type === "add_slider_control") {
        if (typeof window.MapglSliderControl === "function") {
          if (map._mapglSliderControl) {
            try {
              map.removeControl(map._mapglSliderControl);
            } catch (e) { /* noop */ }
            map.controls = map.controls.filter(function (c) {
              return c.type !== "slider";
            });
          }
          const _ts = new window.MapglSliderControl(message.options || {});
          map.addControl(_ts, (message.options && message.options.position) || "top-left");
          map.controls.push({ type: "slider", control: _ts });
        } else {
          console.warn("MapglSliderControl is not loaded.");
        }
      } else if (message.type === "update_slider_control") {
        if (map._mapglSliderControl) {
          map._mapglSliderControl.update(message.options || {});
        }
      } else if (message.type === "add_scale_control") {
        const scaleControl = new maplibregl.ScaleControl({
          maxWidth: message.options.maxWidth,
          unit: message.options.unit,
        });
        map.addControl(scaleControl, message.options.position);
        map.controls.push({ type: "scale", control: scaleControl });
      } else if (message.type === "add_reset_control") {
        const resetControl = document.createElement("button");
        resetControl.className = "maplibregl-ctrl-icon maplibregl-ctrl-reset";
        resetControl.type = "button";
        resetControl.setAttribute("aria-label", "Reset");
        resetControl.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>';
        resetControl.style.cssText = "display:flex;justify-content:center;align-items:center;cursor:pointer;";

        const resetContainer = document.createElement("div");
        resetContainer.className = "maplibregl-ctrl maplibregl-ctrl-group";
        resetContainer.appendChild(resetControl);

        const initialView = {
          center: map.getCenter(),
          zoom: map.getZoom(),
          pitch: map.getPitch(),
          bearing: map.getBearing(),
          animate: message.animate,
        };

        if (message.duration) {
          initialView.duration = message.duration;
        }

        resetControl.onclick = function () {
          map.easeTo(initialView);
        };

        const resetControlObj = {
          onAdd: function () {
            return resetContainer;
          },
          onRemove: function () {
            resetContainer.parentNode.removeChild(resetContainer);
          },
        };

        map.addControl(resetControlObj, message.position);

        map.controls.push({ type: "reset", control: resetControlObj });
      } else if (message.type === "add_screenshot_control") {
        const screenshotControlObj = createScreenshotControl(map, message.options, true);
        map.addControl(screenshotControlObj, message.options.position || "top-right");
        map.controls.push({ type: "screenshot", control: screenshotControlObj });
      } else if (message.type === "add_coordinates_control") {
        const coordinatesControlObj = createCoordinatesControl(message.options);
        map.addControl(
          coordinatesControlObj,
          message.options.position || "bottom-right",
        );
        map.controls.push({ type: "coordinates", control: coordinatesControlObj });
      } else if (message.type === "add_geolocate_control") {
        const geolocate = new maplibregl.GeolocateControl({
          positionOptions: message.options.positionOptions,
          trackUserLocation: message.options.trackUserLocation,
          showAccuracyCircle: message.options.showAccuracyCircle,
          showUserLocation: message.options.showUserLocation,
          showUserHeading: message.options.showUserHeading,
          fitBoundsOptions: message.options.fitBoundsOptions,
        });
        map.addControl(geolocate, message.options.position);
        map.controls.push({ type: "geolocate", control: geolocate });

        if (HTMLWidgets.shinyMode) {
          geolocate.on("geolocate", function (event) {
            Shiny.setInputValue(el.id + "_geolocate", {
              coords: event.coords,
              time: new Date(),
            });
          });

          geolocate.on("trackuserlocationstart", function () {
            Shiny.setInputValue(el.id + "_geolocate_tracking", {
              status: "start",
              time: new Date(),
            });
          });

          geolocate.on("trackuserlocationend", function () {
            Shiny.setInputValue(el.id + "_geolocate_tracking", {
              status: "end",
              time: new Date(),
            });
          });

          geolocate.on("error", function (error) {
            if (error.error.code === 1) {
              Shiny.setInputValue(el.id + "_geolocate_error", {
                message: "Location permission denied",
                time: new Date(),
              });
            }
          });
        }
      } else if (message.type === "add_geocoder_control") {
        const provider = message.options.provider || "osm";
        let geocoder;

        if (provider === "maptiler") {
          // MapTiler geocoder
          const maptilerOptions = {
            apiKey: message.options.api_key,
            maplibregl: maplibregl,
            ...message.options,
          };

          // Create MapTiler geocoder
          geocoder = new maplibreglMaptilerGeocoder.GeocodingControl(
            maptilerOptions,
          );
        } else {
          // OSM/Nominatim geocoder (default)
          const geocoderApi = {
            forwardGeocode: async (config) => {
              const features = [];
              try {
                const request = `https://nominatim.openstreetmap.org/search?q=${
                  config.query
                }&format=geojson&polygon_geojson=1&addressdetails=1`;
                const response = await fetch(request);
                const geojson = await response.json();
                for (const feature of geojson.features) {
                  const center = [
                    feature.bbox[0] + (feature.bbox[2] - feature.bbox[0]) / 2,
                    feature.bbox[1] + (feature.bbox[3] - feature.bbox[1]) / 2,
                  ];
                  const point = {
                    type: "Feature",
                    geometry: {
                      type: "Point",
                      coordinates: center,
                    },
                    place_name: feature.properties.display_name,
                    properties: feature.properties,
                    text: feature.properties.display_name,
                    place_type: ["place"],
                    center,
                  };
                  features.push(point);
                }
              } catch (e) {
                console.error(`Failed to forwardGeocode with error: ${e}`);
              }

              return {
                features,
              };
            },
          };
          geocoder = new MaplibreGeocoder(geocoderApi, {
            maplibregl: maplibregl,
            placeholder: message.options.placeholder,
            collapsed: message.options.collapsed,
          });
        }

        map.addControl(geocoder, message.options.position);
        map.controls.push({ type: "geocoder", control: geocoder });

        // Apply CSS fix for MapTiler geocoder to prevent cutoff
        if (provider === "maptiler") {
          setTimeout(() => {
            const controlContainer = document.querySelector(
              ".maplibregl-ctrl-geocoder",
            );
            if (controlContainer) {
              controlContainer.style.maxWidth = "300px";
              controlContainer.style.width = "auto";
            }
          }, 100);
        }

        // Handle geocoder results in Shiny mode
        if (HTMLWidgets.shinyMode) {
          if (provider === "maptiler") {
            // MapTiler uses different event names
            geocoder.on("pick", function (e) {
              Shiny.setInputValue(data.id + "_geocoder", {
                result: e,
                time: new Date(),
              });
            });
          } else {
            // OSM geocoder
            geocoder.on("result", function (e) {
              Shiny.setInputValue(data.id + "_geocoder", {
                result: e,
                time: new Date(),
              });
            });
          }
        }
      } else if (message.type === "add_layers_control") {
        const layersControl = document.createElement("div");
        layersControl.id = message.control_id;
        layersControl.className = message.collapsible
          ? "layers-control collapsible"
          : "layers-control";
        layersControl.style.position = "absolute";

        // Set the position correctly
        const position = message.position || "top-left";
        if (position === "top-left") {
          layersControl.style.top = (message.margin_top || 10) + "px";
          layersControl.style.left = (message.margin_left || 10) + "px";
        } else if (position === "top-right") {
          layersControl.style.top = (message.margin_top || 10) + "px";
          layersControl.style.right = (message.margin_right || 10) + "px";
        } else if (position === "bottom-left") {
          layersControl.style.bottom = (message.margin_bottom || 10) + "px";
          layersControl.style.left = (message.margin_left || 10) + "px";
        } else if (position === "bottom-right") {
          layersControl.style.bottom = (message.margin_bottom || 40) + "px";
          layersControl.style.right = (message.margin_right || 10) + "px";
        }

        // Apply custom colors if provided
        if (message.custom_colors) {
          const colors = message.custom_colors;

          // Create a style element for custom colors
          const styleEl = document.createElement("style");
          let css = "";

          if (colors.background) {
            css += `#${message.control_id} { background-color: ${colors.background}; }\n`;
          }

          if (colors.text) {
            css += `#${message.control_id} a { color: ${colors.text}; }\n`;
          }

          if (colors.active) {
            css += `#${message.control_id} a.active { background-color: ${colors.active}; }\n`;
            css += `#${message.control_id} .toggle-button { background-color: ${colors.active}; }\n`;
          }

          if (colors.activeText) {
            css += `#${message.control_id} a.active { color: ${colors.activeText}; }\n`;
            css += `#${message.control_id} .toggle-button { color: ${colors.activeText}; }\n`;
          }

          if (colors.hover) {
            css += `#${message.control_id} a:hover { background-color: ${colors.hover}; }\n`;
            css += `#${message.control_id} .toggle-button:hover { background-color: ${colors.hover}; }\n`;
          }

          styleEl.textContent = css;
          document.head.appendChild(styleEl);
        }

        const layersList = document.createElement("div");
        layersList.className = "layers-list";
        layersControl.appendChild(layersList);

        let layers = message.layers || [];
        let layersConfig = message.layers_config;

        // If we have a layers_config, use that; otherwise fall back to original behavior
        if (layersConfig && Array.isArray(layersConfig)) {
          layersConfig.forEach((config, index) => {
            const link = document.createElement("a");
            // Ensure config.ids is always an array
            const layerIds = Array.isArray(config.ids)
              ? config.ids
              : [config.ids];
            link.id = layerIds.join("-");
            link.href = "#";
            link.textContent = config.label;
            link.setAttribute("data-layer-ids", JSON.stringify(layerIds));
            link.setAttribute("data-layer-type", config.type);

            // Check if the first layer's visibility is set to "none" initially
            const firstLayerId = layerIds[0];
            const initialVisibility = map.getLayoutProperty(
              firstLayerId,
              "visibility",
            );
            link.className = initialVisibility === "none" ? "" : "active";

            // Also hide any associated legends if the layer is initially hidden
            if (initialVisibility === "none") {
              layerIds.forEach((layerId) => {
                const associatedLegends = document.querySelectorAll(
                  `.mapboxgl-legend[data-layer-id="${layerId}"]`,
                );
                associatedLegends.forEach((legend) => {
                  legend.style.display = "none";
                });
              });
            }

            // Show or hide layer(s) when the toggle is clicked
            link.onclick = function (e) {
              e.preventDefault();
              e.stopPropagation();

              const layerIds = JSON.parse(this.getAttribute("data-layer-ids"));
              const firstLayerId = layerIds[0];
              const visibility = map.getLayoutProperty(
                firstLayerId,
                "visibility",
              );

              // Toggle visibility for all layer IDs in the group
              if (visibility === "visible") {
                layerIds.forEach((layerId) => {
                  map.setLayoutProperty(layerId, "visibility", "none");
                  // Hide associated legends
                  const associatedLegends = document.querySelectorAll(
                    `.mapboxgl-legend[data-layer-id="${layerId}"]`,
                  );
                  associatedLegends.forEach((legend) => {
                    legend.style.display = "none";
                  });
                });
                this.className = "";
              } else {
                layerIds.forEach((layerId) => {
                  map.setLayoutProperty(layerId, "visibility", "visible");
                  // Show associated legends
                  const associatedLegends = document.querySelectorAll(
                    `.mapboxgl-legend[data-layer-id="${layerId}"]`,
                  );
                  associatedLegends.forEach((legend) => {
                    legend.style.display = "";
                  });
                });
                this.className = "active";
              }
            };

            layersList.appendChild(link);
          });
        } else {
          // Fallback to original behavior for simple layer arrays
          // Ensure layers is always an array
          if (!Array.isArray(layers)) {
            layers = [layers];
          }

          layers.forEach((layerId, index) => {
            const link = document.createElement("a");
            link.id = layerId;
            link.href = "#";
            link.textContent = layerId;

            // Check if the layer visibility is set to "none" initially
            const initialVisibility = map.getLayoutProperty(
              layerId,
              "visibility",
            );
            link.className = initialVisibility === "none" ? "" : "active";

            // Also hide any associated legends if the layer is initially hidden
            if (initialVisibility === "none") {
              const associatedLegends = document.querySelectorAll(
                `.mapboxgl-legend[data-layer-id="${layerId}"]`,
              );
              associatedLegends.forEach((legend) => {
                legend.style.display = "none";
              });
            }

            link.onclick = function (e) {
              const clickedLayer = this.textContent;
              e.preventDefault();
              e.stopPropagation();

              const visibility = map.getLayoutProperty(
                clickedLayer,
                "visibility",
              );

              if (visibility === "visible") {
                map.setLayoutProperty(clickedLayer, "visibility", "none");
                this.className = "";

                // Hide associated legends
                const associatedLegends = document.querySelectorAll(
                  `.mapboxgl-legend[data-layer-id="${clickedLayer}"]`,
                );
                associatedLegends.forEach((legend) => {
                  legend.style.display = "none";
                });
              } else {
                this.className = "active";
                map.setLayoutProperty(clickedLayer, "visibility", "visible");

                // Show associated legends
                const associatedLegends = document.querySelectorAll(
                  `.mapboxgl-legend[data-layer-id="${clickedLayer}"]`,
                );
                associatedLegends.forEach((legend) => {
                  legend.style.display = "";
                });
              }
            };

            layersList.appendChild(link);
          });
        }

        if (message.collapsible) {
          const toggleButton = document.createElement("div");
          toggleButton.className = "toggle-button";

          // Use stacked layers icon instead of text if requested
          if (message.use_icon) {
            // Add icon-only class to the control for compact styling
            layersControl.classList.add("icon-only");

            // More GIS-like layers stack icon
            toggleButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                            <polyline points="2 17 12 22 22 17"></polyline>
                            <polyline points="2 12 12 17 22 12"></polyline>
                        </svg>`;
            toggleButton.style.display = "flex";
            toggleButton.style.alignItems = "center";
            toggleButton.style.justifyContent = "center";
          } else {
            toggleButton.textContent = "Layers";
          }

          toggleButton.onclick = function () {
            layersControl.classList.toggle("open");
          };
          layersControl.insertBefore(toggleButton, layersList);
        }

        const mapContainer = document.getElementById(data.id);
        if (mapContainer) {
          mapContainer.appendChild(layersControl);
        } else {
          console.error(`Cannot find map container with ID ${data.id}`);
        }
      } else if (message.type === "clear_legend") {
        if (message.ids && Array.isArray(message.ids)) {
          message.ids.forEach((id) => {
            const legend = document.querySelector(
              `#${data.id} div[id="${id}"]`,
            );
            if (legend) {
              legend.remove();
            }
            // Remove from legend state
            delete layerState.legends[id];
          });
        } else if (message.ids) {
          const legend = document.querySelector(
            `#${data.id} div[id="${message.ids}"]`,
          );
          if (legend) {
            legend.remove();
          }
          // Remove from legend state
          delete layerState.legends[message.ids];
        } else {
          const existingLegends = document.querySelectorAll(
            `#${data.id} .mapboxgl-legend`,
          );
          existingLegends.forEach((legend) => {
            legend.remove();
          });

          // Clear all legend state
          layerState.legends = {};
        }
      } else if (message.type === "clear_controls") {
        // If no specific controls specified, clear all
        if (!message.controls || message.controls.length === 0) {
          map.controls.forEach((controlObj) => {
            if (controlObj.control) {
              map.removeControl(controlObj.control);
            }
          });
          map.controls = [];
          if (map._mapglSliderControl) {
            delete map._mapglSliderControl;
          }

          const layersControl = document.querySelector(
            `#${data.id} .layers-control`,
          );
          if (layersControl) {
            layersControl.remove();
          }

          // Remove globe minimap if it exists
          const globeMinimap = document.querySelector(
            ".mapboxgl-ctrl-globe-minimap",
          );
          if (globeMinimap) {
            globeMinimap.remove();
          }
        } else {
          // Clear specific controls
          const controlsToRemove = Array.isArray(message.controls)
            ? message.controls
            : [message.controls];

          map.controls = map.controls.filter((controlObj) => {
            if (controlsToRemove.includes(controlObj.type)) {
              if (controlObj.control) {
                map.removeControl(controlObj.control);
              }
              return false; // Remove from array
            }
            return true; // Keep in array
          });

          // Handle special controls that aren't in the controls array
          controlsToRemove.forEach((controlType) => {
            if (controlType === "layers") {
              const layersControl = document.querySelector(
                `#${data.id} .layers-control`,
              );
              if (layersControl) {
                layersControl.remove();
              }
            } else if (controlType === "globe_minimap") {
              const globeMinimap = document.querySelector(
                ".mapboxgl-ctrl-globe-minimap",
              );
              if (globeMinimap) {
                globeMinimap.remove();
              }
            } else if (controlType === "draw") {
              // Hide measurement box when draw control is cleared
              const measurementBox = document.getElementById(
                `measurement-box-${map.getContainer().id}`,
              );
              if (measurementBox) {
                measurementBox.style.display = "none";
              }
            }
          });
        }
      } else if (message.type === "move_layer") {
        if (map.getLayer(message.layer)) {
          if (message.before) {
            map.moveLayer(message.layer, message.before);
          } else {
            map.moveLayer(message.layer);
          }
        } else {
          console.error("Layer not found:", message.layer);
        }
      } else if (message.type === "add_image") {
        const mapId = map.getContainer().id;

        // Helper function to actually add the image
        const doAddImage = function(imageId, url, options) {
          // Register the image for re-adding after style changes
          registerUserImage(mapId, imageId, url, options);

          map
            .loadImage(url)
            .then((image) => {
              if (!map.hasImage(imageId)) {
                map.addImage(imageId, image.data, options);
                console.log("[MapGL Debug] Added image via proxy:", imageId);
              }
            })
            .catch((error) => {
              console.error("Error loading image:", error);
            });
        };

        if (Array.isArray(message.images)) {
          message.images.forEach(function (imageInfo) {
            queueOrExecute(mapId, function() {
              doAddImage(imageInfo.id, imageInfo.url, imageInfo.options);
            });
          });
        } else if (message.url) {
          queueOrExecute(mapId, function() {
            doAddImage(message.imageId, message.url, message.options);
          });
        } else {
          console.error("Invalid image data:", message);
        }
      } else if (message.type === "set_tooltip") {
        const layerId = message.layer;
        const newTooltipProperty = message.tooltip;
        const newTooltipStyle = message.tooltip_style || null;

        // Track tooltip state (content + style)
        layerState.tooltips[layerId] = newTooltipProperty;
        layerState.tooltipStyles[layerId] = newTooltipStyle;

        // If there's an active tooltip open, remove it first
        if (window._activeTooltip) {
          window._activeTooltip.remove();
          delete window._activeTooltip;
        }

        // Remove old handlers if any
        if (window._mapboxHandlers && window._mapboxHandlers[layerId]) {
          const handlers = window._mapboxHandlers[layerId];
          if (handlers.mousemove) {
            map.off("mousemove", layerId, handlers.mousemove);
          }
          if (handlers.mouseleave) {
            map.off("mouseleave", layerId, handlers.mouseleave);
          }
          delete window._mapboxHandlers[layerId];
        }

        // Create a new tooltip popup
        const tooltip = new maplibregl.Popup({
          closeButton: false,
          closeOnClick: false,
          maxWidth: "400px",
        });
        applyPopupClass(tooltip, newTooltipStyle);

        // Define new handlers referencing the updated tooltip property
        const mouseMoveHandler = function (e) {
          onMouseMoveTooltip(e, map, tooltip, newTooltipProperty, layerId);
        };
        const mouseLeaveHandler = function () {
          onMouseLeaveTooltip(map, tooltip);
        };

        // Add the new event handlers
        map.on("mousemove", layerId, mouseMoveHandler);
        map.on("mouseleave", layerId, mouseLeaveHandler);

        // Store these handlers so we can remove/update them in the future
        if (!window._mapboxHandlers) {
          window._mapboxHandlers = {};
        }
        window._mapboxHandlers[layerId] = {
          mousemove: mouseMoveHandler,
          mouseleave: mouseLeaveHandler,
        };
      } else if (message.type === "set_popup") {
        const layerId = message.layer;
        const newPopupProperty = message.popup;
        const newPopupStyle = message.popup_style || null;

        // Track popup state (content + style)
        layerState.popups[layerId] = newPopupProperty;
        layerState.popupStyles[layerId] = newPopupStyle;

        // Remove any existing popup for this layer
        if (window._mapboxPopups && window._mapboxPopups[layerId]) {
          window._mapboxPopups[layerId].remove();
          delete window._mapboxPopups[layerId];
        }

        // Remove old click handler if any
        if (
          window._mapboxClickHandlers &&
          window._mapboxClickHandlers[layerId]
        ) {
          map.off("click", layerId, window._mapboxClickHandlers[layerId]);
          delete window._mapboxClickHandlers[layerId];
        }

        // Remove old hover handlers for cursor change
        map.off("mouseenter", layerId);
        map.off("mouseleave", layerId);

        // Create new click handler
        const clickHandler = function (e) {
          onClickPopup(e, map, newPopupProperty, layerId, newPopupStyle);
        };

        // Add the new event handler
        map.on("click", layerId, clickHandler);

        // Change cursor to pointer when hovering over the layer
        map.on("mouseenter", layerId, function () {
          map.getCanvas().style.cursor = "pointer";
        });

        // Change cursor back to default when leaving the layer
        map.on("mouseleave", layerId, function () {
          map.getCanvas().style.cursor = "";
        });

        // Store handler reference
        if (!window._mapboxClickHandlers) {
          window._mapboxClickHandlers = {};
        }
        window._mapboxClickHandlers[layerId] = clickHandler;
      } else if (message.type === "set_source") {
        const layerId = message.layer;
        const newData = message.source;
        const layerObject = map.getLayer(layerId);

        if (!layerObject) {
          console.error("Layer not found: ", layerId);
          return;
        }

        const sourceId = layerObject.source;
        const sourceObject = map.getSource(sourceId);

        if (!sourceObject) {
          console.error("Source not found: ", sourceId);
          return;
        }

        // Update the geojson data
        sourceObject.setData(newData);
      } else if (message.type === "set_projection") {
        if (map.loaded()) {
          const projection =
            typeof message.projection === "string"
              ? { type: message.projection }
              : message.projection;

          try {
            map.setProjection(projection);
          } catch (e) {
            console.error("Failed to set projection:", e);
          }
        } else {
          console.error("Map not loaded yet");
        }
      } else if (message.type === "add_globe_minimap") {
        const globeMinimapOptions = {
          globeSize: message.options.globe_size || 100,
          landColor: message.options.land_color || "#404040",
          waterColor: message.options.water_color || "#090909",
          markerColor: message.options.marker_color || "#1da1f2",
          markerSize: message.options.marker_size || 2,
        };
        const globeMinimap = new GlobeMinimap(globeMinimapOptions);
        map.addControl(globeMinimap, message.position || "bottom-left");
        map.controls.push({ type: "globe_minimap", control: globeMinimap });
      } else if (message.type === "add_globe_control") {
        const globeControl = new maplibregl.GlobeControl();
        map.addControl(globeControl, message.position);
        map.controls.push({ type: "globe", control: globeControl });
      } else if (message.type === "add_custom_control") {
        const controlOptions = message.options;
        const customControlContainer = document.createElement("div");

        if (controlOptions.className) {
          customControlContainer.className = controlOptions.className;
        } else {
          customControlContainer.className =
            "maplibregl-ctrl maplibregl-ctrl-group";
        }

        customControlContainer.innerHTML = controlOptions.html;

        const customControl = {
          onAdd: function () {
            return customControlContainer;
          },
          onRemove: function () {
            if (customControlContainer.parentNode) {
              customControlContainer.parentNode.removeChild(
                customControlContainer,
              );
            }
          },
        };

        map.addControl(customControl, controlOptions.position || "top-right");
        map.controls.push({ type: message.control_id, control: customControl });
      }
    }
  });
}
