// Angular Core
import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';

// RxJs
import { BehaviorSubject, Subscription, throwError } from 'rxjs';
import { catchError, debounceTime, distinctUntilChanged } from "rxjs/operators";

// Pipes
import { StripNDCPipe } from 'src/app/filters/strip-ndc.pipe';

// Services
import { SearchService } from 'src/app/services/search/search.service';
import { SupplierCatalogService } from 'src/app/services/supplierCatalog/supplier-catalog.service';
import { LocalStorageService } from 'src/app/services/localstorage/local-storage.service';

@Component({
  standalone: false,
  selector: 'app-typeahead',
  templateUrl: './typeahead.component.html',
  styleUrls: ['./typeahead.component.scss']
})
export class TypeaheadComponent implements OnInit, OnDestroy {

  @Input() searchtype: string = '';

  @ViewChild('searchInput') searchInput!: ElementRef;

  @Output() showClearSign = new EventEmitter<string>();
  @Output() showClearSignSSD = new EventEmitter<string>();
  @Output() showClearSignSC = new EventEmitter<string>();
  @Output() hideClearSign = new EventEmitter<string>();
  @Output() hideClearSignSSD = new EventEmitter<string>();
  @Output() hideClearSignSC = new EventEmitter<string>();
  @Output() searchBySearchForm = new EventEmitter<object>();

  /**
   * Default config object
   * @type Object
   */
  config: any = {
    searchInput: '',
    searchCatCode: 'All',
    selectedInput: {}
  };

  activatedRouteListner!: Subscription;
  tab!: string | null;
  isResetRunning = false;
  resetTypeAheadDataSubscription!: Subscription;
  searchTermListener!: Subscription;
  clearSearchInputSubscribe!: Subscription;
  searchInputSubscription!: Subscription;

  constructor(
    private searchService: SearchService,
    private supplierCatalogService: SupplierCatalogService,
    private localStorageService: LocalStorageService,
    private activatedRoute: ActivatedRoute,
    private router: Router,
    private stripNDCPipe: StripNDCPipe
  ) { }

  ngOnInit(): void {
    this.activatedRouteListner = this.activatedRoute.queryParams.subscribe((params: Params) => {
        this.tab = params['tab'];
        this.typeahead(this.config.searchInput);
    });
    this.tab = this.activatedRoute.snapshot.queryParams['tab'];
    this.searchInputSubscription = this.searchTerm$.subscribe((value: string) => {
        value = this.stripNDCPipe.transform(value);
        this.typeahead(value);
    });
    /**
     * Reset Typeahead Data listener
     */
    this.resetTypeAheadDataSubscription = this.searchService.resetTypeAheadData
        .subscribe({
        next: (event: string) => {
            if(!this.isResetRunning){
                this.isResetRunning = true;
                this.typeaheadData = [{
                        NDC:'Loading...'
                }];
                this.isResetRunning = false;
            }
        }
    });
    /**
     * Event listener for searchTerm
     */
    this.searchTermListener = this.searchService.setSearchInput.subscribe((data: string) => {
        this.config.searchInput = data;
    });

    this.clearSearchInputSubscribe = this.searchService.clearSearchInput.subscribe((data: boolean) => {
        this.searchInput.nativeElement.blur();
        this.config.searchInput = '';
        this.setSearchInput("");
    });
  }

  private searchTerm$ = new BehaviorSubject<string>('');

  ngOnDestroy() {
    this.resetTypeAheadDataSubscription?.unsubscribe();
    this.typeaheadSubscribe?.unsubscribe();
    this.searchTermListener?.unsubscribe();
    this.searchInputSubscription?.unsubscribe();
    this.clearSearchInputSubscribe?.unsubscribe();
    this.activatedRouteListner?.unsubscribe();
  }

  /**
   * is it loading?
   */
  isloading: boolean = true;
  isVisible: boolean = false;
  ndcSpecificFlag: boolean = false;


  /**
   * Container for typeahead rendering
   * @type Object
   */
  typeaheadData:any = []; 

  supplierId: any;

  onBlurHandler(){
    setTimeout(() => {
      this.isVisible=false;
    }, 500);
  };

