"use client";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from "react";
import * as L from "leaflet";
import Leaflet from "leaflet";
import classNames from "classnames";
import { AttributionControl, MapContainer, useMap, useMapEvents, } from "react-leaflet";
import Button from "jt-design-system/es/button";
import Tooltip from "jt-design-system/es/tooltip";
import { useEdenContext } from "eden/context";
import ColorPicker from "./color-picker";
import FullScreenButton from "./full-screen-button";
import Geoman from "./geoman";
import InitialMarkerForm from "./initial-marker-form";
import MarkerList from "./marker-list";
import Markers from "./markers";
import { MyLocation } from "./icons";
import { drawShape, getLayerLatLngs, MARKER_SHAPE } from "./utils/shapes";
import css from "./editable-map.module.css";
import "leaflet/dist/leaflet.css";
import "maplibre-gl/dist/maplibre-gl.css";
import "@maplibre/maplibre-gl-leaflet";
const DEFAULT_CENTER = [46.807934, 3.645097];
const DEFAULT_ZOOM = 6;
const DEFAULT_COLOR = "#1f2933";
const MARKER_LIST_THRESHOLD = 2;
const MIN_ZOOM = 1;
const MAX_ZOOM = 19;
const MAX_BOUNDS = [
    [180, -Infinity],
    [-180, Infinity],
];
const STYLE_URL = "https://tiles.openfreemap.org/styles/liberty";
const ATTRIBUTION = '<a href="https://openfreemap.org">OpenFreeMap</a> <a href="https://www.openmaptiles.org/">&copy; OpenMapTiles</a> Data from <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>';
const NEW_MARKER = {
    id: 1,
    title: "Nouveau point d'intérêt",
    description: "",
    url: "",
    label: "",
    tooltipOpened: false,
};
export default function EditableMap({ format }) {
    const { element, isInDialog, isInEditor, presets } = format;
    const { edenMode } = useEdenContext();
    const mapRef = React.useRef(null);
    const containerRef = React.useRef(null);
    const [mapIsReady, setMapIsReady] = React.useState(false);
    const [fullScreen, setFullScreen] = React.useState(false);
    const [listOpened, setListOpened] = React.useState(true);
    const [center, setCenter] = React.useState(presets.center ?? DEFAULT_CENTER);
    const [zoom, setZoom] = React.useState(presets.zoom ?? DEFAULT_ZOOM);
    const [markers, setMarkers] = React.useState(presets.markers ?? []);
    const [shapes, setShapes] = React.useState(presets.shapes ?? []);
    const [isMarkerListSorted, setIsMarkerListSorted] = React.useState(Boolean(presets.isMarkerListSorted));
    const [color, setColor] = React.useState(DEFAULT_COLOR);
    const isEditing = isInEditor && edenMode === "editing";
    const updateLayerGeometry = React.useCallback((layer) => {
        const id = layer._customId;
        if (id === undefined) {
            return;
        }
        if (layer._shapeType === MARKER_SHAPE) {
            const position = layer.getLatLng();
            setMarkers((current) => current.map((marker) => marker.id === id ? { ...marker, position } : marker));
            return;
        }
        const latlngs = getLayerLatLngs(layer);
        const radius = layer instanceof L.Circle ? layer.getRadius() : undefined;
        setShapes((current) => current.map((shape) => shape.id === id
            ? { ...shape, latlngs, radius: radius ?? shape.radius }
            : shape));
    }, []);
    React.useEffect(() => {
        const map = mapRef.current;
        if (!map || !mapIsReady || !presets.shapes?.length) {
            return;
        }
        const layers = presets.shapes
            .map((shape) => drawShape(map, shape))
            .filter((layer) => Boolean(layer));
        layers.forEach((layer) => {
            layer.on("pm:edit", (event) => updateLayerGeometry(event.layer));
            layer.on("pm:dragend", (event) => updateLayerGeometry(event.layer));
        });
        return () => {
            layers.forEach((layer) => map.removeLayer(layer));
        };
    }, [mapIsReady, presets.shapes, updateLayerGeometry]);
    React.useEffect(() => {
        if (!isEditing) {
            return;
        }
        element.setAttribute("data-presets", JSON.stringify({ center, zoom, markers, shapes, isMarkerListSorted }));
    }, [center, element, isEditing, isMarkerListSorted, markers, shapes, zoom]);
    React.useEffect(() => {
        const container = containerRef.current;
        if (!container) {
            return;
        }
        const observer = new ResizeObserver(() => mapRef.current?.invalidateSize());
        observer.observe(container);
        return () => observer.disconnect();
    }, []);
    const resetCenter = () => {
        setCenter(DEFAULT_CENTER);
        setZoom(DEFAULT_ZOOM);
        mapRef.current?.setView(DEFAULT_CENTER, DEFAULT_ZOOM, { animate: true });
    };
    const addInitialMarker = (position) => {
        setMarkers([{ ...NEW_MARKER, position }]);
        mapRef.current?.setView(position, 13);
    };
    const showMarkerList = markers.length > MARKER_LIST_THRESHOLD;
    const classes = classNames(css.editableMap, {
        [css.editing]: isEditing,
        [css.fullScreen]: fullScreen,
    });
    return (_jsxs("div", { ref: containerRef, className: classes, "data-eden-remove-on-save": "", children: [_jsxs(MapContainer, { ref: mapRef, className: css.map, center: center, zoom: zoom, minZoom: MIN_ZOOM, maxZoom: MAX_ZOOM, maxBounds: MAX_BOUNDS, maxBoundsViscosity: 1, scrollWheelZoom: isInDialog || fullScreen, attributionControl: false, whenReady: () => setMapIsReady(true), children: [_jsx(VectorTiles, {}), _jsx(MapEvents, { setCenter: setCenter, setZoom: setZoom }), isEditing && (_jsxs(_Fragment, { children: [_jsx(Geoman, { color: color, setMarkers: setMarkers, setShapes: setShapes, onLayerChange: updateLayerGeometry }), _jsx(ColorPicker, { color: color, setColor: setColor, alignedToRight: !showMarkerList })] })), _jsx(Markers, { markers: markers, setMarkers: setMarkers, isEditing: isEditing, onLayerChange: updateLayerGeometry }), _jsx(AttributionControl, { position: "bottomright", prefix: "" })] }), isEditing && !markers.length && (_jsx(InitialMarkerForm, { onSubmit: addInitialMarker })), !isEditing && (_jsxs(_Fragment, { children: [_jsx(FullScreenButton, { containerRef: containerRef, fullScreen: fullScreen, setFullScreen: setFullScreen, isInDialog: isInDialog, markerListOpened: showMarkerList && listOpened }), _jsx(Tooltip, { content: "Recentrer", contentProps: { side: "left" }, children: _jsx(Button, { type: "button", variant: "secondary", className: classNames(css.resetCenter, {
                                [css.resetCenterInDialog]: isInDialog,
                                [css.resetCenterAlignedToRight]: !showMarkerList || !listOpened,
                            }), onClick: resetCenter, compact: true, children: _jsx(MyLocation, {}) }) })] })), showMarkerList && (_jsx(MarkerList, { markers: markers, setMarkers: setMarkers, isSorted: isMarkerListSorted, setIsSorted: setIsMarkerListSorted, isEditing: isEditing, opened: listOpened, setOpened: setListOpened, mapRef: mapRef }))] }));
}
function VectorTiles() {
    const map = useMap();
    React.useEffect(() => {
        const layer = Leaflet.maplibreGL({
            style: STYLE_URL,
            attributionControl: { customAttribution: ATTRIBUTION },
        }).addTo(map);
        return () => {
            layer.remove();
        };
    }, [map]);
    return null;
}
function MapEvents({ setCenter, setZoom }) {
    const map = useMapEvents({
        dragend: () => setCenter(map.getCenter()),
        zoomend: () => setZoom(map.getZoom()),
    });
    return null;
}
