import { Directive, ElementRef, HostListener, Input, OnDestroy, ViewContainerRef } from '@angular/core';
import { MenuTemplateComponent } from './menu-template.component';
import { HorizontalConnectionPos, Overlay, OverlayRef, VerticalConnectionPos } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal';
import { asapScheduler } from 'rxjs';

@Directive({
  selector: '[menuTrigger]',
  standalone: false,
})
export class MenuTriggerDirective implements OnDestroy {
  @Input('menuTrigger')
  menuTemplate: MenuTemplateComponent;

  private _overlayRef: OverlayRef;

  @Input()
  originX: HorizontalConnectionPos = 'start';

  @Input()
  originY: VerticalConnectionPos = 'bottom';

  @Input()
  overlayX: HorizontalConnectionPos = 'start';

  @Input()
  overlayY: VerticalConnectionPos = 'top';

  constructor(
    private _elementRef: ElementRef,
    private _overlay: Overlay,
    private _viewContainerRef: ViewContainerRef,
  ) {}

  ngOnDestroy() {
    this._overlayRef?.dispose();
  }

  createOverlayRef() {
    if (!this._overlayRef) {
      this._overlayRef = this._overlay.create({
        positionStrategy: this._overlay
          .position()
          .flexibleConnectedTo(this._elementRef)
          .withPositions([
            { originX: this.originX, originY: this.originY, overlayX: this.overlayX, overlayY: this.overlayY },
          ]),
        scrollStrategy: this._overlay.scrollStrategies.reposition(),
        hasBackdrop: false,
      });
    }
    return this._overlayRef;
  }

  @HostListener('click')
  click() {
    if (this._overlayRef && this._overlayRef.hasAttached()) {
      this.close();
    } else {
      this.open();
    }
  }

  open() {
    const overlayRef = this.createOverlayRef();

    const portal = new TemplatePortal(this.menuTemplate.templateRef, this._viewContainerRef);

    this.menuTemplate.menu.registerOnClick((item) => {
      asapScheduler.schedule(() => {
        this.close();
      });
    });

    portal.attach(overlayRef);
  }

  close() {
    this._overlayRef?.detach();
  }

  @HostListener('focusout', ['$event'])
  onKeyUp(event: Event) {
    this.close();
  }
}
