import {
  NgModule, Component, ElementRef, OnDestroy,
  Input, Renderer2, ViewChild, Inject, forwardRef,
  Output, EventEmitter,
} from '@angular/core';
import { trigger, state, style, transition, animate, AnimationEvent } from '@angular/animations';
import { DomHandler } from 'primeng/primeng';


@Component({
  selector: 'of-p-popupPanel',
  templateUrl: './popup-panel.component.html',
  styleUrls: ['./popup-panel.component.scss'],
  animations: [
    trigger('overlayAnimation', [
      state('void', style({
        transform: 'translateY(5%)',
        opacity: 0
      })),
      state('visible', style({
        transform: 'translateY(0)',
        opacity: 1
      })),
      transition('void => visible', animate('225ms ease-out')),
      transition('visible => void', animate('195ms ease-in'))
    ])
  ],
  providers: [DomHandler]
})
export class PopupPanelComponent implements OnDestroy {
  @Input() blockTarget: any;

  @Input() style: any;

  @Input() styleClass: string;

  @Input() appendTo: any;

  @Input() autoZIndex = true;

  @Input() baseZIndex = 0;

  @Output() cancel = new EventEmitter();

  @ViewChild('container') containerViewChild: ElementRef;

  readonly popup = true;

  container: HTMLDivElement;

  documentClickListener: any;

  documentResizeListener: any;

  preventDocumentDefault: boolean;

  target: any;

  visible: boolean;

  blockUIVisible = false;

  constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) { }

  toggle(event) {
    if (this.visible) {
      this.hide();
    } else {
      this.show(event);
    }

    this.preventDocumentDefault = true;
  }

  show(event) {
    this.target = event.currentTarget;
    this.visible = true;
    this.preventDocumentDefault = true;
  }

  onOverlayAnimationStart(event: AnimationEvent) {
    switch (event.toState) {
      case 'visible':
        if (this.popup) {
          this.container = event.element;
          this.moveOnTop();
          this.appendOverlay();
          this.domHandler.absolutePosition(this.container, this.target);
          this.bindDocumentClickListener();
          this.bindDocumentResizeListener();
        }
        break;

      case 'void':
        this.onOverlayHide();
        break;
    }
  }

  onOverlayAnimationDone(event: AnimationEvent) {
    console.log('onOverlayAnimationDone');
  }

  appendOverlay() {
    if (this.appendTo) {
      if (this.appendTo === 'body') {
        document.body.appendChild(this.container);
      } else {
        this.domHandler.appendChild(this.container, this.appendTo);
      }
    }
  }

  restoreOverlayAppend() {
    if (this.container && this.appendTo) {
      this.el.nativeElement.appendChild(this.container);
    }
  }

  moveOnTop() {
    if (this.autoZIndex) {
      this.container.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex));
    }
  }

  hide() {
    this.visible = false;
  }

  onWindowResize() {
    this.hide();
  }

  bindDocumentClickListener() {
    if (!this.documentClickListener) {
      this.documentClickListener = this.renderer.listen('document', 'click', () => {
        if (!this.preventDocumentDefault) {
          this.cancel.emit();
          this.hide();
        }

        this.preventDocumentDefault = false;
      });
    }
  }

  unbindDocumentClickListener() {
    if (this.documentClickListener) {
      this.documentClickListener();
      this.documentClickListener = null;
    }
  }

  bindDocumentResizeListener() {
    this.documentResizeListener = this.onWindowResize.bind(this);
    window.addEventListener('resize', this.documentResizeListener);
  }

  unbindDocumentResizeListener() {
    if (this.documentResizeListener) {
      window.removeEventListener('resize', this.documentResizeListener);
      this.documentResizeListener = null;
    }
  }

  onOverlayHide() {
    this.unbindDocumentClickListener();
    this.unbindDocumentResizeListener();
    this.preventDocumentDefault = false;
    this.target = null;
  }

  ngOnDestroy() {
    if (this.popup) {
      this.restoreOverlayAppend();
      this.onOverlayHide();
    }
  }

}