  typeaheadSubscribe!:Subscription;
  /**
   * Performs an typeahead search
   * @returns {undefined}
   */
  typeahead(searchInput: string) {
    const search = this.searchService
    this.config.searchCatCode = search.getTypeAheadCategoryCode();
    this.supplierId = this.supplierCatalogService.getSupplierId();
    //at least 3 characters needed
    if (searchInput.length >= 3) {
      if (this.searchtype === 'search') {
        search.resetTypeAheadToDefault();
        search.setTypeAheadSearchType("TypeAheadSearch");
      }
      if (this.searchtype === 'suppliercatalog') {
        search.resetTypeAheadToDefault();
        search.setTypeAheadSupplierId(this.supplierId);
      }
      if (this.searchtype === 'shortDated') {
        search.resetTypeAheadToDefault();
        search.setTypeAheadSearchType("ShortDateTypeAhead");
      }
      if (this.searchtype === 'OtcCategory') {
        search.resetTypeAheadToDefault();
        this.config.searchCatCode = this.tab ?? '';
        if (this.tab === undefined || this.tab === '') {
          let catCode: string = String(this.router.url.split('?')[0].split('/').pop());
          let directUrlCategories = search.getDirectUrlCategories()
          if (directUrlCategories.indexOf(catCode.toUpperCase()) !== -1) {
            this.config.searchCatCode = catCode;
          }
        }
      }
      if (this.searchtype === 'DiabeticSupplies') {
        search.resetTypeAheadToDefault();
        search.setTypeAheadSearchType("DiabeticSuppliesTypeAhead");
      }
      search.setTypeAheadSearchTerm(this.config.searchInput);
      search.setTypeAheadCategoryCode(this.config.searchCatCode);
      this.isloading = true;
      this.typeaheadSubscribe = search.typeahead()
        .pipe(
          debounceTime(500),
          distinctUntilChanged(),
          catchError(() => {
            return throwError(() => new Error('ups sommething happend'));
          })
        )
        .subscribe({
          next: (res: any) => {
            //feed typeahead data to object
            this.typeaheadData = res.data.search_result.other[0];
            this.isloading = false;
          },
          error: (err) => {
            this.searchService.errorCallBack(err);
          },
          complete: () => { },
        })
    }
    if (this.searchtype === 'search') {
      this.setSearchInput(this.config.searchInput);
      if (searchInput && searchInput.length >= 1) {
        this.showClearSign.emit(searchInput)
      }
      if (searchInput.length < 1) {
        this.hideClearSign.emit(searchInput);
      }
    }
    else if (this.searchtype === 'suppliercatalog') {
      this.setSupplierSearchInput(this.config.searchInput);
      if (searchInput && searchInput.length >= 1) {
        this.showClearSignSC.emit(searchInput);
      }
      if (searchInput.length < 1) {
        this.hideClearSignSC.emit(searchInput);
      }
    }
    else if (this.searchtype === 'shortDated') {
      this.setShortDatedSearchInput(this.config.searchInput);
      if (searchInput && searchInput.length >= 1) {
        this.showClearSignSSD.emit(searchInput);
      }
      if (searchInput.length < 1) {
        this.hideClearSignSSD.emit(searchInput);
      }
    }
    else if (this.searchtype === 'OtcCategory' || this.searchtype === 'DiabeticSupplies') {
      if (this.searchtype === 'OtcCategory') {
        this.setSupplierSearchInput(this.config.searchInput);
      }
      if (this.searchtype === 'DiabeticSupplies') {
        this.setDiabeticSuppliesSearchInput(this.config.searchInput);
      }
      if (searchInput && searchInput.length >= 1) {
        this.showClearSignSC.emit(searchInput);
      }
      if (searchInput.length < 1) {
        this.hideClearSignSC.emit(searchInput);
      }
    }
    search.resetTypeAheadData.emit("")
  };

  onSearchSuggestionSelection(match:any){
    if(match?.NDC === 'Loading...'){
      this.config.searchInput = '';
      this.hideClearSign.emit(this.config.searchInput);
    }else{
      this.config.searchInput = match;
      this.selectTypeAhead();
    }
  }

  getSearchInput(value: string) {    
    this.searchTerm$.next(value);
  }

