import { Directive, Input, ElementRef, HostListener, Renderer2 } from '@angular/core';

@Directive({
  selector: '[tooltip]',
})
export class TooltipDirective {
  @Input('tooltip') tooltipTitle: string;
  @Input() placement: string;
  @Input() delay: string;
  tooltip: HTMLElement;
  offset = 10;

  constructor(private el: ElementRef, private renderer: Renderer2) {}

  @HostListener('mouseenter') onMouseEnter() {
    if (!this.tooltip) {
      this.show();
    }
  }

  @HostListener('mouseleave') onMouseLeave() {
    if (this.tooltip) {
      this.hide();
    }
  }

  show() {
    this.create();
    this.setPosition();
    this.renderer.addClass(this.tooltip, 'ng-tooltip-show');
  }

  hide() {
    this.renderer.removeClass(this.tooltip, 'ng-tooltip-show');
    window.setTimeout(() => {
      this.renderer.removeChild(document.body, this.tooltip);
      this.tooltip = null;
    }, +this.delay);
  }

  create() {
    this.tooltip = this.renderer.createElement('span');

    this.renderer.appendChild(this.tooltip, this.renderer.createText(this.tooltipTitle));

    this.renderer.appendChild(document.body, this.tooltip);

    this.renderer.addClass(this.tooltip, 'ng-tooltip');
    this.renderer.addClass(this.tooltip, `ng-tooltip-${this.placement}`);

    this.renderer.setStyle(this.tooltip, '-webkit-transition', `opacity ${this.delay}ms`);
    this.renderer.setStyle(this.tooltip, '-moz-transition', `opacity ${this.delay}ms`);
    this.renderer.setStyle(this.tooltip, '-o-transition', `opacity ${this.delay}ms`);
    this.renderer.setStyle(this.tooltip, 'transition', `opacity ${this.delay}ms`);
  }

  setPosition() {
    const hostPos = this.el.nativeElement.getBoundingClientRect();

    const tooltipPos = this.tooltip.getBoundingClientRect();

    const scrollPos = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;

    const fullWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    const fullHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

    let top, left;

    if (this.placement === 'top') {
      top = hostPos.top - tooltipPos.height - this.offset;
      left = hostPos.left + (hostPos.width - tooltipPos.width) / 2;
    }

    if (this.placement === 'bottom') {
      top = hostPos.bottom + this.offset;
      left = hostPos.left + (hostPos.width - tooltipPos.width) / 2;
    }

    if (this.placement === 'left') {
      top = hostPos.top + (hostPos.height - tooltipPos.height) / 2;
      left = hostPos.left - tooltipPos.width - this.offset;
    }

    if (this.placement === 'right') {
      top = hostPos.top + (hostPos.height - tooltipPos.height) / 2;
      left = hostPos.right + this.offset;
    }

    if (left < 0) {
      this.renderer.setStyle(this.tooltip, 'left', `0px`);
      this.renderer.setStyle(this.tooltip, '--pin-left', `${hostPos.left + hostPos.width / 2}px`, 2);
    } else if (fullWidth < left + tooltipPos.width) {
      this.renderer.setStyle(this.tooltip, 'right', `0px`);
      this.renderer.setStyle(this.tooltip, '--pin-left', `${tooltipPos.width - (fullWidth - hostPos.left) + hostPos.width / 2}px`, 2);
    } else {
      this.renderer.setStyle(this.tooltip, 'left', `${left}px`);
    }
    if (top < 0) {
      this.renderer.setStyle(this.tooltip, '--pin-top', `${hostPos.top + hostPos.height / 2}px`, 2);
    } else if (fullHeight < top + tooltipPos.height) {
      this.renderer.setStyle(this.tooltip, '--pin-top', `${tooltipPos.height - (fullHeight - hostPos.top) + hostPos.height / 2}px`, 2);
    }
    this.renderer.setStyle(this.tooltip, 'top', `${top + scrollPos}px`);
  }
}
