import * as i0 from '@angular/core';
import { Injectable, Component, ViewEncapsulation, ViewChild, Directive, Input, NgModule } from '@angular/core';
import * as i2 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import { Destroy } from '@deja-js/component/core';
import { BehaviorSubject, tap, filter, takeUntil, delay, combineLatestWith, fromEvent, switchMap, take, map, of, Subject, mergeWith, distinctUntilChanged } from 'rxjs';
import { Rect, Position } from '@deja-js/component/core/graphics';

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaMouseDragDropService extends Destroy {
    constructor() {
        super();
        this.dragCursor$ = new BehaviorSubject(null);
        this.dropCursor$ = new BehaviorSubject(null);
        this.dragging$ = new BehaviorSubject(false);
        this._context = {};
        this._isDragging = false;
        console.warn('@deja-js/component/mouse-dragdrop is deprecated, and will be removed in a further version. Please use @deja-js/component/v2/mouse-dragdrop.');
        this.dragging$.pipe(tap(value => this._isDragging = value), filter(value => !value), takeUntil(this.destroyed$)).subscribe(() => this._context = {});
    }
    get isDragging() {
        return this._isDragging;
    }
    set context(value) {
        this._context = value;
    }
    get context() {
        return this._context;
    }
}
DejaMouseDragDropService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
DejaMouseDragDropService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: function () { return []; } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaMouseDragDropCursorComponent extends Destroy {
    constructor(elementRef, dragDropService) {
        super();
        this.dragDropService = dragDropService;
        this.position$ = new BehaviorSubject(null);
        this.cursor$ = new BehaviorSubject(null);
        const element = elementRef.nativeElement;
        this.position$.pipe(takeUntil(this.destroyed$)).subscribe(pos => {
            element.style.left = pos ? `${pos.left}px` : '-1000px';
            element.style.top = pos ? `${pos.top}px` : '-1000px';
        });
        // Hide
        this.cursor$.pipe(filter(cursor => !cursor), tap(cursor => {
            if (this.currentCursor) {
                if (this.contentElement) {
                    this.contentElement.style.opacity = '0';
                }
                if (this.iconElement) {
                    this.iconElement.style.opacity = '0';
                }
            }
            this.currentCursor = cursor;
        }), delay(300), takeUntil(this.destroyed$)).subscribe(() => {
            this.position$.next(null);
            element.style.display = 'none';
        });
        // Show
        this.cursor$.pipe(filter(cursor => !!cursor), tap(cursor => {
            element.style.display = '';
            if (this.contentElement) {
                this.contentElement.style.opacity = '0';
            }
            if (this.iconElement) {
                this.iconElement.style.opacity = '0';
            }
            this.currentCursor = cursor;
        }), filter(cursor => !cursor.className || cursor.className !== 'hidden'), tap(cursor => {
            if (cursor.html) {
                element.className = cursor.className;
                if (this.contentElement) {
                    this.contentElement.innerHTML = cursor.html;
                    this.contentElement.style.width = `${cursor.width || 48}px`;
                    this.contentElement.style.height = `${cursor.height || 48}px`;
                }
            }
            else if (this.iconElement) {
                this.iconElement.style.opacity = '1';
            }
        }), delay(1), takeUntil(this.destroyed$)).subscribe(cursor => {
            if (!!cursor.html && this.contentElement) {
                this.contentElement.style.opacity = '1';
            }
        });
        this.dragDropService.dragCursor$.pipe(combineLatestWith(this.dragDropService.dropCursor$), takeUntil(this.destroyed$)).subscribe(([dragCursor, dropCursor]) => {
            var _a, _b, _c, _d;
            const cursor = (dragCursor || dropCursor) && {
                className: (dropCursor === null || dropCursor === void 0 ? void 0 : dropCursor.className) || (dragCursor === null || dragCursor === void 0 ? void 0 : dragCursor.className),
                html: (dropCursor === null || dropCursor === void 0 ? void 0 : dropCursor.html) || (dragCursor === null || dragCursor === void 0 ? void 0 : dragCursor.html) || (dropCursor && (dragCursor === null || dragCursor === void 0 ? void 0 : dragCursor.originalHtml)),
                width: (dropCursor === null || dropCursor === void 0 ? void 0 : dropCursor.width) || (dragCursor === null || dragCursor === void 0 ? void 0 : dragCursor.width),
                height: (dropCursor === null || dropCursor === void 0 ? void 0 : dropCursor.height) || (dragCursor === null || dragCursor === void 0 ? void 0 : dragCursor.height),
                position: dragCursor === null || dragCursor === void 0 ? void 0 : dragCursor.position,
                originalEvent: dragCursor === null || dragCursor === void 0 ? void 0 : dragCursor.originalEvent
            };
            if ((cursor === null || cursor === void 0 ? void 0 : cursor.html) !== ((_a = this.currentCursor) === null || _a === void 0 ? void 0 : _a.html) || (cursor === null || cursor === void 0 ? void 0 : cursor.className) !== ((_b = this.currentCursor) === null || _b === void 0 ? void 0 : _b.className) || (cursor === null || cursor === void 0 ? void 0 : cursor.width) !== ((_c = this.currentCursor) === null || _c === void 0 ? void 0 : _c.width) || (cursor === null || cursor === void 0 ? void 0 : cursor.height) !== ((_d = this.currentCursor) === null || _d === void 0 ? void 0 : _d.height)) {
                // Update Content
                this.cursor$.next(cursor);
            }
            else {
                // Update only Position
                this.position$.next(cursor === null || cursor === void 0 ? void 0 : cursor.position);
            }
        });
    }
    get iconElement() {
        var _a;
        return (_a = this.icon) === null || _a === void 0 ? void 0 : _a.nativeElement;
    }
    get contentElement() {
        var _a;
        return (_a = this.content) === null || _a === void 0 ? void 0 : _a.nativeElement;
    }
}
DejaMouseDragDropCursorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropCursorComponent, deps: [{ token: i0.ElementRef }, { token: DejaMouseDragDropService }], target: i0.ɵɵFactoryTarget.Component });
DejaMouseDragDropCursorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.1", type: DejaMouseDragDropCursorComponent, selector: "deja-mouse-dragdrop-cursor", viewQueries: [{ propertyName: "icon", first: true, predicate: ["block"], descendants: true, static: true }, { propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div id=\"block\" #block>\n    <mat-icon #block>block</mat-icon>\n</div>\n<div #content id=\"content\"></div>\n", styles: ["deja-mouse-dragdrop-cursor{position:fixed;width:0;height:0;overflow:visible;z-index:10000;user-select:none;display:flex;align-items:center;justify-content:space-around}deja-mouse-dragdrop-cursor #block{position:absolute;top:0;left:0;width:3rem;height:3rem;display:flex;align-items:center;justify-content:space-around;transform:translate(-50%,-50%);transition-property:opacity;transition-timing-function:linear;transition-duration:.3s;cursor:default}deja-mouse-dragdrop-cursor #content{position:absolute;top:0;left:0;transform:translate(-50%,-50%);transition-property:opacity;transition-timing-function:linear;transition-duration:.3s;cursor:default}\n"], components: [{ type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropCursorComponent, decorators: [{
            type: Component,
            args: [{ encapsulation: ViewEncapsulation.None, selector: 'deja-mouse-dragdrop-cursor', template: "<div id=\"block\" #block>\n    <mat-icon #block>block</mat-icon>\n</div>\n<div #content id=\"content\"></div>\n", styles: ["deja-mouse-dragdrop-cursor{position:fixed;width:0;height:0;overflow:visible;z-index:10000;user-select:none;display:flex;align-items:center;justify-content:space-around}deja-mouse-dragdrop-cursor #block{position:absolute;top:0;left:0;width:3rem;height:3rem;display:flex;align-items:center;justify-content:space-around;transform:translate(-50%,-50%);transition-property:opacity;transition-timing-function:linear;transition-duration:.3s;cursor:default}deja-mouse-dragdrop-cursor #content{position:absolute;top:0;left:0;transform:translate(-50%,-50%);transition-property:opacity;transition-timing-function:linear;transition-duration:.3s;cursor:default}\n"] }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: DejaMouseDragDropService }]; }, propDecorators: { icon: [{
                type: ViewChild,
                args: ['block', { static: true }]
            }], content: [{
                type: ViewChild,
                args: ['content', { static: true }]
            }] } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaMouseDraggableDirective extends Destroy {
    constructor(elementRef, dragDropService) {
        super();
        const element = elementRef.nativeElement;
        const mouseLeaveEvent$ = fromEvent(element, 'mouseleave');
        const mouseEnterEvent$ = fromEvent(element, 'mouseenter');
        const mouseUpEvent$ = fromEvent(element.ownerDocument, 'mouseup');
        const mouseDownEvent$ = fromEvent(element, 'mousedown');
        const mouseMoveEvent$ = fromEvent(element.ownerDocument, 'mousemove');
        mouseEnterEvent$.pipe(filter(() => !dragDropService.isDragging), switchMap(() => mouseDownEvent$.pipe(filter(event => event.buttons === 1), 
        // eslint-disable-next-line rxjs/no-unsafe-takeuntil
        takeUntil(mouseLeaveEvent$), switchMap(event => {
            let target;
            const match = (el) => el.tagName === this.context.target.toUpperCase() || el.id === this.context.target.substr(1) || el.hasAttribute(this.context.target.substring(1, this.context.target.length - 1));
            if (this.context) {
                if (this.context.target) {
                    target = event.target;
                    // eslint-disable-next-line no-loops/no-loops
                    while (target && !match(target)) {
                        target = target.parentElement;
                    }
                }
                else {
                    target = element;
                }
                if (target && this.context.dragStart) {
                    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
                    const dragContext = this.context.dragStart(target);
                    if (dragContext) {
                        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
                        if (dragContext.subscribe) {
                            const context$ = dragContext;
                            // Observable
                            return context$.pipe(take(1), map((ddctx) => {
                                dragDropService.context = ddctx;
                                return ddctx && target; // Map to target if ddctx is defined
                            }));
                        }
                        else {
                            // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
                            dragDropService.context = dragContext;
                            return of(target);
                        }
                    }
                }
            }
            return of(null);
        }), filter(target => !!target), // Start Drag if target is defined
        switchMap(target => {
            dragDropService.dragging$.next(true);
            const moveUp$ = new Subject();
            const enterWhileNotDragDropEvent$ = mouseEnterEvent$.pipe(filter(event => event.buttons !== 1 && dragDropService.isDragging));
            const kill$ = mouseUpEvent$.pipe(mergeWith(enterWhileNotDragDropEvent$, moveUp$), take(1), tap(() => {
                dragDropService.dragCursor$.next(null);
                dragDropService.dragging$.next(false);
            }));
            return mouseMoveEvent$.pipe(
            // eslint-disable-next-line rxjs/no-unsafe-takeuntil
            takeUntil(kill$), tap(ev => {
                if (target && ev.buttons === 1) {
                    const bounds = new Rect(element.getBoundingClientRect());
                    const position = new Position(ev.pageX, ev.pageY);
                    const html = bounds.containsPoint(position) ? target.innerHTML : undefined;
                    // Post cursor infos to service
                    dragDropService.dragCursor$.next({
                        position: position,
                        html: html,
                        originalHtml: target.innerHTML,
                        width: target.offsetWidth,
                        height: target.offsetHeight,
                        className: this.context.className,
                        originalEvent: ev
                    });
                }
                else {
                    moveUp$.next();
                }
                // ev.preventDefault();
                return false;
            }));
        }))), takeUntil(this.destroyed$)).subscribe();
    }
    set context(value) {
        this._context = value;
    }
    get context() {
        return this._context;
    }
}
DejaMouseDraggableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDraggableDirective, deps: [{ token: i0.ElementRef }, { token: DejaMouseDragDropService }], target: i0.ɵɵFactoryTarget.Directive });
DejaMouseDraggableDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.1", type: DejaMouseDraggableDirective, selector: "[deja-mouse-draggable]", inputs: { context: ["deja-mouse-draggable", "context"] }, usesInheritance: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDraggableDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[deja-mouse-draggable]'
                }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: DejaMouseDragDropService }]; }, propDecorators: { context: [{
                type: Input,
                args: ['deja-mouse-draggable']
            }] } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaMouseDroppableDirective extends Destroy {
    constructor(elementRef, dragDropService) {
        super();
        const element = elementRef.nativeElement;
        const dragging$ = dragDropService.dragging$.pipe(distinctUntilChanged());
        const drop$ = dragDropService.dragCursor$.pipe(filter(value => !!value), switchMap(dragCursor => dragging$.pipe(filter(value => !value), take(1), tap(() => {
            var _a;
            // console.log(`Drop ${!!this._dragContext}`)
            if (this._dragContext && ((_a = this.context) === null || _a === void 0 ? void 0 : _a.drop)) {
                this.context.drop(this._dragContext, dragCursor);
            }
            this._dragContext = undefined;
            dragDropService.dropCursor$.next(null);
        }))));
        dragging$.pipe(filter(value => value), switchMap(() => 
        // console.log(`Drag ${!!this._dragContext}`)
        dragDropService.dragCursor$.pipe(
        // eslint-disable-next-line rxjs/no-unsafe-takeuntil
        takeUntil(drop$), switchMap(dragCursor => {
            var _a;
            const bounds = new Rect(element.getBoundingClientRect());
            if (this.context && dragCursor) {
                const { pageX, pageY } = dragCursor.originalEvent;
                if (bounds.containsPoint(new Position(pageX, pageY))) {
                    if (!this._dragContext) {
                        this._dragContext = dragDropService.context;
                        if (this.context.dragEnter) {
                            const dropContext$ = this.context.dragEnter(this._dragContext, dragCursor);
                            if (dropContext$) {
                                const dropContextObs$ = dropContext$;
                                if (dropContextObs$.subscribe) {
                                    // Observable
                                    return dropContextObs$;
                                }
                                else {
                                    return of(dropContext$);
                                }
                            }
                        }
                    }
                    else if (this.context.dragOver) {
                        const overContext = this.context.dragOver(this._dragContext, dragCursor);
                        if (overContext) {
                            return of(overContext);
                        }
                    }
                }
                else if (this._dragContext) {
                    if ((_a = this.context) === null || _a === void 0 ? void 0 : _a.dragLeave) {
                        this.context.dragLeave(this._dragContext);
                    }
                    this._dragContext = undefined;
                    dragDropService.dropCursor$.next(null);
                }
            }
            return of(null);
        }))), filter(dropCursor => !!dropCursor), takeUntil(this.destroyed$)).subscribe(dropCursor => dragDropService.dropCursor$.next(dropCursor));
    }
    set context(value) {
        this._context = value;
    }
    get context() {
        return this._context;
    }
}
DejaMouseDroppableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDroppableDirective, deps: [{ token: i0.ElementRef }, { token: DejaMouseDragDropService }], target: i0.ɵɵFactoryTarget.Directive });
DejaMouseDroppableDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.1", type: DejaMouseDroppableDirective, selector: "[deja-mouse-droppable]", inputs: { context: ["deja-mouse-droppable", "context"] }, usesInheritance: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDroppableDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[deja-mouse-droppable]'
                }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: DejaMouseDragDropService }]; }, propDecorators: { context: [{
                type: Input,
                args: ['deja-mouse-droppable']
            }] } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaMouseDragDropModule {
}
DejaMouseDragDropModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
DejaMouseDragDropModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropModule, declarations: [DejaMouseDragDropCursorComponent,
        DejaMouseDraggableDirective,
        DejaMouseDroppableDirective], imports: [MatIconModule], exports: [DejaMouseDragDropCursorComponent,
        DejaMouseDraggableDirective,
        DejaMouseDroppableDirective] });
DejaMouseDragDropModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropModule, providers: [], imports: [[
            MatIconModule
        ]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.1", ngImport: i0, type: DejaMouseDragDropModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [
                        DejaMouseDragDropCursorComponent,
                        DejaMouseDraggableDirective,
                        DejaMouseDroppableDirective
                    ],
                    imports: [
                        MatIconModule
                    ],
                    exports: [
                        DejaMouseDragDropCursorComponent,
                        DejaMouseDraggableDirective,
                        DejaMouseDroppableDirective
                    ],
                    providers: []
                }]
        }] });

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

export { DejaMouseDragDropCursorComponent, DejaMouseDragDropModule, DejaMouseDragDropService, DejaMouseDraggableDirective, DejaMouseDroppableDirective };
//# sourceMappingURL=deja-js-component-mouse-dragdrop.mjs.map
