import { DOCUMENT } from '@angular/common';
import {
  Component,
  ChangeDetectionStrategy,
  Input,
  OnChanges,
  SimpleChanges,
  Output,
  EventEmitter,
  ElementRef,
  Renderer2,
  Inject,
  AfterViewInit,
  HostListener,
} from '@angular/core';
import { IUiFilter, UiFilter } from './tree/ui-filter';

@Component({
  selector: 'ui-filter',
  templateUrl: 'ui-filter.component.html',
  styleUrls: ['ui-filter.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UiFilterComponent implements OnChanges, AfterViewInit {
  @Input()
  loading: boolean;

  @Input()
  hint: string;

  @Output()
  search = new EventEmitter<string>();

  @Input()
  filter: IUiFilter;

  @Input()
  resizeInputOptionsToElement: string | HTMLElement;

  @Input()
  scanner = false;

  get uiFilter() {
    return this.filter instanceof UiFilter && this.filter;
  }

  constructor(private elementRef: ElementRef, private renderer: Renderer2, @Inject(DOCUMENT) private document: Document) {}

  ngOnChanges({ filter }: SimpleChanges): void {
    if (filter) {
      if (!(this.filter instanceof UiFilter)) {
        this.filter = UiFilter.create(this.filter);
      }
    }
  }

  ngAfterViewInit() {
    setTimeout(() => this.resizeInputOptions(), 500);
  }

  getHtmlElement(element: string | HTMLElement): HTMLElement {
    return typeof element === 'string' ? this.document.querySelector(element) : element;
  }

  @HostListener('window:resize', ['$event'])
  @HostListener('window:click', ['$event'])
  resizeInputOptions() {
    if (this.resizeInputOptionsToElement) {
      const inputOptions = this.elementRef.nativeElement.querySelector('.input-options');
      const targetElement = this.getHtmlElement(this.resizeInputOptionsToElement);

      // set the max-height of the input-options to the height of the actions, depending on the distance between the two
      if (inputOptions && targetElement) {
        const distanceBetweenElements = this.getDistanceBetweenElements(inputOptions, targetElement) - 15;
        this.renderer.setStyle(inputOptions, 'max-height', `${distanceBetweenElements}px`);
      }
    }
  }

  getDistanceBetweenElements(element1: HTMLElement, element2: HTMLElement) {
    const rect1 = element1.getBoundingClientRect();
    const rect2 = element2.getBoundingClientRect();

    return Math.abs(rect1.top - rect2.top);
  }

  emitSearch(query: string) {
    setTimeout(() => {
      this.search.emit(query);
    }, 1);
  }
}
