// src/map.tsx
import * as maplibre from "maplibre-gl";
import {
  createContext as createContext2,
  createSignal as createSignal2,
  onCleanup as onCleanup2,
  onMount,
  useContext as useContext2,
  createEffect,
  splitProps,
  createMemo,
  createUniqueId
} from "solid-js";

// src/maps.tsx
import { createSignal, createContext, useContext } from "solid-js";
var MapsContext = createContext();
function MapsProvider(props) {
  const [maps, setMaps] = createSignal(/* @__PURE__ */ new Map(), {
    equals: false
  });
  const onMapMount = (map, id) => {
    setMaps((maps2) => maps2.set(id, map));
  };
  const onMapUnmount = (id) => setMaps((maps2) => {
    maps2.delete(id);
    return maps2;
  });
  return <MapsContext.Provider
    value={{
      maps,
      onMapMount,
      onMapUnmount
    }}
  >
      {props.children}
    </MapsContext.Provider>;
}
var useMaps = () => useContext(MapsContext);

// src/util.ts
import { onCleanup } from "solid-js";
function deepEqual(a, b) {
  if (typeof a !== typeof b) return false;
  if (typeof a === "object" && typeof b === "object" && a !== null && b !== null) {
    for (const key in a) {
      if (!(key in b)) return false;
      if (!deepEqual(a[key], b[key]))
        return false;
    }
    for (const key in b) {
      if (!(key in a)) return false;
      if (!deepEqual(a[key], b[key]))
        return false;
    }
    return true;
  }
  return a === b;
}
function addEventListeners(target, listeners) {
  for (const [key, listener] of Object.entries(listeners)) {
    if (!key.startsWith("on")) {
      continue;
    }
    const name = key.slice(2).toLowerCase();
    target.on(name, listener);
    onCleanup(() => {
      target.off(name, listener);
    });
  }
}

// src/map.tsx
var MapContext = createContext2();
var useMap = () => useContext2(MapContext);
var useMapEffect = (f) => createEffect(() => {
  const map = useMap()?.();
  if (map) {
    f(map);
  }
});
function Map3(initial) {
  const [props, events] = splitProps(initial, [
    "id",
    "style",
    "class",
    "classList",
    "cursor",
    "options",
    "children"
  ]);
  const id = createMemo(() => props.id ?? createUniqueId());
  const defaultStyle = createMemo(
    () => !props.style && !props.class && !props.classList ? { position: "relative", width: "100%", "aspect-ratio": "calc(16/9)" } : void 0
  );
  const container = <div
    id={id()}
    class={props.class}
    classList={props.classList}
    style={props.style ?? defaultStyle()}
  />;
  const [map, setMap] = createSignal2();
  const mapsContext = useMaps();
  onMount(() => {
    const map2 = new maplibre.Map({
      style: "https://demotiles.maplibre.org/style.json",
      ...props.options,
      container
    });
    mapsContext?.onMapMount(map2, id());
    void map2.once("load", () => setMap(map2));
  });
  const interactive = createMemo(
    () => typeof props.options?.interactive === "undefined" || props.options.interactive
  );
  createEffect(() => {
    const canvas = map()?.getCanvas();
    if (canvas) canvas.style.cursor = props.cursor ?? interactive() ? "grab" : "auto";
  });
  createEffect(() => {
    const m = map();
    if (m) {
      addEventListeners(m, events);
    }
  });
  onCleanup2(() => {
    map()?.remove();
    mapsContext?.onMapUnmount(id());
  });
  return <MapContext.Provider value={map}>
      {container}
      {props.children}
    </MapContext.Provider>;
}

// src/source.tsx
import { createContext as createContext3, onCleanup as onCleanup3, useContext as useContext3, createUniqueId as createUniqueId2, createMemo as createMemo2 } from "solid-js";
var SourceIdContext = createContext3();
var useSource = () => useContext3(SourceIdContext);
function Source(props) {
  const id = createMemo2(() => props.id ?? createUniqueId2());
  useMapEffect((map) => {
    if (!map.getSource(id())) {
      map.addSource(id(), props.source);
    }
  });
  onCleanup3(() => useMap()?.()?.getSource(id()) && useMap()?.()?.removeSource(id()));
  return <SourceIdContext.Provider value={id()}>{props.children}</SourceIdContext.Provider>;
}

