import { ComponentFactoryResolver, ElementRef, Injectable } from '@angular/core';
import { NbAdjustableConnectedPositionStrategy, NbAdjustment, NbComponentPortal, NbDynamicOverlay, NbDynamicOverlayHandler, NbOverlayRef, NbOverlayService, NbPosition, NbPositionBuilderService, NbScrollStrategy, NbTrigger } from '@nebular/theme';
import { PopoverMsgComponent } from '../directives/rbj-tooltip/popover-msg/popover-msg.component';
import { DebounceTimer } from '../utilities/timer-utils';
import { UuidUtils } from '../utilities/uuid-utils';

@Injectable({
  providedIn: 'root',
})
export class RbjTooltipService {

  private _overlays:
    {
      key: string, dynamicOverlay: NbOverlayRef,
      autoHideDebounceTimer: DebounceTimer
    }[] = [];
  constructor(
    protected overlay: NbOverlayService,
    protected positionBuilder: NbPositionBuilderService,
    protected cfr: ComponentFactoryResolver,
  ) { }

  show(elementRef: ElementRef, message: string, id: string = null, autoHideSecs = 3, position: NbPosition = NbPosition.BOTTOM_END) {
    if (null == id) {
      id = UuidUtils.generate();
    }


    let overlay = this._overlays.find(o => o.key === id);
    if (!overlay) {
      const positionStrategy = this.createPositionStrategy(elementRef, position);
      const scrollStrategy = this.createScrollStrategy();
      let dynamicOverlay = this.overlay.create({ positionStrategy, scrollStrategy });
      let autoHideDebounceTimer = new DebounceTimer(autoHideSecs * 1000, () => { this.hide(id); });
      overlay = { key: id, dynamicOverlay, autoHideDebounceTimer };
      this._overlays.push(overlay);
    }
    if (!overlay.dynamicOverlay.hasAttached()) {
      let compRef = overlay.dynamicOverlay.attach(new NbComponentPortal(PopoverMsgComponent));
      compRef.instance.context = { message: message, position };
    }
    if (autoHideSecs > 0) {
      overlay.autoHideDebounceTimer.resetTimer();
    }
  }

  hide(id: string) {
    let overlay = this._overlays.find(o => o.key === id);
    if (overlay && overlay.dynamicOverlay.hasAttached()) overlay.dynamicOverlay.detach();
  }

  destroy(id: string) {
    let overlay = this._overlays.find(o => o.key === id);
    if (overlay) {
      this._overlays = this._overlays.filter(o => o != overlay);
      overlay.dynamicOverlay.dispose();
    }
  }

  private createPositionStrategy(elementRef: ElementRef, position: NbPosition = NbPosition.BOTTOM_END): NbAdjustableConnectedPositionStrategy {
    return this.positionBuilder
      .connectedTo(elementRef)
      .position(position)
      .offset(0)
      .adjustment(NbAdjustment.VERTICAL);
  }
  private createScrollStrategy(): NbScrollStrategy {
    return this.overlay.scrollStrategies.reposition();
  }
}
