import { IControl, Map } from "mapbox-gl";
import { ControlPosition } from "mapbox-gl";
import { cloneElement, memo, ReactElement, useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { useControl } from "react-map-gl/mapbox";
import { v4 as uuidv4 } from 'uuid';

type OverlayProps = {
    position: ControlPosition;
    children: ReactElement<{ map?: Map }>;
    id?: string;
};

// Definisikan custom control untuk overlay
class OverlayControl implements IControl {
    _map: Map | null = null;
    _container: HTMLElement | null = null;
    _position: ControlPosition;
    _id: string;
    _redraw?: () => void;

    constructor({ position, id, redraw }: { position: ControlPosition; id: string; redraw?: () => void }) {
        this._position = position;
        this._id = id;
        this._redraw = redraw;
    }

    onAdd(map: Map) {
        this._map = map;
        this._container = document.createElement('div');
        this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group';
        this._container.id = this._id;

        if (this._redraw) {
            map.on('move', this._redraw);
            this._redraw();
        }

        return this._container;
    }

    onRemove() {
        if (!this._map || !this._container) return;

        if (this._redraw) {
            this._map.off('move', this._redraw);
        }

        this._container.remove();
        this._map = null;
    }

    getDefaultPosition() {
        return this._position;
    }

    getMap() {
        return this._map;
    }

    getElement() {
        return this._container;
    }
}

// Komponen Overlay yang telah ditingkatkan
function _Overlay({ position, children, id = `overlay-${uuidv4()}` }: OverlayProps) {
    const [container, setContainer] = useState<HTMLElement | null>(null);
    const [map, setMap] = useState<Map | null>(null)

    // Gunakan useControl dengan ID unik untuk menghindari konflik
    const ctrl = useControl<OverlayControl>(
        () => new OverlayControl({ position, id }),
        { position } // Hanya menggunakan position yang valid dalam ControlOptions
    );

    // Update container dan map instance ketika control siap
    useEffect(() => {
        if (ctrl) {
            setContainer(ctrl.getElement());
            setMap(ctrl.getMap());
        }
    }, [ctrl]);

    // Hanya render jika container sudah siap
    if (!container || !map) return null;

    // Gunakan createPortal untuk merender children ke container
    return createPortal(
        cloneElement(children, { map }),
        container
    );
}

// Export sebagai komponen memoized
export const Overlay = memo(_Overlay);