/*
    "צבע שחור" — חלון ההתראה (alert.html).
    פריסה אנכית: סוג-אירוע + מיקום מדויק (עיר, כתובת) → הערה → מפה עם נעץ בנקודה המדויקת.
    אירוע יחיד אצלנו — אין רשימת ערים/פוליגונים/קיבוץ אזורים (שרידי "צבע אדום" הוסרו).

    שני מצבים:
      • live  — נפתח מה-background לאירוע פעיל; נרשם לעדכונים שוטפים ונסגר כשהאירוע מסתיים.
      • history — נפתח מהיסטוריית ההתרעות (popup.js) עם נתוני אירוע ב-query params; תצוגה
                  סטטית, ללא מנוי לעדכונים (האירוע אינו "פעיל").
    כפתור "מרחק מהמיקום שלי" (זהה בשני המצבים): המיקום נשמר אחרי האיתור הראשון
    (chrome.storage.local). בלחיצה — מציגים מיד את המרחק מהמיקום השמור (אם טרי), *ובו-זמנית*
    מאתרים טרי תוך כדי ומעדכנים (stale-while-revalidate). מרחק אווירי = haversine מקומי מיידי;
    מרחק/זמן ברכב+ברגל ממולאים תוך כדי מ-Valhalla (ניתוב חיצוני keyless, לא חוסם).
*/
var map;
var isMapLoaded = false;
var nowCities = [];
var mapMouseDown = false;

City.loadDataSync();
window.addEventListener("load", function () {
  loadMap();

  const params = new URLSearchParams(location.search);
  if (params.has("history")) {
    // מצב היסטוריה: רינדור מ-params בלבד (ללא מנוי ל-background, שלא יסגור את החלון)
    renderFromParams(params);
  } else {
    // מצב live: ערים נוכחיות מה-background (snapshot ראשוני) + עדכונים שוטפים
    chrome.runtime.sendMessage("currentCities", (currentCities) => alertsListener(currentCities || []));
    // חלון שנפתח טרי בדיוק לרגע הסיום מושך את חיווי "האירוע הסתיים" הממתין (מונע מירוץ עם השידור)
    chrome.runtime.sendMessage("pendingFlash", (flash) => {
      if (flash === "ended") showEndedFlash();
    });
    chrome.runtime.onMessage.addListener((data) => {
      if (!data) return;
      // סיום אירוע (#4): הבהוב עדין + כיתוב "האירוע הסתיים", ואז סגירה אוטומטית.
      if (data.flash === "ended") return showEndedFlash();
      if (data.hasOwnProperty("cities"))
        data.cities.length ? alertsListener(data.cities) : window.close();
    });
  }

  document.getElementById("distance").addEventListener("click", onDistanceClick);
});

// רינדור חלון ממאפייני URL (מצב היסטוריה) — שקול ל-alertsListener אך מנתונים סטטיים.
function renderFromParams(params) {
  const eventType = Number(params.get("eventType"));
  const city = params.get("city") || "";
  const address = params.get("address") || "";
  const note = params.get("note") || "";
  const lat = params.has("lat") ? Number(params.get("lat")) : undefined;
  const lng = params.has("lng") ? Number(params.get("lng")) : undefined;

  const hasLoc =
    typeof lat === "number" && !Number.isNaN(lat) &&
    typeof lng === "number" && !Number.isNaN(lng) && (lat || lng);
  // אובייקט עיר-מדומה (מספיק ל-addMarkers / eventPoint): lat/lng/eventType/notificationId
  nowCities = hasLoc ? [{ eventType, lat, lng, notificationId: "history" }] : [];

  document.getElementById("eventTitle").textContent = City.getLocalizationEventTypeTitle(eventType);
  document.getElementById("locationText").textContent = address ? `${city}, ${address}` : city;

  const noteEl = document.getElementById("alertNote");
  if (note) {
    noteEl.textContent = note;
    noteEl.hidden = false;
  } else {
    noteEl.hidden = true;
  }

  if (isMapLoaded) addMarkers(nowCities);
}

// צבע הנעץ לפי סוג אירוע (גוון האקסנט נשמר; אין יותר פוליגונים)
function getColorForEventType(t) {
  switch (t) {
    case 0: return "#ffd500"; // נסיון מעצר מ.צ.
    case 2: return "#ffd500"; // התרעת מחסומים
    case 3: return "#ff8000"; // נסיון הסגרה
    default: return "#c9cbd6"; // כללי
  }
}

