"use strict";
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.startDragAndDrop = void 0;
const NOOP_1 = require("../NOOP");
const event_1 = require("./event");
function startDragAndDrop(system, element, pointerId, data, onDrag, onDrop = NOOP_1.NOOP) {
    // console.log('dragAndDrop')
    const { root, api: { input: { pointer: { getPointerPosition }, }, document: { elementFromPoint }, }, } = system;
    root.appendChild(element);
    system.cache.dragAndDrop[pointerId] = data;
    const { screenX, screenY } = getPointerPosition(pointerId);
    let currentElement = elementFromPoint(screenX, screenY);
    if (currentElement) {
        currentElement.dispatchEvent(new CustomEvent('_dragenter', {
            detail: {
                pointerId,
                clientX: screenX,
                clientY: screenY,
                screenX,
                screenY,
            },
            bubbles: true,
        }));
    }
    const findDropTarget = (clientX, clientY) => {
        let dropTarget = elementFromPoint(clientX, clientY);
        return dropTarget;
        while (dropTarget && !dropTarget.hasAttribute('dropTarget')) {
            dropTarget = dropTarget.parentElement;
        }
        return dropTarget && dropTarget.getAttribute('dropTarget') === 'true'
            ? dropTarget
            : null;
    };
    const drag = (screenX, screenY) => {
        onDrag(screenX, screenY);
        const dropTarget = findDropTarget(screenX, screenY);
        if (dropTarget) {
            if (currentElement !== dropTarget) {
                if (currentElement) {
                    // console.log('_dragleave', currentElement)
                    currentElement.dispatchEvent(new CustomEvent('_dragleave', {
                        detail: {
                            pointerId,
                            clientX: screenX,
                            clientY: screenY,
                            screenX,
                            screenY,
                        },
                        bubbles: true,
                    }));
                }
                currentElement = dropTarget;
                currentElement.dispatchEvent(new CustomEvent('_dragenter', {
                    detail: {
                        pointerId,
                        clientX: screenX,
                        clientY: screenY,
                        screenX,
                        screenY,
                    },
                    bubbles: true,
                }));
            }
            else {
                if (currentElement) {
                    currentElement.dispatchEvent(new CustomEvent('_dragover', {
                        detail: {
                            pointerId,
                            clientX: screenX,
                            clientY: screenY,
                            screenX,
                            screenY,
                        },
                        bubbles: true,
                    }));
                }
            }
        }
        else if (currentElement) {
            currentElement.dispatchEvent(new CustomEvent('_dragleave', {
                detail: {
                    pointerId,
                    clientX: screenX,
                    clientY: screenY,
                    screenX,
                    screenY,
                },
                bubbles: true,
            }));
        }
        currentElement = dropTarget;
    };
    const pointerMoveListener = (event) => {
        const { pointerId: _pointerId, clientX, clientY } = event;
        // console.log('pointerMoveListener')
        if (_pointerId === pointerId) {
            drag(clientX, clientY);
        }
    };
    let canceled = false;
    const _cancel = () => {
        // console.log('dragAndDrop', 'pointerup')
        if (canceled) {
            return;
        }
        canceled = true;
        root.removeChild(element);
        unlistenPointerMove();
        unlistenPointerUp();
    };
    const pointerUpListener = (event) => {
        const { pointerId: _pointerId, clientX, clientY } = event, rest = __rest(event, ["pointerId", "clientX", "clientY"]);
        if (_pointerId === pointerId) {
            _cancel();
            const dropTarget = findDropTarget(clientX, clientY);
            if (dropTarget) {
                let dragBackData;
                const dragBackListener = (event) => {
                    dragBackData = event.detail;
                };
                dropTarget.addEventListener('_dragback', dragBackListener, {
                    capture: true,
                });
                dropTarget.dispatchEvent(new CustomEvent('_dragdrop', {
                    detail: Object.assign(Object.assign({}, Object.assign({ pointerId: _pointerId, clientX, clientY }, rest)), { data }),
                    bubbles: true,
                }));
                dropTarget.removeEventListener('_dragback', dragBackListener, {
                    capture: true,
                });
                onDrop(true, dragBackData);
            }
            else {
                onDrop(false, undefined);
            }
            delete system.cache.dragAndDrop[pointerId];
        }
    };
    const unlistenPointerMove = (0, event_1._addEventListener)('pointermove', root, pointerMoveListener, true);
    const unlistenPointerUp = (0, event_1._addEventListener)('pointerup', root, pointerUpListener, true);
    drag(screenX, screenY);
    return () => {
        if (currentElement) {
            currentElement.dispatchEvent(new CustomEvent('_dragcancel', {
                detail: Object.assign({ pointerId }, { data }),
                bubbles: true,
            }));
        }
        _cancel();
    };
}
exports.startDragAndDrop = startDragAndDrop;
//# sourceMappingURL=dnd.js.map