// src/layer.tsx
import { onCleanup as onCleanup4, createUniqueId as createUniqueId3, splitProps as splitProps2, createMemo as createMemo3 } from "solid-js";
function Layer(initial) {
  const [props, events] = splitProps2(initial, ["id", "layer"]);
  const id = createMemo3(() => props.id ?? createUniqueId3());
  const sourceId = useSource();
  useMapEffect((map) => {
    if (!sourceId || map.getLayer(id())) return;
    map.addLayer({
      ...props.layer,
      id: id(),
      source: sourceId
    });
  });
  useMapEffect((map) => {
    if (!map.getLayer(id())) return;
    for (const [k, v] of Object.entries(props.layer.paint ?? {})) {
      const old = map.getPaintProperty(id(), k);
      if (!deepEqual(old, v)) {
        map.setPaintProperty(id(), k, v);
      }
    }
    const oldFilter = map.getFilter(id());
    if (!deepEqual(oldFilter, props.layer.filter)) {
      map.setFilter(id(), props.layer.filter);
    }
  });
  useMapEffect((map) => {
    for (const [key, handler] of Object.entries(events)) {
      if (!key.startsWith("on")) continue;
      const name = key.slice(2).toLowerCase();
      map.on(name, id(), handler);
      onCleanup4(() => map.off(name, id(), handler));
    }
  });
  onCleanup4(() => useMap()?.()?.getLayer(id()) && useMap()?.()?.removeLayer(id()));
  return <></>;
}

// src/marker.tsx
import * as maplibre2 from "maplibre-gl";
import { createEffect as createEffect2, createSignal as createSignal3, onCleanup as onCleanup5, onMount as onMount2, splitProps as splitProps3 } from "solid-js";
function Marker2(initial) {
  const [props, rest] = splitProps3(initial, ["position"]);
  const [events, options] = splitProps3(rest, ["ondrag", "ondragstart", "ondragend"]);
  const [marker, setMarker] = createSignal3();
  onMount2(() => {
    setMarker(new maplibre2.Marker(options));
  });
  createEffect2(() => {
    const m = marker();
    if (m) {
      addEventListeners(m, events);
    }
  });
  createEffect2(() => {
    const m = marker();
    if (m) {
      m.setLngLat(props.position);
      m.setDraggable(options.draggable);
      m.setOffset(options.offset ?? [0, 0]);
      m.setOpacity(options.opacity, options.opacityWhenCovered);
      m.setPitchAlignment(options.pitchAlignment);
      m.setRotation(options.rotation);
      m.setRotationAlignment(options.rotationAlignment);
      m.setSubpixelPositioning(options.subpixelPositioning ?? false);
    }
  });
  useMapEffect((map) => {
    marker()?.addTo(map);
  });
  onCleanup5(() => {
    marker()?.remove();
  });
  return <></>;
}

// src/popup.tsx
import * as maplibre3 from "maplibre-gl";
import { onCleanup as onCleanup6, splitProps as splitProps4 } from "solid-js";
function Popup2(initial) {
  const [props, options] = splitProps4(initial, ["position", "content"]);
  let popup;
  useMapEffect((map) => {
    if (!popup) popup = new maplibre3.Popup(options);
    if (props.position && props.content) {
      popup.setLngLat(props.position).setHTML(props.content).addTo(map);
    } else {
      popup.remove();
    }
  });
  onCleanup6(() => popup?.remove());
  return <></>;
}

// src/controls.tsx
import * as maplibre4 from "maplibre-gl";
import { onCleanup as onCleanup7, splitProps as splitProps5 } from "solid-js";
var createControl = (ctor) => (props) => {
  const [own, options] = splitProps5(props, ["position"]);
  let control;
  useMapEffect((map) => {
    if (!control) {
      control = new ctor(options.options ?? {});
      map.addControl(control, own.position);
    }
  });
  onCleanup7(() => {
    const m = useMap()?.();
    if (control && m && m.hasControl(control)) m.removeControl(control);
  });
  return <></>;
};
var NavigationControl2 = createControl(maplibre4.NavigationControl);
var ScaleControl2 = createControl(maplibre4.ScaleControl);
export {
  Layer,
  Map3 as Map,
  MapContext,
  MapsContext,
  MapsProvider,
  Marker2 as Marker,
  NavigationControl2 as NavigationControl,
  Popup2 as Popup,
  ScaleControl2 as ScaleControl,
  Source,
  SourceIdContext,
  createControl,
  useMap,
  useMapEffect,
  useMaps,
  useSource
};