async function alertsListener(cities) {
  // שחזור ל-City + שימור מטא-נתוני האירוע (note/address/lat/lng) שמגיעים מה-background
  cities = cities.map((c) => {
    const city = new City(c.value, c.eventType, c.expireAt, c.timestamp);
    city.note = c.note || "";
    city.address = c.address || "";
    if (typeof c.lat === "number") city.lat = c.lat;
    if (typeof c.lng === "number") city.lng = c.lng;
    return city;
  });
  nowCities = cities;

  // כותרת = סוג(י) האירוע
  const titles = [];
  cities.forEach((c) => {
    const t = City.getLocalizationEventTypeTitle(c.eventType);
    if (!titles.includes(t)) titles.push(t);
  });
  document.getElementById("eventTitle").textContent = titles.join(" | ");

  // מיקום = "עיר, כתובת" לכל אירוע (textContent — קשיח מפני HTML/XSS)
  const locations = cities.map((c) => {
    const name = c.getLocalizationCityName();
    return c.address ? `${name}, ${c.address}` : name;
  });
  document.getElementById("locationText").textContent = locations.join(" · ");

  // הערות ייחודיות
  const noteEl = document.getElementById("alertNote");
  const notes = [];
  cities.forEach((c) => {
    if (c.note && !notes.includes(c.note)) notes.push(c.note);
  });
  if (notes.length) {
    noteEl.textContent = notes.join(" · ");
    noteEl.hidden = false;
  } else {
    noteEl.textContent = "";
    noteEl.hidden = true;
  }

  if (isMapLoaded) addMarkers(cities);
}

// סיום אירוע (#4): מציג באנר "האירוע הסתיים" + הבהוב עדין של החלון, ואז סוגר אוטומטית.
// בטוח לקריאה כפולה (סבב poll עשוי לשדר את הסיום יותר מפעם אחת) — מתבצע פעם אחת בלבד.
let endedFlashShown = false;
function showEndedFlash() {
  if (endedFlashShown) return;
  endedFlashShown = true;

  const banner = document.getElementById("eventEndedBanner");
  banner.textContent = STR("eventEnded");
  banner.hidden = false;
  document.body.classList.add("event-ended");

  // ~8ש' של הבהוב כדי שהמשתמש ישים לב, ואז סגירה אוטומטית
  setTimeout(() => window.close(), 8000);
}

const markers = {};
function addMarkers(cities) {
  const bounds = L.latLngBounds();
  const seen = new Set();

  cities.forEach((c) => {
    if (!c.lat && !c.lng) return;
    const key = c.notificationId || `${c.lat},${c.lng}`;
    seen.add(key);
    bounds.extend([c.lat, c.lng]);

    if (markers[key]) {
      markers[key].setLatLng([c.lat, c.lng]);
      return;
    }
    const color = getColorForEventType(c.eventType);
    const icon = L.divIcon({
      className: "",
      html: `<div class="bc-pin" style="background:${color}">${eventIconSvg(c.eventType, 18)}</div>`,
      iconSize: [34, 34],
      iconAnchor: [17, 33],
    });
    markers[key] = L.marker([c.lat, c.lng], { icon }).addTo(map);
  });

  // הסרת נעצים של אירועים שכבר אינם פעילים
  Object.keys(markers).forEach((key) => {
    if (!seen.has(key)) {
      map.removeLayer(markers[key]);
      delete markers[key];
    }
  });

  if (bounds.isValid() && !mapMouseDown) {
    const pts = Object.keys(markers).length;
    if (pts <= 1) map.setView(bounds.getCenter(), 16);
    else map.fitBounds(bounds, { padding: [30, 30], maxZoom: 16 });
  }
}

async function loadMap() {
  map = L.map("map", { zoomControl: false }).setView([31.5469501, 34.6863132], 8);
  map.attributionControl.setPrefix("");
  map.attributionControl.setPosition("bottomleft");

  // OpenStreetMap — keyless (עקבי עם SPEC §5.3)
  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    maxZoom: 19,
    attribution: "© OpenStreetMap",
  }).addTo(map);

  map.on("mousedown", () => (mapMouseDown = true));
  map.on("mouseup", () => (mapMouseDown = false));

  isMapLoaded = true;
  if (nowCities.length) addMarkers(nowCities);
}

/* ============================================================
   "מרחק מהמיקום שלי" — לא חוסם את הצגת ההתראה.
   זרימה בלחיצה: geolocation → מרחק אווירי מיידי (haversine, מקומי) →
   מרחק/זמן ברכב+ברגל ממולאים תוך כדי, מ-Valhalla (ניתוב חיצוני, keyless).
   ============================================================ */
