import { i as e, t } from "../../sanitize-CDxuPfMB.js";
import { n, t as r } from "../../utils-C_mWfcFX.js";
//#region src/visualization/map/index.ts
var i = 256, a = "https://tile.openstreetmap.org/{z}/{x}/{y}.png", o = {
	lat: 0,
	lng: 0
}, s = 2, c = 256;
function l(e, t, n) {
	return Math.max(t, Math.min(n, e));
}
function u(e, t, n) {
	let r = 2 ** n * i, a = (t + 180) / 360 * r, o = l(Math.sin(e * Math.PI / 180), -.9999, .9999);
	return {
		x: a,
		y: (.5 - Math.log((1 + o) / (1 - o)) / (4 * Math.PI)) * r
	};
}
var d = class {
	id;
	container;
	config;
	tileUrl;
	minZoom;
	maxZoom;
	markers;
	regions;
	wrapperEl = null;
	tileLayerEl = null;
	markerLayerEl = null;
	popupEl = null;
	centerLat;
	centerLng;
	zoom;
	offsetX = 0;
	offsetY = 0;
	viewportWidth = 0;
	viewportHeight = 0;
	isDragging = !1;
	dragStartX = 0;
	dragStartY = 0;
	dragOffsetX = 0;
	dragOffsetY = 0;
	boundMouseDown;
	boundMouseMove;
	boundMouseUp;
	boundWheel;
	boundResize;
	tileCache = /* @__PURE__ */ new Map();
	constructor(e) {
		this.id = n("cmm-map"), this.container = r(e.container), this.config = e, this.tileUrl = e.tileUrl ?? (e.allowExternalTiles === !1 ? null : a), this.minZoom = e.minZoom ?? 1, this.maxZoom = e.maxZoom ?? 18, this.markers = e.markers === void 0 ? [] : [...e.markers], this.regions = e.regions === void 0 ? [] : [...e.regions];
		let t = e.center ?? o;
		this.centerLat = t.lat, this.centerLng = t.lng, this.zoom = l(e.zoom ?? s, this.minZoom, this.maxZoom), this.boundMouseDown = this.handleMouseDown.bind(this), this.boundMouseMove = this.handleMouseMove.bind(this), this.boundMouseUp = this.handleMouseUp.bind(this), this.boundWheel = this.handleWheel.bind(this), this.boundResize = this.handleResize.bind(this), this.render(), this.computeOffset(), this.renderTiles(), this.renderMarkers(), this.attachEvents();
	}
	setCenter(e, t) {
		this.centerLat = e, this.centerLng = t, this.closePopup(), this.computeOffset(), this.renderTiles(), this.renderMarkers();
	}
	setZoom(e) {
		let t = l(Math.round(e), this.minZoom, this.maxZoom);
		t !== this.zoom && (this.zoom = t, this.closePopup(), this.computeOffset(), this.renderTiles(), this.renderMarkers(), this.updateZoomButtons());
	}
	addMarker(e) {
		this.markers.push(e), this.renderMarkers();
	}
	removeMarker(e) {
		let t = this.markers.findIndex((t) => t.id === e);
		t >= 0 && (this.markers.splice(t, 1), this.renderMarkers());
	}
	getRegions() {
		return this.regions;
	}
	destroy() {
		this.detachEvents(), this.tileCache.clear(), this.container.innerHTML = "", this.wrapperEl = null, this.tileLayerEl = null, this.markerLayerEl = null, this.popupEl = null;
	}
	render() {
		this.container.innerHTML = "";
		let e = document.createElement("div");
		e.className = "cmm-map", e.id = this.id, this.config.className !== void 0 && e.classList.add(this.config.className);
		let t = document.createElement("div");
		t.className = "cmm-map__tile-layer", e.appendChild(t), this.tileLayerEl = t;
		let n = document.createElement("div");
		n.className = "cmm-map__marker-layer", e.appendChild(n), this.markerLayerEl = n;
		let r = document.createElement("div");
		r.className = "cmm-map__controls";
		let i = document.createElement("button");
		i.className = "cmm-map__zoom-btn", i.setAttribute("data-action", "zoom-in"), i.textContent = "+", i.setAttribute("aria-label", "Zoom in"), i.addEventListener("click", () => {
			this.setZoom(this.zoom + 1);
		}), r.appendChild(i);
		let o = document.createElement("button");
		o.className = "cmm-map__zoom-btn", o.setAttribute("data-action", "zoom-out"), o.textContent = "−", o.setAttribute("aria-label", "Zoom out"), o.addEventListener("click", () => {
			this.setZoom(this.zoom - 1);
		}), r.appendChild(o), e.appendChild(r);
		let s = document.createElement("div");
		s.className = "cmm-map__attribution", s.textContent = this.tileUrl === a ? "OpenStreetMap" : "", e.appendChild(s), this.container.appendChild(e), this.wrapperEl = e, this.viewportWidth = e.clientWidth, this.viewportHeight = e.clientHeight;
	}
	computeOffset() {
		let e = u(this.centerLat, this.centerLng, this.zoom);
		this.offsetX = e.x - this.viewportWidth / 2, this.offsetY = e.y - this.viewportHeight / 2;
	}
	renderTiles() {
		if (this.tileLayerEl === null || (this.tileLayerEl.innerHTML = "", this.tileUrl === null)) return;
		let e = 2 ** this.zoom, t = e * i, n = Math.floor(this.offsetX / i), r = Math.floor(this.offsetY / i), a = Math.ceil((this.offsetX + this.viewportWidth) / i), o = Math.ceil((this.offsetY + this.viewportHeight) / i);
		for (let s = r; s <= o; s++) for (let r = n; r <= a; r++) {
			let n = (r % e + e) % e;
			if (s < 0 || s >= e) continue;
			let a = r * i - this.offsetX, o = s * i - this.offsetY;
			if (a + i < -i || a > this.viewportWidth + i || o + i < -i || o > this.viewportHeight + i || Math.abs(a) > t || Math.abs(o) > t) continue;
			let c = `${String(this.zoom)}/${String(n)}/${String(s)}`, l = this.tileUrl.replace("{z}", String(this.zoom)).replace("{x}", String(n)).replace("{y}", String(s)), u = document.createElement("div");
			u.className = "cmm-map__tile cmm-map__tile--loading", u.style.left = `${String(a)}px`, u.style.top = `${String(o)}px`;
			let d = this.tileCache.get(c);
			if (d !== void 0) {
				this.tileCache.delete(c), this.tileCache.set(c, d);
				let e = d.cloneNode(!0);
				e.className = "cmm-map__tile", e.style.left = `${String(a)}px`, e.style.top = `${String(o)}px`, this.tileLayerEl.appendChild(e);
			} else {
				let e = document.createElement("img");
				e.className = "cmm-map__tile cmm-map__tile--loading", e.style.left = `${String(a)}px`, e.style.top = `${String(o)}px`, e.draggable = !1, e.alt = "", e.src = l, e.addEventListener("load", () => {
					e.classList.remove("cmm-map__tile--loading"), this.addToTileCache(c, e.cloneNode(!0));
				}), e.addEventListener("error", () => {
					e.classList.remove("cmm-map__tile--loading"), e.classList.add("cmm-map__tile--error");
				}), this.tileLayerEl.appendChild(e);
			}
		}
	}
	renderMarkers() {
		if (this.markerLayerEl !== null) {
			this.markerLayerEl.innerHTML = "", this.closePopup();
			for (let n of this.markers) {
				let r = u(n.lat, n.lng, this.zoom), i = r.x - this.offsetX, a = r.y - this.offsetY;
				if (i < -50 || i > this.viewportWidth + 50 || a < -50 || a > this.viewportHeight + 50) continue;
				let o = document.createElement("div");
				o.className = "cmm-map__marker", o.style.left = `${String(i)}px`, o.style.top = `${String(a)}px`, o.setAttribute("data-marker-id", n.id);
				let s = document.createElement("div");
				s.className = "cmm-map__marker-pin";
				let c = t(n.color ?? "hsl(0, 70%, 55%)");
				if (n.icon === void 0 ? e(s, `<svg viewBox="0 0 24 36" width="24" height="36" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M12 0C5.373 0 0 5.373 0 12c0 9 12 24 12 24s12-15 12-24C24 5.373 18.627 0 12 0z" fill="${c}"/>
          <circle cx="12" cy="12" r="5" fill="white" opacity="0.8"/>
        </svg>`) : e(s, n.icon), o.appendChild(s), n.label !== void 0) {
					let e = document.createElement("div");
					e.className = "cmm-map__marker-label", e.textContent = n.label, o.appendChild(e);
				}
				o.addEventListener("click", (e) => {
					e.stopPropagation(), this.config.onMarkerClick !== void 0 && this.config.onMarkerClick(n), n.popup !== void 0 && this.showPopup(n, i, a);
				}), this.markerLayerEl.appendChild(o);
			}
		}
	}
	showPopup(e, t, n) {
		if (this.closePopup(), this.wrapperEl === null) return;
		let r = document.createElement("div");
		r.className = "cmm-map__popup", r.style.left = `${String(t)}px`, r.style.top = `${String(n)}px`;
		let i = document.createElement("button");
		i.className = "cmm-map__popup-close", i.textContent = "×", i.addEventListener("click", (e) => {
			e.stopPropagation(), this.closePopup();
		}), r.appendChild(i);
		let a = document.createElement("div");
		a.textContent = e.popup ?? "", r.appendChild(a), this.wrapperEl.appendChild(r), this.popupEl = r;
	}
	closePopup() {
		this.popupEl !== null && (this.popupEl.remove(), this.popupEl = null);
	}
	updateZoomButtons() {
		if (this.wrapperEl === null) return;
		let e = this.wrapperEl.querySelector("[data-action=\"zoom-in\"]"), t = this.wrapperEl.querySelector("[data-action=\"zoom-out\"]");
		e !== null && (e.disabled = this.zoom >= this.maxZoom), t !== null && (t.disabled = this.zoom <= this.minZoom);
	}
	attachEvents() {
		this.wrapperEl !== null && (this.wrapperEl.addEventListener("mousedown", this.boundMouseDown), window.addEventListener("mousemove", this.boundMouseMove), window.addEventListener("mouseup", this.boundMouseUp), this.wrapperEl.addEventListener("wheel", this.boundWheel, { passive: !1 }), window.addEventListener("resize", this.boundResize));
	}
	detachEvents() {
		this.wrapperEl !== null && (this.wrapperEl.removeEventListener("mousedown", this.boundMouseDown), this.wrapperEl.removeEventListener("wheel", this.boundWheel)), window.removeEventListener("mousemove", this.boundMouseMove), window.removeEventListener("mouseup", this.boundMouseUp), window.removeEventListener("resize", this.boundResize);
	}
	handleMouseDown(e) {
		let t = e.target;
		t.closest(".cmm-map__controls") !== null || t.closest(".cmm-map__popup") !== null || t.closest(".cmm-map__marker") !== null || (this.isDragging = !0, this.dragStartX = e.clientX, this.dragStartY = e.clientY, this.dragOffsetX = this.offsetX, this.dragOffsetY = this.offsetY, this.closePopup());
	}
	handleMouseMove(e) {
		if (!this.isDragging) return;
		let t = e.clientX - this.dragStartX, n = e.clientY - this.dragStartY;
		this.offsetX = this.dragOffsetX - t, this.offsetY = this.dragOffsetY - n;
		let r = 2 ** this.zoom * i;
		this.offsetY = l(this.offsetY, 0, r - this.viewportHeight), this.renderTiles(), this.renderMarkers();
	}
	handleMouseUp(e) {
		this.isDragging && (this.isDragging = !1, this.updateCenterFromOffset());
	}
	handleWheel(e) {
		e.preventDefault();
		let t = e.deltaY < 0 ? 1 : -1, n = l(this.zoom + t, this.minZoom, this.maxZoom);
		if (n === this.zoom) return;
		let r = this.wrapperEl?.getBoundingClientRect();
		if (r === void 0) return;
		let a = e.clientX - r.left, o = e.clientY - r.top, s = this.offsetX + a, c = this.offsetY + o, u = 2 ** (n - this.zoom), d = s * u, f = c * u;
		this.zoom = n, this.offsetX = d - a, this.offsetY = f - o;
		let p = 2 ** this.zoom * i;
		this.offsetY = l(this.offsetY, 0, p - this.viewportHeight), this.updateCenterFromOffset(), this.closePopup(), this.renderTiles(), this.renderMarkers(), this.updateZoomButtons();
	}
	handleResize() {
		this.wrapperEl !== null && (this.viewportWidth = this.wrapperEl.clientWidth, this.viewportHeight = this.wrapperEl.clientHeight, this.computeOffset(), this.renderTiles(), this.renderMarkers());
	}
	addToTileCache(e, t) {
		for (; this.tileCache.size >= c;) {
			let e = this.tileCache.keys().next().value;
			if (e !== void 0) this.tileCache.delete(e);
			else break;
		}
		this.tileCache.set(e, t);
	}
	updateCenterFromOffset() {
		let e = 2 ** this.zoom * i, t = this.offsetX + this.viewportWidth / 2, n = this.offsetY + this.viewportHeight / 2;
		this.centerLng = t / e * 360 - 180;
		let r = Math.PI - 2 * Math.PI * n / e;
		this.centerLat = 180 / Math.PI * Math.atan(.5 * (Math.exp(r) - Math.exp(-r)));
	}
};
//#endregion
export { d as ThreatMap };

//# sourceMappingURL=index.js.map