  /**
   * Event gets called when a typeahead item is clicked
   * @returns {undefined}
   */
  selectTypeAhead() {
    let search = this.searchService;
    if (typeof (this.config.searchInput) === 'object') {
        this.config.selectedInput = this.config.searchInput;
        this.config.searchInput = this.config.selectedInput.shortName;
        search.searchLabel = this.config.searchInput;
        this.setSearchTermsFromTypeahead(this.config.selectedInput);
    }
    search.resetTypeAheadSupplierId();
  };

  /**
   * Sets the current search input
   * @param {string} Input
   * @returns {undefined}
   */
  setSearchInput(Input: string) {
    this.searchService.setSearchTerm(Input);
  };
  /**
   * Sets the current search input
   * @param {string} Input
   * @returns {undefined}
   */
  setSupplierSearchInput(Input: string) {
    this.searchService.setSpecificSearchSearchTerm(Input);
  };

  setShortDatedSearchInput(Input: string) {
    this.searchService.setSpecificSearchSearchTerm(Input);
  };

  setOtcSearchInput(Input: string) {
    this.searchService.setSpecificSearchSearchTerm(Input);
  };

  setDiabeticSuppliesSearchInput(Input: string) {
    this.searchService.setSpecificSearchSearchTerm(Input);
  };


  /**
   * Sets the searchQuery values according to typeahead object selected
   * @param {object} selected object
   * @returns {undefined}
   */
  setSearchTermsFromTypeahead(selected: any) {
    if (typeof (selected) == 'object') {
      if (selected.categoryCode === '') {
        selected.categoryCode = 'All';
      }
      let search = this.searchService;
      search.setCategoryCode(selected.categoryCode);
      var input = '';

      /**
       * Type Ahead selection converts search bar entry to product name
       */
      if (selected.NDC) {
        input = selected.NDC;
      } else {
        input = selected.shortName;
      }
      if (this.searchtype === 'search') {
        this.ndcSpecificFlag = false;
        if (this.localStorageService.getItem('ndc_specific_search_only') === 'true') {
            this.ndcSpecificFlag = true;
        }
        search.resetNDCSpecificCheck(this.ndcSpecificFlag);
        this.setSearchInput(input);
        setTimeout(() => {
          this.searchBySearchForm.emit({});
        }, 500);
      }
      else if (this.searchtype === 'suppliercatalog') {
        search.setSpecificSearchSearchTerm('');
        search.resetSpecificSearchQuery();
        this.setSupplierSearchInput(input);
        search.setSpecificSearchType("SupplierCatalog");
        search.setSpecificSearchPageNumber(1);
        search.supplierSearchBySearchQuery.emit({resetFilters: true});
      }
      else if (this.searchtype === 'shortDated') {
        search.setSpecificSearchSearchTerm('');
        search.resetSpecificSearchQuery();
        this.setShortDatedSearchInput(input);
        search.setSpecificSearchType("ShortDateSearch");
        search.setSpecificSearchPageNumber(1);
        search.shortDatedSearchBySearchQuery.emit({resetFilters: true});
      }
      else if (this.searchtype === 'OtcCategory') {
        search.setSpecificSearchSearchTerm('');
        search.resetSpecificSearchQuery();
        this.setOtcSearchInput(input);
        search.setSpecificSearchType("OtcCategory");
        search.setSpecificSearchPageNumber(1);
        search.otcCatagorySearchQuery.emit({resetFilters: true});
      }
      else if (this.searchtype === 'DiabeticSupplies') {
        search.setSpecificSearchSearchTerm('');
        search.resetSpecificSearchQuery();
        this.setDiabeticSuppliesSearchInput(input);
        search.setSpecificSearchType("DiabeticSupplies");
        search.setSpecificSearchPageNumber(1);
        search.diabeticSuppliesSearchQuery.emit({resetFilters: true});
      }
    }
  };

  /**
   * overrides angular strap comparator, comparion is doen in the backend
   */
  typeaheadComparator(input: any, actual: any) {
    //there is always a match
    return true;
  };

  /**
   * Introduced as part of TRX-8003
   * Strips Special characters from Start and end of Search Input
   * 
   * @param {string} input
   *
   * @returns {void}
  */
  trimSearchInput(input: string) {
    this.config.searchInput = this.stripNDCPipe.transform(input);
  };

  resetSearchPayload() {
    this.searchService.resetAllToInitialState();
    this.searchService.setTypeAheadCategoryCode('All');
  }
}