let userMarker = null;
let distanceLine = null;
// undefined = בטעינה ("…"), null = נכשל (מושמט), אובייקט {km,sec} = תוצאה
let distState = { air: null, car: undefined, walk: undefined };

// מטמון מיקום: נשמר ב-chrome.storage.local (מקומי למכשיר, פרטי יותר — לא מסונכרן) אחרי האיתור
// הראשון, כך שבלחיצה הבאה מציגים אותו *מיד* ומאתרים טרי תוך כדי. {coords:[lat,lng], ts}.
const LOCATION_CACHE_KEY = "lastLocation";
const LOCATION_FRESH_MS = 30 * 60 * 1000; // עד 30 דק' — מציגים מיד; ישן מזה → ממתינים לאיתור טרי
let lastKnownLocation = null; // עותק בזיכרון לחלון הנוכחי (חוסך קריאת storage חוזרת)

function locationStore() {
  // alert.html הוא דף תוסף → chrome.storage.local זמין; נפילה ל-sync ליתר ביטחון (shim ב-Preferences.js)
  return (chrome.storage && (chrome.storage.local || chrome.storage.sync)) || null;
}
function getCachedLocation() {
  const store = locationStore();
  if (!store) return Promise.resolve(null);
  return new Promise((resolve) =>
    store.get({ [LOCATION_CACHE_KEY]: null }, (v) => resolve(v && v[LOCATION_CACHE_KEY]))
  );
}
function saveCachedLocation(loc) {
  const store = locationStore();
  if (store) store.set({ [LOCATION_CACHE_KEY]: loc });
}
function locationFresh(c) {
  return !!(
    c && Array.isArray(c.coords) && typeof c.ts === "number" && Date.now() - c.ts < LOCATION_FRESH_MS
  );
}

function STR(name) {
  try {
    return STRINGS[name][(City.siteLanguage || "HE").toLowerCase()] || STRINGS[name].he;
  } catch (e) {
    return "";
  }
}

// נקודת האירוע (הראשונה עם נ.צ תקפה) — לחישוב מרחק ולקו על המפה
function eventPoint() {
  for (const c of nowCities) {
    const lat = Number(c.lat);
    const lng = Number(c.lng);
    if ((lat || lng) && !Number.isNaN(lat) && !Number.isNaN(lng)) return [lat, lng];
  }
  return null;
}

function haversineKm(a, b) {
  const R = 6371;
  const toRad = (d) => (d * Math.PI) / 180;
  const dLat = toRad(b[0] - a[0]);
  const dLng = toRad(b[1] - a[1]);
  const s =
    Math.sin(dLat / 2) ** 2 +
    Math.cos(toRad(a[0])) * Math.cos(toRad(b[0])) * Math.sin(dLng / 2) ** 2;
  return 2 * R * Math.asin(Math.sqrt(s));
}

function fmtDist(km) {
  if (km == null || Number.isNaN(km)) return "—";
  return km < 1 ? `${Math.round(km * 1000)} מ׳` : `${km.toFixed(1)} ק״מ`;
}

function fmtDur(sec) {
  const m = Math.round(sec / 60);
  if (m < 1) return "פחות מדקה";
  if (m < 60) return `${m} דק׳`;
  const h = Math.floor(m / 60);
  const mm = m % 60;
  return mm ? `${h} ש׳ ${mm} דק׳` : `${h} ש׳`;
}

// ניתוב keyless דרך Valhalla הציבורי (FOSSGIS). timeout קצר → לא תוקע את הפס.
async function fetchRoute(costing, from, to) {
  const body = {
    locations: [
      { lat: from[0], lon: from[1] },
      { lat: to[0], lon: to[1] },
    ],
    costing,
    units: "kilometers",
  };
  const url =
    "https://valhalla1.openstreetmap.de/route?json=" + encodeURIComponent(JSON.stringify(body));
  const ctrl = new AbortController();
  const timer = setTimeout(() => ctrl.abort(), 7000);
  try {
    const res = await fetch(url, { signal: ctrl.signal });
    if (!res.ok) throw new Error(res.status);
    const data = await res.json();
    const s = data && data.trip && data.trip.summary;
    if (!s || typeof s.length !== "number") throw new Error("no summary");
    return { km: s.length, sec: s.time };
  } catch (e) {
    return null;
  } finally {
    clearTimeout(timer);
  }
}

