import {
  AfterViewInit,
  ChangeDetectorRef,
  Component,
  ElementRef,
  EventEmitter,
  HostListener,
  Input,
  OnInit,
  Output,
  ViewChild
} from '@angular/core';
import {AbstractControl} from '@angular/forms';
import {InputComponent} from "../input/input.component";
import {ClickEvent} from "../../utils/click/click-outside-or-esc.directive";

@Component({
  selector: '[search-input]',
  template: `
    <div *ngIf="initialized" class="uk-flex uk-flex-right uk-width-1-1">
      <div #searchInput click-outside-or-esc (clickOutside)="click($event)" class="search-input" [class.focused]="input.focused"
           [class.collapsed]="hidden" [ngClass]="searchInputClass">
        <div class="uk-flex uk-flex-middle">
          <div class="uk-width-expand">
            <div #input  [class.uk-hidden]="hidden" input [formInput]="searchControl" [inputClass]="'search'+(iconPosition === 'left'?' icon-left':'')" [disabledIcon]="null"
                 [placeholder]="{label: placeholder, static: true}" [value]="value" (valueChange)="valueChange.emit($event)"
                 [disabled]="disabled" [showOptionsOnEmpty]="false" [type]="(options.length > 0?'autocomplete_soft':'text')" [options]="options"></div>
          </div>
          <div [class.uk-hidden]="(!searchControl?.value && !value) || disabled" class="uk-width-auto">
            <button class="uk-close uk-icon" (click)="reset()">
              <icon name="close" [flex]="true"></icon>
            </button>
          </div>
          <div class="uk-width-auto" [class.uk-flex-first]="iconPosition === 'left'">
            <div class="search-icon" [class.disabled]="disabled" (click)="search($event)">
              <icon name="search" [flex]="true" [ratio]="ratio"></icon>
            </div>
          </div>
          <div class="uk-width-auto filters-toggle">
            <ng-content select="[filters-toggle]"></ng-content>
          </div>
        </div>
      </div>
    </div>
  `
})
export class SearchInputComponent implements OnInit, AfterViewInit {
  @Input() disabled: boolean = false;
  @Input() searchInputClass: string = 'inner';
  @Input() iconPosition: 'left' | 'right' = 'right';
  @Input() searchControl: AbstractControl;
  @Input() value: string;
  @Output() valueChange = new EventEmitter<string>();
  @Input() options: string[] = [];
  @Input() placeholder: string;
  @Input() expandable: boolean = false;
  @Output() searchEmitter: EventEmitter<void> = new EventEmitter<void>();
  @ViewChild('searchInput') searchInput: ElementRef;
  @ViewChild('input') input: InputComponent;
  public expanded: boolean = true;
  public initialized: boolean = false;
  public ratio: number = 1;
  
  constructor(private cdr: ChangeDetectorRef) {
  }
  
  @HostListener('window:keydown.enter', ['$event'])
  enter(event: KeyboardEvent) {
    if(this.input.focused && !this.input.opened) {
      event.preventDefault();
      this.search(event);
    } else {
      this.input.enter(event);
      event.stopPropagation();
      this.search(event);
    }
  }
  
  click(event: ClickEvent) {
    if(this.expandable && !this.disabled) {
      this.expand(!event.clicked);
    }
  }
  
  ngOnInit() {
    this.expanded = !this.expandable;
    this.initialized = true;
  }
  
  ngAfterViewInit() {
    if(typeof document !== 'undefined') {
      this.ratio = Number.parseFloat(getComputedStyle(this.searchInput.nativeElement).getPropertyValue('--search-input-icon-ratio'));
      this.cdr.detectChanges();
    }
  }
  
  expand(value: boolean) {
    this.expanded = value;
    this.cdr.detectChanges();
    if(this.expanded) {
      this.input.focus(true);
    }
  }
  
  public search(event) {
    if(!this.disabled) {
      this.searchEmitter.emit();
      if(this.expandable) {
        this.expand(!this.expanded);
      }
      event.stopPropagation();
    }
  }
  
  public reset() {
    if(this.searchControl){
      this.searchControl.setValue('');
    } else {
      this.valueChange.emit('');
    }
    setTimeout(() => {
      this.input.focus(true);
    }, 100)
  }
  
  get hidden(): boolean {
    return !this.expanded && (!this.searchControl?.value && !this.value);
  }
}
