import { Directive, ElementRef, EventEmitter, Input, NgZone, Output } from '@angular/core';
import { extend, generateId } from '@jscrpt/common';
import { DndService } from '@ng-dnd/core';
import { Subscription } from 'rxjs';
import { DragActiveService } from '../../../../services';
import { DndBusService } from '../../services';
import * as i0 from "@angular/core";
import * as i1 from "@ng-dnd/core";
import * as i2 from "../../../../services";
import * as i3 from "../../services";
// import { getEmptyImage } from 'react-dnd-html5-backend';
// we don't want to depend on the backend, so here that is, copied
/** @ignore */
let emptyImage;
/**
 * Returns a 0x0 empty GIF for use as a drag preview.
 * @ignore
 */
function getEmptyImage() {
    if (!emptyImage) {
        emptyImage = new Image();
        emptyImage.src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
    }
    return emptyImage;
}
/**
 * Directive used for initializing and handling dnd core functionality for layout component palette item
 */
export class DndCorePaletteItemDirective {
    //######################### constructor #########################
    constructor(dnd, paletteItemElement, draggingSvc, bus, zone) {
        this.dnd = dnd;
        this.paletteItemElement = paletteItemElement;
        this.draggingSvc = draggingSvc;
        this.bus = bus;
        this.zone = zone;
        //######################### protected properties #########################
        /**
         * Subscriptions created during initialization
         */
        this.initSubscriptions = new Subscription();
        /**
         * Drag source used for dragging palette item
         */
        this.drag = this.dnd.dragSource('METADATA', {
            beginDrag: () => {
                this.draggingSvc.setDragging(true);
                const dragData = extend(true, {}, this.dragData);
                if (dragData.metadata) {
                    const generatedId = generateId(16);
                    const newId = `${dragData.metadata.name}-${generatedId}`;
                    dragData.metadata.id = newId;
                    dragData.metadata.displayName = dragData?.metadata.displayName && dragData?.metadata.displayName != '' ? `${dragData?.metadata.displayName}-${generatedId}` : newId;
                }
                return {
                    dragData,
                };
            },
            endDrag: monitor => {
                //dropped into drop zone
                if (monitor.didDrop()) {
                    const item = monitor.getItem();
                    const dropResult = monitor.getDropResult();
                    if (!item) {
                        return;
                    }
                    item.dragData.index = dropResult.index;
                    this.bus.setDropData({
                        data: item.dragData,
                        id: dropResult.id,
                    });
                    this.itemDrop.emit();
                }
                this.bus.setDropPlaceholderPreview(null);
                this.draggingSvc.setDragging(false);
            },
        }, this.initSubscriptions);
        //######################### public properties - outputs #########################
        /**
         * Occurs when item was succesfully dropped
         */
        this.itemDrop = new EventEmitter();
        this.connectDragToItem();
    }
    //######################### public methods - implementation of OnInit #########################
    /**
     * Initialize component
     */
    ngOnInit() {
        if (!this.dragData) {
            throw new Error('DndCoreDesignerDirective: missing drag data!');
        }
    }
    //######################### public methods - implementation of OnDestroy #########################
    /**
     * Called when component is destroyed
     */
    ngOnDestroy() {
        this.initSubscriptions.unsubscribe();
        this.itemConnection?.unsubscribe();
        this.itemConnection = null;
        this.dragPreviewConnection?.unsubscribe();
        this.dragPreviewConnection = null;
    }
    //######################### protected methods #########################
    /**
     * Connects palette item element to drag source
     */
    connectDragToItem() {
        this.zone.runOutsideAngular(() => {
            this.itemConnection?.unsubscribe();
            this.itemConnection = this.drag.connectDragSource(this.paletteItemElement.nativeElement, { dropEffect: 'copy' });
            this.dragPreviewConnection = this.drag.connectDragPreview(getEmptyImage());
        });
    }
}
DndCorePaletteItemDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: DndCorePaletteItemDirective, deps: [{ token: i1.DndService }, { token: i0.ElementRef }, { token: i2.DragActiveService }, { token: i3.DndBusService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
DndCorePaletteItemDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.4", type: DndCorePaletteItemDirective, selector: "[dndCorePaletteItem]", inputs: { dragData: ["dndCorePaletteItem", "dragData"] }, outputs: { itemDrop: "itemDrop" }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: DndCorePaletteItemDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[dndCorePaletteItem]',
                }]
        }], ctorParameters: () => [{ type: i1.DndService }, { type: i0.ElementRef }, { type: i2.DragActiveService }, { type: i3.DndBusService }, { type: i0.NgZone }], propDecorators: { dragData: [{
                type: Input,
                args: ['dndCorePaletteItem']
            }], itemDrop: [{
                type: Output
            }] } });
//# sourceMappingURL=dndCorePaletteItem.directive.js.map