function renderDistance() {
  const bar = document.getElementById("distanceBar");
  const seg = [`${STR("distanceAir")}: ${fmtDist(distState.air)}`];
  const part = (label, v) => {
    if (v === undefined) return `${label}: …`; // עדיין מחושב — ההתראה כבר מוצגת
    if (v === null) return null; // נכשל — מושמט (המרחק האווירי תמיד נשאר)
    return `${label}: ${fmtDist(v.km)} (${fmtDur(v.sec)})`;
  };
  const car = part(STR("distanceCar"), distState.car);
  const walk = part(STR("distanceWalk"), distState.walk);
  if (car) seg.push(car);
  if (walk) seg.push(walk);
  bar.textContent = seg.join("  ·  ");
  bar.hidden = false;
}

// מצייר את "המיקום שלך" + קו לאירוע, וממסגר את שתי הנקודות
function drawUser(me, target) {
  if (!isMapLoaded) return;
  if (userMarker) map.removeLayer(userMarker);
  if (distanceLine) map.removeLayer(distanceLine);

  const icon = L.divIcon({
    className: "",
    html: `<div class="bc-userpin" title="${STR("youAreHere")}"></div>`,
    iconSize: [24, 24],
    iconAnchor: [12, 12],
  });
  userMarker = L.marker(me, { icon }).addTo(map);
  distanceLine = L.polyline([me, target], {
    color: "#4c8dff",
    weight: 3,
    dashArray: "6 7",
    opacity: 0.9,
  }).addTo(map);

  map.fitBounds(L.latLngBounds([me, target]), { padding: [44, 44], maxZoom: 16 });
}

// מצייר את המיקום על המפה, מחשב מרחק אווירי מיידי (מקומי), וממלא רכב/רגל תוך כדי (לא חוסם).
// משותף לתצוגה מהמטמון ולתצוגה מהאיתור הטרי.
function showFromLocation(me, target) {
  drawUser(me, target);

  // מרחק אווירי — מיידי, מקומי, ללא רשת
  distState = { air: haversineKm(me, target), car: undefined, walk: undefined };
  renderDistance();

  // רכב + רגל — ממולאים תוך כדי, כל אחד מעדכן את הפס בנפרד (לא חוסם)
  fetchRoute("auto", me, target).then((r) => {
    distState.car = r;
    renderDistance();
  });
  fetchRoute("pedestrian", me, target).then((r) => {
    distState.walk = r;
    renderDistance();
  });
}

async function onDistanceClick() {
  const bar = document.getElementById("distanceBar");
  const btn = document.getElementById("distance");
  const target = eventPoint();

  if (!target) {
    bar.hidden = false;
    bar.textContent = STR("distanceNoEventLoc");
    return;
  }
  if (!navigator.geolocation) {
    bar.hidden = false;
    bar.textContent = STR("distanceGeoError");
    return;
  }

  bar.hidden = false;

  // 1) מיקום שמור (מהפעם הקודמת / מחלון קודם) → הצגה *מיידית* בלי להמתין לאיתור
  let shownCoords = null;
  const cached = lastKnownLocation || (await getCachedLocation());
  if (locationFresh(cached)) {
    lastKnownLocation = cached;
    shownCoords = cached.coords;
    showFromLocation(cached.coords, target);
  } else {
    bar.textContent = STR("distanceComputing");
  }

  // 2) איתור טרי *תוך כדי* שההתראה כבר מוצגת — מעדכן תצוגה+מטמון כשמגיע (לא חוסם)
  btn.classList.add("loading");
  navigator.geolocation.getCurrentPosition(
    (pos) => {
      btn.classList.remove("loading");
      const me = [pos.coords.latitude, pos.coords.longitude];
      lastKnownLocation = { coords: me, ts: Date.now() };
      saveCachedLocation(lastKnownLocation); // נשמר → הלחיצה הבאה תציג אותו מיד
      // אם כבר הצגנו מיקום כמעט-זהה מהמטמון (≤50מ׳) — אין צורך לצייר/לחשב מחדש (מונע ריצוד וקריאות רשת כפולות)
      if (!shownCoords || haversineKm(shownCoords, me) > 0.05) showFromLocation(me, target);
    },
    () => {
      btn.classList.remove("loading");
      // אם הצגנו מהמטמון — משאירים אותו (עדיף על הודעת שגיאה); אחרת מודיעים על כשל איתור
      if (!shownCoords) {
        bar.hidden = false;
        bar.textContent = STR("distanceGeoError");
      }
    },
    { enableHighAccuracy: true, timeout: 10000, maximumAge: 60000 }
  );
}
