document.addEventListener("DOMContentLoaded", () => {
 const map_element = document.querySelector("#map");
 if( !map_element){
  return;
 }
 const svg = d3.select("#map");
 let projection, path;
 let geoDataGlobal = null;
 let stateToSafe = {};
 let currentActiveName = null;
 let syncingFromMap = false; // Flag to stop recursive calls when map initiates the slide change
 let hoverActiveName = null;

 function safeNameFromLabel(name) {
  return String(name || "").toLowerCase().replace(/\s+/g, "-");
 }

 // ---------- SWIPER HANDLING ----------
 function getOrInitSwiper() {  
  const el = document.querySelector("#map_slider");
  if (!el) return null;

  if (window.mapSwiper && !window.mapSwiper.destroyed) return window.mapSwiper;

  window.mapSwiper = new Swiper("#map_slider", {
   slidesPerView: 3,
   spaceBetween: 20,
   loop: false,
  //  autoplay:true,
   observer: true,
   observeParents: true,
   navigation: {
    nextEl: ".custom_slider_controls .map_slide_next",
    prevEl: ".custom_slider_controls .map_slide_prev",
   },
   breakpoints: {
    0: { slidesPerView: 1, spaceBetween: 5 },
    767: { slidesPerView: 2, spaceBetween: 10 },
    991: { slidesPerView: 3 },
   },
   on: {
    init(swiper) {
     updateArrows(swiper);
     if (swiper.slides.length > 0) {
      activateStateFromSlide(swiper);
     }
    },
    // FIX: Use slideChange for instant state synchronization from the slider.
    slideChange(swiper) { 
     // Only sync map state if the slide change was NOT initiated by a map click.
     if (!syncingFromMap) {
      activateStateFromSlide(swiper);
     }
     updateArrows(swiper);
    },
    // Ensure arrows update at the end of transition
    slideChangeTransitionEnd(swiper) {
     updateArrows(swiper);
    },
   },
  });

  return window.mapSwiper;
 }

 function updateArrows(swiper) {
  const prev = document.querySelector(".custom_slider_controls .map_slide_prev");
  const next = document.querySelector(".custom_slider_controls .map_slide_next");

  if (!prev || !next) return;

  if (swiper.isBeginning) {
   prev.classList.add("swiper-button-disabled");
   prev.style.pointerEvents = "none";
   prev.style.opacity = "0.3";
  } else {
   prev.classList.remove("swiper-button-disabled");
   prev.style.pointerEvents = "auto";
   prev.style.opacity = "1";
  }

  if (swiper.isEnd) {
   next.classList.add("swiper-button-disabled");
   next.style.pointerEvents = "none";
   next.style.opacity = "0.3";
  } else {
   next.classList.remove("swiper-button-disabled");
   next.style.pointerEvents = "auto";
   next.style.opacity = "1";
  }
 }

 // ---------- MAP ⇄ SLIDER SYNC ----------
 function activateStateFromSlide(swiper) {
  if (!swiper) swiper = window.mapSwiper;
  if (!swiper) return;

  const realIndex = swiper.realIndex || swiper.activeIndex;
  const slides = document.querySelectorAll("#map_slider .swiper-slide");
  const activeSlide = slides[realIndex];
  const safeName = activeSlide?.getAttribute("data-state")?.trim()?.toLowerCase();
  if (!safeName) return;

  // Ensure we don't re-activate the same state
  if (currentActiveName === safeName) return;

  // Activate map state (second argument false prevents activating the slide again)
  setActiveBySafeName(safeName, false); 
 }

 function activateSlideByState(safeName) {
  if (!safeName) return;
  const swiper = getOrInitSwiper();
  if (!swiper) return;

  const slides = Array.from(document.querySelectorAll("#map_slider .swiper-slide"));
  const targetIndex = slides.findIndex(slide =>
   (slide.getAttribute("data-state") || "").trim().toLowerCase() === safeName
  );
  if (targetIndex === -1) return;

  if (swiper.activeIndex === targetIndex) return;

  // FIX: Set flag before sliding to prevent map re-activation by the slideChange event
  syncingFromMap = true;
  swiper.slideTo(targetIndex, 400);
  // Clear the flag after the transition time plus a buffer
  setTimeout(() => (syncingFromMap = false), 420); 
 }

 // ---------- MAP HIGHLIGHT / INTERACTION ----------
 function setActiveBySafeName(safeName, moveSlide = true) {
  d3.selectAll(".label_group").classed("active", false);
  d3.selectAll("path.m_state").classed("active", false);

  if (!safeName) {
   currentActiveName = null;
   return;
  }
    
  // Prevent redundant map updates if the state is already active
  if (currentActiveName === safeName && !moveSlide) return;

  d3.selectAll(".label_group." + safeName).classed("active", true);
  d3.selectAll("path.m_state").each(function(d) {
   let m_stateProp = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
   m_stateProp = m_stateProp.toLowerCase().trim();
   if (stateToSafe[m_stateProp] === safeName)
    d3.select(this).classed("active", true);
  });

  currentActiveName = safeName;
  if (moveSlide) activateSlideByState(safeName); // Triggers slider sync
 }

 function setTemporaryHover(safeName) {
  if (!safeName || safeName === currentActiveName) return;

  if (hoverActiveName && hoverActiveName !== currentActiveName) {
   d3.selectAll(".label_group." + hoverActiveName).classed("active", false);
   d3.selectAll("path.m_state").each(function(d) {
    let m = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
    if (stateToSafe[m.toLowerCase().trim()] === hoverActiveName)
     d3.select(this).classed("active", false);
   });
  }

  d3.selectAll(".label_group." + safeName).classed("active", true);
  d3.selectAll("path.m_state").each(function(d) {
   let m = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
   if (stateToSafe[m.toLowerCase().trim()] === safeName)
    d3.select(this).classed("active", true);
  });

  hoverActiveName = safeName;
 }

 function clearTemporaryHover() {
  if (hoverActiveName && hoverActiveName !== currentActiveName) {
   d3.selectAll(".label_group." + hoverActiveName).classed("active", false);
   d3.selectAll("path.m_state").each(function(d) {
    let m = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
    if (stateToSafe[m.toLowerCase().trim()] === hoverActiveName)
     d3.select(this).classed("active", false);
   });
  }
  hoverActiveName = null;
 }

 function attachInteractions() {
  d3.selectAll("path.m_state").on(".map", null);
  d3.selectAll(".label_group").on(".map", null);

  d3.selectAll("path.m_state")
   .on("mouseover.map", function(event, d) {
    const n = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
    const safe = stateToSafe[n.toLowerCase().trim()] || safeNameFromLabel(n);
    setTemporaryHover(safe);
   })
   .on("mouseout.map", clearTemporaryHover)
   .on("click.map", function(event, d) {
    const n = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
    const safe = stateToSafe[n.toLowerCase().trim()] || safeNameFromLabel(n);
    setActiveBySafeName(safe, true); // moveSlide = true to sync slider
   });

  d3.selectAll(".label_group")
   .on("mouseover.map", function() {
    const classes = (this.getAttribute("class") || "").split(/\s+/);
    const safe = classes.find(c => c !== "label_group" && c !== "active");
    setTemporaryHover(safe);
   })
   .on("mouseout.map", clearTemporaryHover)
   .on("click.map", function() {
    const classes = (this.getAttribute("class") || "").split(/\s+/);
    const safe = classes.find(c => c !== "label_group" && c !== "active");
    setActiveBySafeName(safe, true); // moveSlide = true to sync slider
   });
 }

function drawLabel({ svg, projection, center, name, lat, lng, hDir, hLen, vDir, vLen }) {
  const [cx, cy] = lat && lng ? projection([lng, lat]) : center;

  const parent = document.getElementById("map-wrapper");
  const svgWidth = parent.clientWidth;
  const scale = svgWidth / 1200;

  const dotRadius = 3 * scale;
  const h = hLen * scale;
  const v = vLen * scale;
  const fontSize = 14 * scale;
  const padding = 7 * scale; // Used for text padding inside the box
  const boxHeight = 26 * scale;
  
  // Estimate text width for box sizing
  const textWidthEstimate = name.length * (fontSize * 0.6); 
  const boxWidth = textWidthEstimate + padding * 3; 

  const safeName = safeNameFromLabel(name);

  const group = svg.append("g").attr("class", "label_group " + safeName);

  // Dot
  group.append("circle")
    .attr("class", "location_dot")
    .attr("cx", cx)
    .attr("cy", cy)
    .attr("r", dotRadius);

  // --- Connector Line Endpoints ---
  let hx = cx;
  if (h !== 0) {
    hx = hDir === "right" ? cx + h : cx - h;
  }

  let vy = cy; 
  if (v !== 0) {
    vy = vDir === "down" ? cy + v : cy - v;
  }

  // --- Draw Primary Segments ---
  // Horizontal segment (if it exists)
  if (h !== 0) {
    group.append("line")
      .attr("class", "connector_line")
      .attr("x1", cx)
      .attr("y1", cy)
      .attr("x2", hx)
      .attr("y2", cy);
  }

  // Vertical segment (if it exists)
  if (v !== 0) {
    // Note: The vertical segment is always at hx (or cx if h=0) and ends at vy.
    const vStart = h !== 0 ? cy : cy; 
    group.append("line")
      .attr("class", "connector_line")
      .attr("x1", hx)
      .attr("y1", vStart)
      .attr("x2", hx)
      .attr("y2", vy);
  }

  // --- Calculate Box Position (Flush against the line end) ---
  let boxX, boxY;

  // --- CASE A — Horizontal only (v === 0) ---
  // The line is horizontal at cy. Box must be centered vertically on cy.
  if (h !== 0 && v === 0) {
    if (hDir === "right") {
      boxX = hx; // Box starts right at hx
    } else {
      boxX = hx - boxWidth; // Box ends left at hx
    }
    // Centered vertically on the line (cy)
    boxY = cy - boxHeight / 2; 
  }

  // --- CASE B — Vertical only (h === 0) ---
  // The line is vertical at cx. Box must be centered horizontally on cx.
  else if (v !== 0 && h === 0) {
    // Centered horizontally on the line (cx)
    boxX = cx - boxWidth / 2; 
    
    if (vDir === "down") {
      boxY = vy; // Box starts down at vy
    } else {
      boxY = vy - boxHeight; // Box ends up at vy
    }
  }

  // --- CASE C — Corner (horizontal + vertical) ---
  // The final segment is vertical, located at hx. Box must be centered horizontally on hx.
  else if (h !== 0 && v !== 0) {
    
    // FIX: Center box horizontally on the vertical line segment (hx)
    boxX = hx - boxWidth / 2; 
    
    // Vertical placement (Flush against the line end vy)
    // The box is centered on the vertical line, so it must start flush at vy.
    if (vDir === "down") {
      boxY = vy; // Box starts down at vy
    } else {
      boxY = vy - boxHeight; // Box ends up at vy
    }
  }
  
  // --- Draw Box ---
  group.append("rect")
    .attr("class", "label_box")
    .attr("x", boxX)
    .attr("y", boxY)
    .attr("width", boxWidth)
    .attr("height", boxHeight)
    .attr("rx", 14 * scale);

  // --- Draw Text ---
  group.append("text")
    .attr("class", "label_text")
    .attr("x", boxX + boxWidth / 2)
    .attr("y", boxY + boxHeight / 2)
    .attr("dominant-baseline", "middle")
    .attr("text-anchor", "middle")
    .style("font-size", fontSize + "px")
    .text(name);
}

  function drawSeaLabel({ svg, projection, name, lat, lng, fontSize, opacity }) {
    const [x, y] = projection([lng, lat]);

    const parent = document.getElementById("map-wrapper");
    const svgWidth = parent.clientWidth;
    const scale = svgWidth / 1200;

    const scaledFont = fontSize * scale;

    svg.append("text")
      .attr("class", "sea_label")
      .attr("x", x)
      .attr("y", y)
      .attr("text-anchor", "middle")
      .style("font-size", scaledFont + "px")
      .style("font-weight", "600")
      .style("opacity", opacity)
      .text(name);
  }

 // ---------- LABEL CONFIGS ----------
 const labelConfigs = [
  { m_state: "Perlis", name: "Perlis", lat: 6.610376, lng: 100.240903, hDir: "left", hLen: 4, vDir: "up", vLen: 30 },
  { m_state: "Kedah", name: "Kedah", lat: 6.111422, lng: 100.9312, hDir: "right", hLen: 50, vDir: "up", vLen: 30 },
  { m_state: "Penang", name: "Penang", lat: 5.285864, lng: 100.493668, hDir: "left", hLen: 27, vDir: "down", vLen: 35 },
  { m_state: "Perak", name: "Perak", lat: 4.099753, lng: 100.907049, hDir: "left", hLen: 30, vDir: "down", vLen: 0 },
  { m_state: "Kelantan", name: "Kelantan", lat: 6.012705, lng: 102.250905, hDir: "right", hLen: 100, vDir: "up", vLen: 0 },
  { m_state: "Terengganu", name: "Terengganu", lat: 5.044188, lng: 102.997404, hDir: "right", hLen: 80, vDir: "up", vLen: 0 },
  { m_state: "Selangor", name: "Selangor", lat: 3.613306, lng: 101.184196, hDir: "left", hLen: 28, vDir: "down", vLen: 0 },
  { m_state: "KualaLumpur", name: "Kuala Lumpur", lat: 3.152954, lng: 101.691444, hDir: "left", hLen: 80, vDir: "down", vLen: 30 },
  { m_state: "Putrajaya", name: "Putrajaya", lat: 2.935609, lng: 101.692961, hDir: "left", hLen: 13, vDir: "down", vLen: 70 },
  { m_state: "Melaka", name: "Melaka", lat: 2.297552, lng: 102.28276, hDir: "right", hLen: 13, vDir: "down", vLen: 70 },
  { m_state: "NegeriSembilan", name: "Negeri Sembilan", lat: 2.962658, lng: 102.248178, hDir: "right", hLen: 190, vDir: "up", vLen: 20 },
  { m_state: "Pahang", name: "Pahang", lat: 3.880965, lng: 102.591956, hDir: "right", hLen: 130, vDir: "up", vLen: 0 },
  { m_state: "Johor", name: "Johor", lat: 1.895016, lng: 103.859798, hDir: "right", hLen:55, vDir: "up", vLen: 0 },
  { m_state: "Labuan", name: "Labuan", lat: 5.280694, lng: 111.183774, hDir: "left", hLen: 60, vDir: "up", vLen: 20 },
  { m_state: "Sarawak", name: "Sarawak", lat: 2.88229, lng: 108.846506, hDir: "left", hLen: 60, vDir: "up", vLen: 60 },
  { m_state: "Sabah", name: "Sabah", lat: 5.873501, lng: 112.669104, hDir: "left", hLen: 60, vDir: "up", vLen: 60 },
 ];
 // ---------- SEA LABEL CONFIGS ----------
  const seaLabelConfigs = [
    { name: "South China Sea",lat: 5.5,lng: 107.5,fontSize: 16,opacity: 0.35 },
    { name: "Straits of Malacca",lat: 0.5,lng: 101.3,fontSize: 16,opacity: 0.35 },
    { name: "Sulu Sea",lat: 7.2,lng: 114.2,fontSize: 16,opacity: 0.35 },
    { name: "Celebes Sea",lat: 3.0,lng: 114.3,fontSize: 16,opacity: 0.35 },
    { name: "Java Sea",lat: 0.5,lng: 105.5,fontSize: 16,opacity: 0.35 }
  ];


 const baseURL = window.location.origin;
//  const geoJsonUrl = "http://localhost/HIP/new_malaysia_travel/share_with_mimi/After_changes_in_theme/assets/map/malaysia_states.json";
 const geoJsonUrl = `${baseURL}/assets/map/malaysia_states.json`;
 d3.json(geoJsonUrl).then((geoData) => {
  geoDataGlobal = geoData;

  // Coordinate offset for East Malaysia (Sabah, Sarawak, Labuan) for better visual grouping
  geoData.features.forEach(f => {
   const n = f.properties.NAME_1 || f.properties.name;
   if (["Sabah", "Sarawak", "Labuan"].includes(n)) {
    if (f.geometry && Array.isArray(f.geometry.coordinates)) {
     // Assuming a simple 4 degree offset for visualization purposes
     f.geometry.coordinates = f.geometry.coordinates.map(poly =>
      poly.map(ring => ring.map(([x, y]) => [x - 4, y]))
     );
    }
   }
  });

  function render() {
   d3.selectAll("#map > *").remove();

   const parent = document.getElementById("map-wrapper");

   if( !parent ) { return }
   const w = parent.clientWidth;
   const h = parent.clientHeight;

   projection = d3.geoMercator().fitSize([w, h], geoData);
   path = d3.geoPath().projection(projection);

   svg.selectAll("path.m_state")
    .data(geoData.features)
    .enter()
    .append("path")
    .attr("class", "m_state")
    .attr("d", path);

   stateToSafe = {};
   labelConfigs.forEach(L => stateToSafe[L.m_state.toLowerCase().trim()] = safeNameFromLabel(L.name));

   labelConfigs.forEach(L => {
    const feature = geoData.features.find(f => {
     const n = (f.properties && (f.properties.NAME_1 || f.properties.name)) || "";
     return n.toLowerCase().trim() === String(L.m_state).toLowerCase().trim();
    });
    if (!feature) return;
    const center = path.centroid(feature);
    // draw state labels
    drawLabel({
     svg,
     projection,
     center,
     name: L.name,
     lat: L.lat,
     lng: L.lng,
     hDir: L.hDir,
     hLen: L.hLen,
     vDir: L.vDir,
     vLen: L.vLen,
    });

    // ----- Draw Sea Labels -----
    seaLabelConfigs.forEach(S => {
      drawSeaLabel({
        svg,
        projection,
        name: S.name,
        lat: S.lat,
        lng: S.lng,
        fontSize: S.fontSize,
        opacity: S.opacity
      });
    });

   });

   attachInteractions();
   const swiper = getOrInitSwiper();
   if (currentActiveName) setActiveBySafeName(currentActiveName);
  }

  render();

  // Debounced resize handler for responsiveness
  window.addEventListener("resize", () => {
   if (window._malaysia_map_resize_timer) clearTimeout(window._malaysia_map_resize_timer);
   window._malaysia_map_resize_timer = setTimeout(() => {
    render();
    window._malaysia_map_resize_timer = null;
   }, 120);
  });
 });

 // Global function exposure for external calls if needed
 window.__setActiveBySafeName = function(name) {
  setActiveBySafeName(name);
 };
});