var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
import { jsx as _jsx } from "react/jsx-runtime";
import { memo, useEffect, useRef, useState, useCallback } from 'react';
import { useAppDispatch, useAppSelector } from 'src/app/redux/store';
import { setClickedMarkerId, setHoveredMarkerId, setScrollToDocId, } from 'src/app/redux/slices/common';
import InfoWindow from './InfoWindow';
import { Provider } from 'react-redux';
import { store } from 'src/app/redux/store';
import { createRoot } from 'react-dom/client';
import css from './Maps.module.scss';
import { _cx } from 'src/utility/class';
var cx = _cx(css);
var PIN_DIMENSIONS = {
    width: 16,
    height: 20,
};
var PIN_URLS = {
    normal: 'https://images.ctfassets.net/vh25xg5i1h5l/33JZ6K7iuALyUtU35tK861/2216f0b26432e0500a8fab2648adac93/map_pin.svg',
    active: 'https://images.ctfassets.net/vh25xg5i1h5l/3Kie2nU70mZLjBXLxOH1FB/a74414a6c12571c3de62352492c07e62/map_pin_active.svg',
};
var createPinIcon = function (isActive) { return ({
    url: isActive ? PIN_URLS.active : PIN_URLS.normal,
    size: new google.maps.Size(PIN_DIMENSIONS.width, PIN_DIMENSIONS.height),
    scaledSize: new google.maps.Size(PIN_DIMENSIONS.width, PIN_DIMENSIONS.height),
    anchor: new google.maps.Point(PIN_DIMENSIONS.width / 2, PIN_DIMENSIONS.height),
    origin: new google.maps.Point(0, 0),
}); };
var GoogleMap = function (_a) {
    var markerData = _a.markerData, zipLatLng = _a.zipLatLng, _b = _a.isMobile, isMobile = _b === void 0 ? false : _b;
    var dispatch = useAppDispatch();
    var mapRef = useRef(null);
    var _c = __read(useState(null), 2), map = _c[0], setMap = _c[1];
    var _d = __read(useState({}), 2), markers = _d[0], setMarkers = _d[1];
    var _e = __read(useState(null), 2), infoWindow = _e[0], setInfoWindow = _e[1];
    var _f = useAppSelector(function (state) { return state.common; }), hoveredMarkerId = _f.hoveredMarkerId, clickedMarkerId = _f.clickedMarkerId;
    var _g = useAppSelector(function (state) { return state.config.config; }), googleKey = _g.googleKey, localeId = _g.localeId;
    // Create InfoWindow content
    var createInfoWindowContent = useCallback(function (location) {
        var container = document.createElement('div');
        var root = createRoot(container);
        // Render the content
        root.render(_jsx(Provider, { store: store, children: _jsx(InfoWindow, { marker: location, isMobile: isMobile }) }));
        // Add deferred cleanup function
        container.cleanup = function () {
            // Defer unmount to next tick to avoid React rendering conflicts
            Promise.resolve().then(function () {
                root.unmount();
            });
        };
        return container;
    }, [isMobile]);
    // Update marker icon and z-index
    var updateMarkerState = useCallback(function (marker, isActive) {
        marker.setIcon(createPinIcon(isActive));
        marker.setZIndex(isActive ? google.maps.Marker.MAX_ZINDEX + 1 : google.maps.Marker.MAX_ZINDEX);
    }, []);
    // Handle hover states only
    useEffect(function () {
        if (!markers)
            return;
        Object.entries(markers).forEach(function (_a) {
            var _b = __read(_a, 2), docId = _b[0], marker = _b[1];
            var isActive = Number(docId) === hoveredMarkerId || Number(docId) === clickedMarkerId;
            updateMarkerState(marker, isActive);
        });
    }, [hoveredMarkerId, markers, clickedMarkerId, updateMarkerState]);
    // Handle InfoWindow separately
    useEffect(function () {
        if (!map || !infoWindow || !markers || !clickedMarkerId)
            return;
        var marker = markers[clickedMarkerId];
        var location = markerData.find(function (doc) { return doc.DocID === clickedMarkerId; });
        if (marker && location && !isMobile) {
            var content = infoWindow.getContent();
            if (content && content.cleanup) {
                content.cleanup();
            }
            infoWindow.setContent(createInfoWindowContent(location));
            infoWindow.open(map, marker);
        }
        return function () {
            if (infoWindow) {
                var content = infoWindow.getContent();
                if (content && content.cleanup) {
                    content.cleanup();
                }
                infoWindow.close();
            }
        };
    }, [clickedMarkerId, markers, map, infoWindow, createInfoWindowContent, isMobile, markerData]);
    // Initialize map
    useEffect(function () {
        var _a;
        if (!mapRef.current || !((_a = window.google) === null || _a === void 0 ? void 0 : _a.maps) || map)
            return;
        var mapInstance = new google.maps.Map(mapRef.current, {
            zoom: isMobile ? 14 : 10,
            mapTypeControl: true,
            scaleControl: true,
            minZoom: 0,
            streetViewControl: false,
            fullscreenControl: false,
            draggable: true,
        });
        var bounds = getBounds();
        if (bounds) {
            mapInstance.fitBounds(bounds);
            google.maps.event.addListenerOnce(mapInstance, 'idle', function () {
                if (mapInstance.getZoom() > 16)
                    mapInstance.setZoom(16);
            });
        }
        var infoWindowInstance = new google.maps.InfoWindow();
        infoWindowInstance.addListener('closeclick', function () {
            var content = infoWindowInstance.getContent();
            if (content && content.cleanup) {
                content.cleanup();
            }
            dispatch(setClickedMarkerId(0));
        });
        setInfoWindow(infoWindowInstance);
        setMap(mapInstance);
        return function () {
            var content = infoWindowInstance.getContent();
            if (content && content.cleanup) {
                content.cleanup();
            }
        };
    }, [isMobile]);
    // Create/update markers
    useEffect(function () {
        if (!map)
            return;
        Object.values(markers).forEach(function (marker) { return marker.setMap(null); });
        var newMarkers = {};
        markerData.forEach(function (location) {
            var _a, _b, _c;
            var isActive = location.DocID === hoveredMarkerId || location.DocID === clickedMarkerId;
            var marker = new google.maps.Marker({
                map: map,
                position: { lat: Number(location.Latitude), lng: Number(location.Longitude) },
                title: ((_a = location.PreferredName) === null || _a === void 0 ? void 0 : _a.toUpperCase()) ||
                    ((_b = location.PracticeName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) ||
                    ((_c = location.FullName) === null || _c === void 0 ? void 0 : _c.toUpperCase()),
                icon: createPinIcon(isActive),
                optimized: true,
            });
            marker.addListener('click', function () {
                if (isMobile)
                    return;
                var newClickedId = location.DocID === clickedMarkerId ? 0 : location.DocID;
                dispatch(setClickedMarkerId(newClickedId));
                dispatch(setScrollToDocId(newClickedId));
            });
            if (!isMobile) {
                marker.addListener('mouseover', function () {
                    dispatch(setHoveredMarkerId(location.DocID));
                });
                marker.addListener('mouseout', function () {
                    dispatch(setHoveredMarkerId(0));
                });
            }
            newMarkers[location.DocID] = marker;
        });
        setMarkers(newMarkers);
        // Add zip location marker
        if (zipLatLng.lat && zipLatLng.lng) {
            new google.maps.Marker({
                map: map,
                position: { lat: Number(zipLatLng.lat), lng: Number(zipLatLng.lng) },
                title: 'Your Location',
                icon: {
                    url: 'https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi2_hdpi.png',
                    scaledSize: new google.maps.Size(27, 43),
                    anchor: new google.maps.Point(13, 43),
                },
                zIndex: google.maps.Marker.MAX_ZINDEX + 2,
            });
        }
        return function () {
            Object.values(newMarkers).forEach(function (marker) { return marker.setMap(null); });
        };
    }, [map, markerData, isMobile, zipLatLng]);
    // Calculate bounds
    var getBounds = useCallback(function () {
        var _a;
        if (!((_a = window.google) === null || _a === void 0 ? void 0 : _a.maps))
            return null;
        var bounds = new google.maps.LatLngBounds();
        var points = zipLatLng.lat
            ? __spreadArray(__spreadArray([], __read(markerData), false), [{ Latitude: zipLatLng.lat, Longitude: zipLatLng.lng }], false) : markerData;
        points.forEach(function (point) {
            bounds.extend({
                lat: Number(point.Latitude),
                lng: Number(point.Longitude),
            });
        });
        return bounds;
    }, [markerData, zipLatLng]);
    return (_jsx("div", { ref: mapRef, className: cx('map-container'), style: { width: '100%', height: '100%' } }));
};
export default memo(GoogleMap);
