import { Component, Input, Output, OnInit, EventEmitter, SimpleChanges, OnChanges, ViewChild } from '@angular/core';
import { Observable ,  of,merge,forkJoin } from 'rxjs';
import { debounceTime,distinctUntilChanged,tap,switchMap,catchError,map} from 'rxjs/operators';
import { TypeaheadService, TimespanService } from '@farmmaps/common';
import { IQueryState } from '@farmmaps/common';
import { IPeriodState } from '../../models/period.state';
import { tassign } from 'tassign';

@Component({
    selector: 'fm-map-map-search',
    templateUrl: './map-search.component.html',
    styleUrls: ['./map-search.component.scss'],
    standalone: false
})
export class MapSearchComponent {

  @ViewChild('searchText', { static: true }) searchText;
  @Input() clearEnabled: boolean
  @Input() set collapsed(collapsed: boolean) {
    this.collapsedLocal = collapsed;
    if (collapsed) this.searchText.nativeElement.blur();
  }
  @Input() set searchMinified(minified: boolean) {
    this.searchMinifiedLocal = minified;
  }
  @Input() set period(period:IPeriodState) {
    this.periodLocal =  tassign(this.periodLocal,{startDate: period.startDate,endDate:period.endDate});
    this.startEndCaption = this.timespanService.getCaption(period.startDate, period.endDate, 4)
  }
  @Output() onSearch = new EventEmitter<IQueryState>()
  @Output() onCitySearch = new EventEmitter<string>()
  @Output() onClear = new EventEmitter<any>();
  @Output() onSearchCollapse = new EventEmitter<any>();
  @Output() onSearchExpand = new EventEmitter<any>();
  @Output() onToggleMenu = new EventEmitter<any>();
  @Output() onOpenModal = new EventEmitter<string>();
  @Output() onCloseModal = new EventEmitter<any>();
  @Output() onPeriodChange = new EventEmitter<IPeriodState>();
  @Input() openedModalName: string;
  @Input() set filterOptions(filterOptions: IQueryState) {
    if (filterOptions && filterOptions.query && filterOptions.query.length > 0) {
      this.disabled = false;
    } else {
      this.disabled = true;
    }       
    this.filterOptionsLocal = tassign(this.filterOptionsLocal, { tags: filterOptions.tags, query: filterOptions.query,bbox:filterOptions.bbox });
    if (filterOptions.tags) {
      this.searchTextLocal = { name: filterOptions.tags };
    } else {
      this.searchTextLocal = { name: filterOptions.query };
    } 
  }

  public collapsedLocal = true;
  public searchMinifiedLocal = false;
  public periodLocal: IPeriodState = { startDate:new Date(new Date(Date.now()).getFullYear(), new Date(Date.now()).getMonth() - 3, 1), endDate:new Date(Date.now())};
  public filterOptionsLocal: IQueryState;
  private extent: number[];
  public searchTextLocal: any;
  public searchTextLocalOutput: string; 
  public dateFilter = true; 
  public startEndCaption: string = this.timespanService.getCaption(this.periodLocal.startDate, this.periodLocal.endDate, 4);

  searching = false;
  searchFailed = false;
  hideSearchingWhenUnsubscribed = new Observable(() => () => this.searching = false);

  public disabled = true;

  constructor(private typeaheadService: TypeaheadService, private timespanService: TimespanService) {
    this.filterOptionsLocal = { query: "", tags: "", startDate: null, endDate: null, bboxFilter: false, itemType: null, itemCode:null,level:0,parentCode:null,bbox:[] };   
  }

