import { Component, Input, forwardRef,ElementRef,ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR,NgModel } from '@angular/forms';
import { Observable,of } from 'rxjs';
import { tap,catchError,debounceTime,distinctUntilChanged,switchMap } from 'rxjs/operators'
import { TypeaheadService } from '../../services/typeahead.service';

@Component({
  selector: 'fm-tag-input',
  templateUrl: 'tag-input.component.html',
  styleUrls: ['tag-input.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => TagInputComponent),
      multi: true
    }
  ]
})

export class TagInputComponent implements ControlValueAccessor  {
  @Input() tags: string[]
  @ViewChild('taginput', { static: true }) tagInputElement: ElementRef;
  public tag: string;
  searching = false;
  searchFailed = false;

  constructor(private typeaheadService: TypeaheadService) {
  }

  tagExists(tag) {
    if (tag.length == 0) return true;
    for (let t of this.tags) {
      if (t.toLowerCase() == tag.toLowerCase()) return true;
    }
    return false;
  }

  handleDeleteTag(tag) {
    let tags = [];
    for (let t of this.tags) {
      if (t != tag) tags.push(t);
    }
    this.tags = tags;
    this.propagateChange(tags);
  }

  handleAddTag(event) {
    if (!this.tagExists(this.tag)) {
      this.tags.push(this.tag);
      this.propagateChange(this.tags);
    }
    this.tag = "";
    this.tagInputElement.nativeElement.focus();
  }

  handleCheckAddTag(event: KeyboardEvent) {
    if (event.keyCode == 188) {
      let tag = this.tag.substr(0, this.tag.length - 1); // strip ,
      if (!this.tagExists(tag)) {
        this.tags.push(tag);
        this.propagateChange(this.tags);
      }
      this.tag = "";
    }
  }

  handleSelect(event) {
    if (!this.tagExists(event.item)) {
      this.tags.push(event.item);
      this.propagateChange(this.tags);
    }
    event.preventDefault();
    this.tag = "";
  }

  propagateChange = (_: any) => { };

  registerOnChange(fn) {
    this.propagateChange = fn;
  }

  findTag = (text$: Observable<string>) =>
  text$.pipe(
        debounceTime(200),
        distinctUntilChanged(), 
        tap(() => this.searching = true),
        switchMap(term => term.length < 1 ? of([]) :
           this.typeaheadService.getTagTypeaheadItems(term).pipe(
            tap(() => this.searchFailed = false),
            catchError(() => {
                this.searchFailed = true;
                return of([]);
            }))
         ),
         tap(() => this.searching = false)
  );

  writeValue(value: any) {
    this.tags = value;
    this.tag = "";
  }

  registerOnTouched() { }
}
