import * as i0 from '@angular/core';
import { Injectable, EventEmitter, Directive, ContentChildren, Output, HostListener } from '@angular/core';

class DragAndDropService {
    getDragAfterElement(y, hostElement) {
        const draggableElements = [...hostElement.nativeElement.children].filter(child => !child.classList.contains('dragging'));
        return draggableElements.reduce((closest, child) => {
            const box = child.getBoundingClientRect();
            const offset = y - box.top - box.height / 2;
            return offset < 0 && offset > closest.offset ? { offset, element: child } : closest;
        }, { offset: Number.NEGATIVE_INFINITY }).element;
    }
    onDragToEdgeOfScrollableContainer({ dragElement, containerElement }) {
        let pageY = 0;
        let distanceFromTopOfContainer = 0;
        if (dragElement) {
            pageY = dragElement.getBoundingClientRect().top;
            distanceFromTopOfContainer = pageY - containerElement.getBoundingClientRect().top;
            if (distanceFromTopOfContainer < 30) {
                this.scrollEntities({ containerElement, action: 'scrollUp' });
            }
            else if (distanceFromTopOfContainer > containerElement.clientHeight - 30) {
                this.scrollEntities({ containerElement, action: 'scrollDown' });
            }
        }
    }
    scrollEntities({ containerElement, action }) {
        if (action === 'scrollDown') {
            containerElement.scrollTop += 10;
        }
        else if (action === 'scrollUp') {
            containerElement.scrollTop -= 10;
        }
    }
    static { this.ɵfac = function DragAndDropService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DragAndDropService)(); }; }
    static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DragAndDropService, factory: DragAndDropService.ɵfac, providedIn: 'root' }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DragAndDropService, [{
        type: Injectable,
        args: [{
                providedIn: 'root'
            }]
    }], null, null); })();

const _c0 = ["draggableItem"];
class DragAndDropDirective {
    set draggableListItems(value) {
        this.setDraggableAttributeToItems(value);
    }
    constructor(hostElement, dragAndDropStableService) {
        this.hostElement = hostElement;
        this.dragAndDropStableService = dragAndDropStableService;
        this.dragElementDrop = new EventEmitter();
        this.dragElementEnd = new EventEmitter();
        this.dragElementStart = new EventEmitter();
        this.dragChanges = { element: null, fromIndex: null, toIndex: null };
    }
    onDragStart($event) {
        const draggableElement = $event?.target?.closest('[draggable]');
        $event.dataTransfer.effectAllowed = 'move';
        if (draggableElement) {
            this.dragChanges.fromIndex = this.getElementIndex(draggableElement);
            this.dragElement = draggableElement;
            this.dragElement.classList.add('dragging');
            this.dragElementStart.emit(this.dragElement);
        }
    }
    onDragEnd($event) {
        const draggableElement = $event?.target?.closest('[draggable]');
        if (draggableElement) {
            this.dragElement.classList.remove('dragging');
            this.dragElement.classList.remove('dragging-transit');
            this.dragElementEnd.emit();
        }
    }
    onDragOver($event) {
        $event.preventDefault();
        this.dragElement.classList.add('dragging-transit');
        const afterElement = this.dragAndDropStableService.getDragAfterElement($event.clientY, this.hostElement);
        if (!afterElement) {
            this.hostElement.nativeElement.appendChild(this.dragElement);
        }
        else {
            this.hostElement.nativeElement.insertBefore(this.dragElement, afterElement);
        }
        this.dragAndDropStableService.onDragToEdgeOfScrollableContainer({
            dragElement: this.dragElement,
            containerElement: this.hostElement.nativeElement
        });
    }
    onDrop($event) {
        const draggableElement = $event?.target?.closest('[draggable]');
        if (draggableElement) {
            this.dragChanges.toIndex = this.getElementIndex(draggableElement);
            this.dragChanges.element = draggableElement;
            this.dragElement.classList.remove('dragging');
            this.dragElement.classList.remove('dragging-transit');
            if (this.dragChanges.toIndex !== this.dragChanges.fromIndex) {
                this.dragElementDrop.emit(this.dragChanges);
            }
        }
        this.dragChanges = { element: null, fromIndex: null, toIndex: null };
    }
    getElementIndex(element) {
        return Array.from(this.hostElement.nativeElement.children).findIndex(child => child === element);
    }
    setDraggableAttributeToItems(draggableItems) {
        draggableItems.forEach(itemElement => {
            const isDraggable = itemElement.nativeElement.getAttribute('draggable');
            if (!isDraggable) {
                itemElement.nativeElement.setAttribute('draggable', true);
            }
        });
    }
    static { this.ɵfac = function DragAndDropDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DragAndDropDirective)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(DragAndDropService)); }; }
    static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: DragAndDropDirective, selectors: [["", "fusionDragAndDrop", ""]], contentQueries: function DragAndDropDirective_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) {
            i0.ɵɵcontentQuery(dirIndex, _c0, 4);
        } if (rf & 2) {
            let _t;
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.draggableListItems = _t);
        } }, hostBindings: function DragAndDropDirective_HostBindings(rf, ctx) { if (rf & 1) {
            i0.ɵɵlistener("dragstart", function DragAndDropDirective_dragstart_HostBindingHandler($event) { return ctx.onDragStart($event); })("dragend", function DragAndDropDirective_dragend_HostBindingHandler($event) { return ctx.onDragEnd($event); })("dragover", function DragAndDropDirective_dragover_HostBindingHandler($event) { return ctx.onDragOver($event); })("drop", function DragAndDropDirective_drop_HostBindingHandler($event) { return ctx.onDrop($event); });
        } }, outputs: { dragElementDrop: "dragElementDrop", dragElementEnd: "dragElementEnd", dragElementStart: "dragElementStart" }, standalone: true, features: [i0.ɵɵProvidersFeature([DragAndDropService])] }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DragAndDropDirective, [{
        type: Directive,
        args: [{
                selector: '[fusionDragAndDrop]',
                standalone: true,
                providers: [DragAndDropService]
            }]
    }], () => [{ type: i0.ElementRef }, { type: DragAndDropService }], { draggableListItems: [{
            type: ContentChildren,
            args: ['draggableItem']
        }], dragElementDrop: [{
            type: Output
        }], dragElementEnd: [{
            type: Output
        }], dragElementStart: [{
            type: Output
        }], onDragStart: [{
            type: HostListener,
            args: ['dragstart', ['$event']]
        }], onDragEnd: [{
            type: HostListener,
            args: ['dragend', ['$event']]
        }], onDragOver: [{
            type: HostListener,
            args: ['dragover', ['$event']]
        }], onDrop: [{
            type: HostListener,
            args: ['drop', ['$event']]
        }] }); })();

/**
 * Generated bundle index. Do not edit.
 */

export { DragAndDropDirective };
//# sourceMappingURL=ironsource-fusion-ui-directives-drag-and-drop.mjs.map