  search = (text$: Observable<string>) => 
    text$.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      tap(() => {this.searching = true;this.searchFailed=false;}),
      switchMap(term => term.length < 1 ? of([]) : 
      forkJoin(
        this.typeaheadService.getTagTypeaheadItems(term).pipe(
          catchError(() => {
            this.searchFailed = true;
            return of([]);
          }),map( (sa:string[]) => sa.map((s,i) => ({"name":s,"type":"tag"})))),
          this.typeaheadService.getCityTypeaheadItems(term).pipe(
            catchError(() => {
              this.searchFailed = true;
              return of([]);
            }),map( (sa:string[]) => sa.map((s,i) => ({"name":s,"type":"city"})))),
        ).pipe(map(([a1,a2]) => [...a1, ...a2] ),map(a => a.sort((a, b) => (a.name.toUpperCase() > b.name.toUpperCase()) ? 1 : -1)))
      ),
      tap(() => this.searching = false),
      );

  formatter = (x: { name: string }) => x.name;

  handleSearch(event) {
    this.filterOptionsLocal.tags = null;
    this.filterOptionsLocal.itemType = null;
    this.filterOptionsLocal.itemCode = null;
    this.filterOptionsLocal.parentCode = null;
    this.filterOptionsLocal.query = this.searchTextLocalOutput;
    if (this.dateFilter) {
      this.filterOptionsLocal.startDate = this.periodLocal.startDate;
      this.filterOptionsLocal.endDate = this.periodLocal.endDate;
    }
    this.onSearch.emit(this.filterOptionsLocal);
  }

  handleOpenSelectPeriodModal(event: MouseEvent) {
    event.preventDefault();
    this.onOpenModal.emit('selectPeriodModal');
  }

  handleCloseModal() {
    this.onCloseModal.emit({});
  }

  handleSelect(event) {
    if(event.item.type == "tag") {
      event.preventDefault();
      this.filterOptionsLocal.query = null;
      this.filterOptionsLocal.itemType = null;
      this.filterOptionsLocal.itemCode = null;
      this.filterOptionsLocal.parentCode = null;
      this.filterOptionsLocal.tags = event.item.name;
      if (this.dateFilter) {
        this.filterOptionsLocal.startDate = this.periodLocal.startDate;
        this.filterOptionsLocal.endDate = this.periodLocal.endDate;
      }
      this.onSearch.emit(this.filterOptionsLocal);
      this.searchTextLocal = { name: this.filterOptionsLocal.tags };  
    } else if (event.item.type == "city") {
      this.clearEnabled = true;
      this.onCitySearch.emit(event.item.name);
    }
  }

  handleSelectPeriod(event: { startDate: Date, endDate: Date }) {
    this.periodLocal = { startDate: event.startDate, endDate: event.endDate}
    this.onPeriodChange.emit(this.periodLocal);
    this.startEndCaption = this.timespanService.getCaption(event.startDate, event.endDate, 4);
    if(this.dateFilter) {
      this.filterOptionsLocal.startDate =event.startDate;
      this.filterOptionsLocal.endDate = event.endDate;
      this.onSearch.emit(this.filterOptionsLocal);
    }
    this.handleCloseModal();
  }

  handleChangeEnableDateFilter(enabled) {
    this.dateFilter = enabled;
    if (enabled) {
      this.filterOptionsLocal.startDate = this.periodLocal.startDate;
      this.filterOptionsLocal.endDate = this.periodLocal.endDate;
    } else {
      this.filterOptionsLocal.startDate = null;
      this.filterOptionsLocal.endDate = null;
    }
    if(this.filterOptionsLocal.query || this.filterOptionsLocal.tags)
      this.onSearch.emit(this.filterOptionsLocal);
  }

  handleChangeEnableBBOXFilter(enabled) {
    this.filterOptionsLocal.bboxFilter = enabled;
    if (this.filterOptionsLocal.query || this.filterOptionsLocal.tags)
      this.onSearch.emit(this.filterOptionsLocal);
  }


  handleToggleMenu(event) {
    this.onToggleMenu.emit({});
  }  

  handleFocus(event) {
    this.onSearchExpand.emit({});
  }

  handleChange(event: string) {
    this.searchTextLocalOutput = event;
    if (event && event.length == 1) {
      this.onSearchExpand.emit({});
    }
    if (event && event.length > 0)
      this.disabled = false;
    else
      this.disabled = true;
  }

  handleClearClick(event) {
    this.onClear.emit({});
  }

  getIcon(type):string {
    if(type == "tag")
      return "fal fa-tag";
    else if(type == "city")
      return "fal fa-map-marker-alt";
    else if(type == "search")
      return "fal fa-search";

  }
}

