/*
 * Copyright (C) 2023 Robert Bosch GmbH Copyright (C) 2023 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import {
  AfterContentInit,
  ChangeDetectorRef,
  Component,
  ContentChildren,
  EventEmitter,
  Input,
  OnDestroy,
  OnInit,
  Output,
  QueryList,
} from '@angular/core';
import { BciSharedIntl } from '../shared-intl';
import { BciFilterService } from './service/bci-filter.service';
import { BciFilterTabComponent } from './bci-filter-tab/bci-filter-tab.component';
import { Subject, distinctUntilChanged, takeUntil } from 'rxjs';
import { FormGroup } from '@angular/forms';

@Component({
  selector: 'bci-filter',
  templateUrl: './bci-filter.component.html',
  styleUrls: ['./bci-filter.component.scss'],
})
export class BciFilterComponent implements OnInit, AfterContentInit, OnDestroy {
  // holds collection of tabs Form Group
  @Input()
  public formGroup: FormGroup;

  // Emitter to emit value onclick of Apply button
  @Output()
  public filter: EventEmitter<string> = new EventEmitter<string>();

  @Output()
  // eslint-disable-next-line @angular-eslint/no-output-native
  public close: EventEmitter<string> = new EventEmitter<string>();

  // search text entered in search field
  searchInput = '';

  // variable to show 'x' icon on focus of search input field
  isSearchInputFocused = false;

  //holds the value of tab - label, activecount, emptystate
  tabLabelValue : {label: string, activeCount: number, showEmptyState: boolean }[] =  []; 

  //holds the value of total of number of all the active filters applied within each tabs
  totalActiveCount = 0;

  //holds the index of the current selected tab
  selectedTabIndex = 0;

  /** Used for component-wide unsubscription on destroy. */
  private ngUnsubscribe = new Subject<void>();

  // Use to query for all instances of BciFilterTabComponent
  @ContentChildren(BciFilterTabComponent, { descendants: true })
  private childComponents: QueryList<BciFilterTabComponent>;

  tabControlNames = [];

  numberOfTotalActiveFilterBeforeCancel = 0;

  constructor(
    public intl: BciSharedIntl,
    private changeDetector: ChangeDetectorRef,
    public bciFilterService: BciFilterService
  ) {}

  ngOnInit() {
    this.intl.changes.pipe(takeUntil(this.ngUnsubscribe)).subscribe(() => this.changeDetector.detectChanges());
  }

  ngAfterContentInit(): void {
    //To get label names, active count from child tab components and set here to display inside the mat-tab-group
    this.tabControlNames = Object.keys(this.formGroup.value);
    this.tabControlNames.map((tab,index)=> {
      const tabValue = {label: (this.childComponents.toArray())[index]?.label, activeCount: (this.childComponents.toArray())[index]?.activeFilterCount, showEmptyState: false}
      this.tabLabelValue.push(tabValue);
    });
    this.setChildState();
    this.numberOfTotalActiveFilterBeforeCancel = this.bciFilterService.totalActiveFilterCount;
    this.selectedTabIndex = 0;
    this.displayTabContent();

  }

  ngOnDestroy(): void {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

  /**
   * Method called on click of Apply button
   */
  applyFilters() {    
    this.bciFilterService.totalActiveFilterCount = this.totalActiveCount;    
    this.bciFilterService.updateFormGroup();
    this.filter.emit();
  }

  /**
   * Method used for closing the dialog modal
   */
  closeModal() {
    this.bciFilterService.totalActiveFilterCount = this.numberOfTotalActiveFilterBeforeCancel;
    this.bciFilterService.cancelUnappliedFilters();
    this.close.emit();
  }

  /**
   * Method to emit data on click of reset all filter button
   */
  onClickResetfilters() {
    this.formGroup.reset(this.bciFilterService.initialTabValues);
    this.childComponents.forEach((child) => {
      child.resetTab();
    });
    
    this.bciFilterService.activateApplyBtn = true;
  }

  /**
   * Change event called on click of another tab
   * @param event
   */
  onSelectedTabChange(event) {
    this.selectedTabIndex = event.index;
    this.displayTabContent();
  }

  /**
   * Method called on click of search icon after entering the search string
   */
  searchSubmit() {
    this.bciFilterService.searchText.next(this.searchInput);
  }

  /**
   * Method called to reset or remove the search string
   */
  removeFilter() {
    this.searchInput = '';
    this.bciFilterService.searchText.next(this.searchInput);
  }

  /**
   * Method used for displaying the tab content dynamically based on index
   * @param index
   */
  displayTabContent() { 
    this.childComponents.forEach((child, i) => {      
      if (i === this.selectedTabIndex) {
        child.show = true;
      } else {
        child.show = false;
      }
    });
  }

  /**
   * Method used for setting the tab state and handle the changes inside the each tab respectively
   */
  setChildState() {
    this.childComponents.forEach((child, i) => {
      //Detects the changes in the tab's active filter count and activates/deacivates the apply and reset buttons accordingly,
      // along with total number of acitve filter counts overall
      child.updateActiveFilterCount.pipe(distinctUntilChanged()).subscribe((activeCount:number) => {
        this.tabLabelValue[i].activeCount = activeCount;
        this.totalActiveCount = 0;
        this.tabLabelValue.forEach(tab=>
          {
            this.totalActiveCount = this.totalActiveCount+ tab.activeCount;
          });
        (this.formGroup.dirty) ? this.bciFilterService.activateApplyBtn = true :  this.bciFilterService.activateApplyBtn = false;
        this.totalActiveCount > 0 ? this.bciFilterService.activateResetAllBtn = true : this.bciFilterService.activateResetAllBtn = false;
        this.bciFilterService.totalActiveFilterCount = this.totalActiveCount;
      });

      //Detect the changes in the tabs visibility , then update the emptystates for respective tabs accordingly
      child.updateFilterVisibility.subscribe((data: boolean) => {
        this.tabLabelValue[i].showEmptyState = data;
        (i === this.selectedTabIndex) ? child.show = true: child.show = false;
      }); 
         
      //Sets the tabs content 
      child.tab = this.formGroup.controls[this.tabControlNames[i]] as FormGroup;
      child.setContent([this.tabControlNames[i]]);
    })
  }
}
