import { useEffect, useMemo, useRef, useState } from '@byted-doubao-apps/framework';
import { registerMapController, unregisterMapController } from '../../internal/map-context/index.js';
import { Image } from '../Image/index.jsx';
import { warnUnsupported } from '../base/warn-unsupported.js';
import { composeMarkers, createMarkerElementProps, dispatchMarkerTapEvent, getNumericMarkerId, hasByClickCallout, hasTapTitle, mapMarkerToNativeProps, mapPolylineTapDetail, mapRegionChangeDetail, mergeMarkersById, removeMarkersByIds, resolveMarkerIconStyle, resolveNativePolygons, resolveMarkerTextContent, resolvePolylines, shouldAutoSizeMarkerIcon, resolvePadding } from './bridge.js';
import { collectMapUnsupportedWarnings, mergeMapStyle, resolveNativeCircles, resolveMapValues, toCommonEvent } from './mapping.js';
function DoubaoAppsMap(props) {
    const { id, className, style, hidden, animation, children, onTouchStart, onTouchMove, onTouchCancel, onTouchEnd, onClick: onBaseClick, onLongPress, onLongClick, onTransitionEnd, onAnimationStart, onAnimationIteration, onAnimationEnd, longitude, latitude, scale, minScale, maxScale, markers, covers, polyline, circles, controls, includePoints, showLocation, polygons, subkey, layerStyle, rotate, skew, showCompass, showScale, enableOverlooking, enableZoom, enableScroll, enableRotate, enableSatellite, enableTraffic, setting, includePadding, groundOverlays, tileOverlay, enablePoi, enableBuilding, polygon, customMapStyle, panels, theme, optimize, enableAutoMaxOverlooking, enable3D, onTap, onMarkerTap, onLabelTap, onControlTap, onCalloutTap, onUpdated, onRegionChange, onPoiTap, onPolylineTap, onAbilitySuccess, onAbilityFailed, onAuthSuccess, onInterpolatePoint, onError, onCallOutTap, onAnchorPointTap, onPanelTap, onInitComplete, ...rest } = props;
    const mapRef = useRef(null);
    const mapControllerRef = useRef(null);
    const markerRefsRef = useRef(new Map());
    const [activeCalloutMarkerId, setActiveCalloutMarkerId] = useState(undefined);
    const [imperativeAddedMarkers, setImperativeAddedMarkers] = useState([]);
    const [imperativeRemovedMarkerIds, setImperativeRemovedMarkerIds] = useState([]);
    const rawMapStyle = props.mapStyle;
    const passedThroughMapStyle = typeof rawMapStyle === 'string' ? rawMapStyle : undefined;
    const unsupportedRest = { ...rest };
    delete unsupportedRest.mapStyle;
    const resolvedCenter = useMemo(() => ({
        latitude,
        longitude
    }), [latitude, longitude]);
    const { resolvedSetting, resolvedScale, resolvedMinScale, resolvedMaxScale, resolvedRotate, resolvedShowScale, resolvedEnableTilt, resolvedEnableScale, resolvedEnableDrag, resolvedEnableRotate, resolvedMarkers, resolvedPolygons, resolvedMapStyle } = resolveMapValues({
        setting,
        scale,
        minScale,
        maxScale,
        rotate,
        showScale,
        enableOverlooking,
        enableZoom,
        enableScroll,
        enableRotate,
        markers,
        covers,
        polygons,
        polygon,
        customMapStyle
    });
    const mapId = id ? String(id) : '';
    if (!mapControllerRef.current) {
        mapControllerRef.current = createMapController({
            mapRef,
            setImperativeAddedMarkers,
            setImperativeRemovedMarkerIds
        });
    }
    const unsupported = collectMapUnsupportedWarnings({
        unsupportedValues: {
            animation,
            controls,
            subkey,
            layerStyle,
            skew,
            showCompass,
            enableSatellite,
            enableTraffic,
            groundOverlays,
            tileOverlay,
            enablePoi,
            enableBuilding,
            panels,
            theme,
            optimize,
            enableAutoMaxOverlooking,
            enable3D,
            onTouchStart,
            onTouchMove,
            onTouchCancel,
            onTouchEnd,
            onLongPress,
            onLongClick,
            onTransitionEnd,
            onAnimationStart,
            onAnimationIteration,
            onAnimationEnd,
            onControlTap,
            onPoiTap,
            onAbilitySuccess,
            onAbilityFailed,
            onAuthSuccess,
            onInterpolatePoint,
            onError,
            onAnchorPointTap,
            onPanelTap
        },
        customMapStyle,
        resolvedMapStyle,
        includePadding,
        includePoints,
        rest: unsupportedRest,
        resolvedSetting,
        resolvedMarkers,
        polyline,
        circles,
        resolvedPolygons
    });
    warnUnsupported('Map', unsupported);
    const { top: includePaddingTop, right: includePaddingRight, bottom: includePaddingBottom, left: includePaddingLeft } = includePadding ?? {};
    useEffect(() => {
        if (!mapControllerRef.current || !includePoints?.length) {
            return;
        }
        const padding = includePadding ? resolvePadding(includePadding) : undefined;
        void mapControllerRef.current.fitPoints(includePoints, padding);
    }, [
        includePoints,
        includePaddingTop,
        includePaddingRight,
        includePaddingBottom,
        includePaddingLeft,
        mapControllerRef
    ]);
    useEffect(() => {
        if (!mapId || !mapControllerRef.current) {
            return;
        }
        const controller = mapControllerRef.current;
        registerMapController(mapId, controller);
        return () => {
            unregisterMapController(mapId, controller);
        };
    }, [mapId]);
    const markerTapHandlers = {
        onMarkerTap,
        onLabelTap,
        onCalloutTap,
        onCallOutTap
    };
    const shouldDispatchMarkerTap = onMarkerTap !== undefined ||
        onLabelTap !== undefined ||
        onCalloutTap !== undefined ||
        onCallOutTap !== undefined;
    const renderMarkers = composeMarkers(resolvedMarkers, imperativeAddedMarkers, imperativeRemovedMarkerIds);
    return (<map className={className || ''} ref={mapRef} style={mergeMapStyle(style, hidden)} 
    // @ts-expect-error
    enableNativeInteraction={rest.enableNativeInteraction} mapStyle={passedThroughMapStyle ?? resolvedMapStyle} 
    // @ts-ignore
    center={longitude !== undefined && latitude !== undefined ? resolvedCenter : undefined} scale={resolvedScale} minScale={resolvedMinScale} maxScale={resolvedMaxScale} rotate={resolvedRotate} showScale={resolvedShowScale} showLocation={showLocation} enableTilt={resolvedEnableTilt} enableScale={resolvedEnableScale} enableDrag={resolvedEnableDrag} enableRotate={resolvedEnableRotate} polyline={resolvePolylines(polyline)} circles={resolveNativeCircles(circles)} polygons={resolveNativePolygons(resolvedPolygons)} onClick={(detail) => {
            const event = toCommonEvent({ point: detail.point }, 'tap', mapId);
            onTap?.(event);
            onBaseClick?.(event);
        }} onMapLoaded={() => {
            const event = toCommonEvent(undefined, 'updated', mapId);
            onUpdated?.(event);
            onInitComplete?.(event);
        }} onRegionChange={(detail) => {
            onRegionChange?.(toCommonEvent(mapRegionChangeDetail(detail), 'regionchange', mapId));
        }} onPolylineClick={(detail) => {
            onPolylineTap?.(toCommonEvent(mapPolylineTapDetail(detail), 'polylinetap', mapId));
        }}>
      {renderMarkers.map((marker, index) => {
            const nativeMarker = mapMarkerToNativeProps(marker, index);
            const markerId = nativeMarker.markerId;
            const markerTapEvent = toCommonEvent({
                markerId
            }, 'markertap', mapId);
            const shouldActivateByClickCallout = hasByClickCallout(marker);
            const shouldActivateTitle = hasTapTitle(marker);
            const shouldActivateMarkerText = shouldActivateByClickCallout || shouldActivateTitle;
            const handleMarkerClick = shouldDispatchMarkerTap || shouldActivateMarkerText
                ? () => {
                    if (shouldActivateMarkerText) {
                        setActiveCalloutMarkerId(markerId);
                    }
                    if (shouldDispatchMarkerTap) {
                        dispatchMarkerTapEvent(markerTapHandlers, markerTapEvent);
                    }
                }
                : undefined;
            const markerElementProps = createMarkerElementProps({
                nativeMarker,
                onClick: handleMarkerClick
            });
            const handleMarkerLayout = () => {
                const ref = markerRefsRef.current.get(markerId);
                ref?.refreshMarker?.();
            };
            const markerContent = marker.children != null
                ? marker.children
                : renderDefaultMarkerContent(marker, markerId, activeCalloutMarkerId, handleMarkerLayout);
            const markerElementPropsWithRef = {
                ...markerElementProps,
                ref: (node) => {
                    if (node) {
                        markerRefsRef.current.set(markerId, node);
                    }
                    else {
                        markerRefsRef.current.delete(markerId);
                    }
                }
            };
            return (
            // biome-ignore lint: key is not sure
            <map-marker {...markerElementPropsWithRef}>{markerContent}</map-marker>);
        })}
      {children}
    </map>);
}
function renderDefaultMarkerContent(marker, markerId, activeCalloutMarkerId, onLayout) {
    const textContent = resolveMarkerTextContent(marker, markerId, activeCalloutMarkerId);
    const iconStyle = resolveMarkerIconStyle(marker);
    const shouldAutoSizeIcon = shouldAutoSizeMarkerIcon(marker);
    return (<view flatten={false} bindlayoutchange={onLayout} style={{
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center'
        }}>
      {textContent.callout ? (<view flatten={false} style={{
                ...(textContent.callout.style || {}),
                position: textContent.callout.style?.position !== undefined
                    ? textContent.callout.style.position
                    : 'relative',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                overflow: 'visible',
                paddingBottom: '4px'
            }}>
          <text style={{
                color: textContent.callout.style?.color,
                fontSize: textContent.callout.style?.fontSize,
                textAlign: textContent.callout.style?.textAlign
            }}>
            {textContent.callout.content}
          </text>
          <view flatten={false} user-interaction-enabled={false} style={{
                position: 'absolute',
                left: '50%',
                marginLeft: '-3px',
                bottom: '-3px',
                width: '6px',
                height: '6px',
                backgroundColor: textContent.callout.style?.backgroundColor ?? '#ffffff',
                transform: 'rotate(45deg)'
            }}/>
        </view>) : null}
      {textContent.label ? <text style={textContent.label.style}>{textContent.label.content}</text> : null}
      {textContent.title ? <text style={textContent.title.style}>{textContent.title.content}</text> : null}
      <Image src={marker.iconPath} style={iconStyle} autoSize={shouldAutoSizeIcon}/>
    </view>);
}
function createMapController(options) {
    return {
        getCenter: () => getMapInstance(options.mapRef).getCenter(),
        setCenter: (center, scaleValue, animationOptions) => {
            getMapInstance(options.mapRef).setCenter(center, scaleValue, animationOptions);
        },
        getScale: () => getMapInstance(options.mapRef).getScale(),
        getBound: () => getMapInstance(options.mapRef).getBound(),
        fitPoints: (points, padding, animationOptions) => {
            getMapInstance(options.mapRef).fitPoints(points, padding, animationOptions);
        },
        setAnchor: (position) => {
            getMapInstance(options.mapRef).setAnchor(position);
        },
        addMarkers: (markers, clear) => {
            const runtimeMarkers = markers;
            const shouldClear = clear === true;
            options.setImperativeAddedMarkers((previousAddedMarkers) => mergeMarkersById(shouldClear ? [] : previousAddedMarkers, runtimeMarkers));
            options.setImperativeRemovedMarkerIds((previousRemovedMarkerIds) => {
                const baseRemovedMarkerIds = shouldClear ? [] : previousRemovedMarkerIds;
                const restoredMarkerIds = runtimeMarkers
                    .map((marker) => getNumericMarkerId(marker))
                    .filter((markerId) => markerId !== undefined);
                if (restoredMarkerIds.length === 0) {
                    return baseRemovedMarkerIds;
                }
                const restoredIdSet = new Set(restoredMarkerIds);
                return baseRemovedMarkerIds.filter((markerId) => !restoredIdSet.has(markerId));
            });
        },
        removeMarkers: (markerIds) => {
            options.setImperativeAddedMarkers((previousAddedMarkers) => removeMarkersByIds(previousAddedMarkers, markerIds));
            options.setImperativeRemovedMarkerIds((previousRemovedMarkerIds) => {
                const markerIdSet = new Set([...previousRemovedMarkerIds, ...markerIds]);
                return Array.from(markerIdSet);
            });
        }
    };
}
function getMapInstance(mapRef) {
    if (!mapRef.current) {
        throw new Error('Map component has not been properly initialized yet');
    }
    return mapRef.current;
}
export { DoubaoAppsMap as Map };
//# sourceMappingURL=index.jsx.map