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 { useCallback, useEffect, useRef, useState } from 'react';
import { isDomElement } from '../../helpers';
import { buildPolygonFromVertices, dedupeTrailingDuplicateVertex, validateRing } from './polygonRingHelpers';
import { MAP_DRAWING_CROSSHAIR_CURSOR, useDrawingCursors } from './useDrawingCursors';
import { usePreviewPolylines } from './usePreviewPolylines';
import { useVertexHandles } from './useVertexHandles';
export { MAP_DRAWING_CROSSHAIR_CURSOR } from './useDrawingCursors';
export var usePolygonDrawing = function (_a) {
    var map = _a.map, isActive = _a.isActive, previewPolylineOptions = _a.previewPolylineOptions, completedPolygonOptions = _a.completedPolygonOptions, onPolygonComplete = _a.onPolygonComplete;
    var _b = useState([]), vertices = _b[0], setVertices = _b[1];
    var verticesRef = useRef([]);
    var completionLockRef = useRef(false);
    var previewPolylineOptionsRef = useRef(previewPolylineOptions);
    previewPolylineOptionsRef.current = previewPolylineOptions;
    verticesRef.current = vertices;
    var prevDisableDoubleClickZoom = useRef(undefined);
    var prevClickableIcons = useRef(undefined);
    var prevDraggableCursor = useRef(undefined);
    var syncDisposeVertexHandlesRef = useRef(function () { });
    useEffect(function () {
        if (map && isActive) {
            setVertices([]);
            completionLockRef.current = false;
        }
        else if (!isActive) {
            setVertices([]);
        }
    }, [map, isActive]);
    var reapplyCursors = useDrawingCursors(map, isActive).reapplyCursors;
    var _c = usePreviewPolylines(map, previewPolylineOptionsRef, isActive), polylineRef = _c.polylineRef, rubberBandPolylineRef = _c.rubberBandPolylineRef, handleZIndexRef = _c.handleZIndexRef;
    var reapplyCursorsRef = useRef(reapplyCursors);
    reapplyCursorsRef.current = reapplyCursors;
    var onPolygonCompleteRef = useRef(onPolygonComplete);
    onPolygonCompleteRef.current = onPolygonComplete;
    var completedPolygonOptionsRef = useRef(completedPolygonOptions);
    completedPolygonOptionsRef.current = completedPolygonOptions;
    var tryComplete = useCallback(function () {
        var _a, _b;
        if (completionLockRef.current) {
            return;
        }
        var verts = dedupeTrailingDuplicateVertex(verticesRef.current);
        if (!validateRing(verts)) {
            return;
        }
        completionLockRef.current = true;
        syncDisposeVertexHandlesRef.current();
        (_a = rubberBandPolylineRef.current) === null || _a === void 0 ? void 0 : _a.setPath([]);
        var polygon = buildPolygonFromVertices(verts, completedPolygonOptionsRef.current);
        (_b = polylineRef.current) === null || _b === void 0 ? void 0 : _b.setPath([]);
        setVertices([]);
        reapplyCursorsRef.current();
        onPolygonCompleteRef.current(polygon);
    }, [polylineRef, rubberBandPolylineRef]);
    var resetDraftPolygon = useCallback(function () {
        var _a, _b;
        if (verticesRef.current.length === 0) {
            return;
        }
        setVertices([]);
        (_a = polylineRef.current) === null || _a === void 0 ? void 0 : _a.setPath([]);
        (_b = rubberBandPolylineRef.current) === null || _b === void 0 ? void 0 : _b.setPath([]);
        reapplyCursorsRef.current();
    }, [polylineRef, rubberBandPolylineRef]);
    var tryCompleteRef = useRef(tryComplete);
    tryCompleteRef.current = tryComplete;
    var resetDraftPolygonRef = useRef(resetDraftPolygon);
    resetDraftPolygonRef.current = resetDraftPolygon;
    var previewPathVertexCountRef = useRef(0);
    useVertexHandles({
        map: map,
        isActive: isActive,
        vertices: vertices,
        handleZIndexRef: handleZIndexRef,
        onFirstHandleClick: tryComplete,
        syncDisposeRef: syncDisposeVertexHandlesRef
    });
    useEffect(function () {
        if (!isActive) {
            previewPathVertexCountRef.current = 0;
            return;
        }
        var line = polylineRef.current;
        var band = rubberBandPolylineRef.current;
        if (!line) {
            return;
        }
        var path = line.getPath();
        var prev = previewPathVertexCountRef.current;
        var vertexCount = vertices.length;
        if (vertexCount === 0) {
            if (path.getLength() > 0) {
                path.clear();
            }
            band === null || band === void 0 ? void 0 : band.setPath([]);
            previewPathVertexCountRef.current = 0;
            return;
        }
        var pathLen = path.getLength();
        if (vertexCount < prev) {
            line.setPath(vertices);
        }
        else if (vertexCount === prev + 1 && pathLen === prev) {
            var added = vertices[vertexCount - 1];
            if (added) {
                path.push(added);
            }
        }
        else if (vertexCount !== prev || pathLen !== vertexCount) {
            line.setPath(vertices);
        }
        previewPathVertexCountRef.current = vertexCount;
        var last = vertices[vertexCount - 1];
        if (last) {
            band === null || band === void 0 ? void 0 : band.setPath([last, last]);
        }
    }, [isActive, vertices, polylineRef, rubberBandPolylineRef]);
    useEffect(function () {
        if (!map || !isActive) {
            return undefined;
        }
        prevDisableDoubleClickZoom.current = map.get('disableDoubleClickZoom');
        prevClickableIcons.current = map.get('clickableIcons');
        prevDraggableCursor.current = map.get('draggableCursor');
        var mapDiv = map.getDiv();
        var rubber = rubberBandPolylineRef;
        var updateRubberBand = function (latLngFromEvent) {
            var _a, _b, _c;
            var verts = verticesRef.current;
            if (!verts.length || !latLngFromEvent) {
                (_a = rubber.current) === null || _a === void 0 ? void 0 : _a.setPath([]);
                return;
            }
            var last = verts[verts.length - 1];
            if (!last) {
                (_b = rubber.current) === null || _b === void 0 ? void 0 : _b.setPath([]);
                return;
            }
            (_c = rubber.current) === null || _c === void 0 ? void 0 : _c.setPath([last, latLngFromEvent]);
        };
        map.setOptions({
            disableDoubleClickZoom: true,
            clickableIcons: false,
            draggableCursor: MAP_DRAWING_CROSSHAIR_CURSOR
        });
        var mouseMoveListener = map.addListener('mousemove', function (e) {
            var _a;
            updateRubberBand((_a = e.latLng) !== null && _a !== void 0 ? _a : null);
        });
        var onDrawingClick = function (e) {
            var latLng = e.latLng;
            if (!latLng) {
                return;
            }
            if (completionLockRef.current) {
                return;
            }
            setVertices(function (vs) { return __spreadArray(__spreadArray([], vs, true), [latLng], false); });
        };
        var clickListener = map.addListener('click', onDrawingClick);
        var onMapDivDblClick = function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            tryCompleteRef.current();
        };
        var onMapDivMouseLeave = function () {
            resetDraftPolygonRef.current();
        };
        if (isDomElement(mapDiv)) {
            mapDiv.addEventListener('dblclick', onMapDivDblClick, true);
            mapDiv.addEventListener('mouseleave', onMapDivMouseLeave);
        }
        return function () {
            var _a;
            if (isDomElement(mapDiv)) {
                mapDiv.removeEventListener('dblclick', onMapDivDblClick, true);
                mapDiv.removeEventListener('mouseleave', onMapDivMouseLeave);
            }
            google.maps.event.removeListener(mouseMoveListener);
            google.maps.event.removeListener(clickListener);
            map.setOptions({
                disableDoubleClickZoom: (_a = prevDisableDoubleClickZoom.current) !== null && _a !== void 0 ? _a : false,
                clickableIcons: prevClickableIcons.current !== undefined ? prevClickableIcons.current : true,
                draggableCursor: prevDraggableCursor.current
            });
        };
    }, [map, isActive]);
};
