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

import { Injectable } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Subject } from 'rxjs';

export enum Actions {
  Add = 'Add',
  Remove ='Remove'
}

@Injectable({
  providedIn: 'root',
})
export class BciFilterService {
  //used for activating the 'Reset All' button  
  activateResetAllBtn = false; 

  //used for activating the 'Apply' button
  activateApplyBtn = false;

  //holds the updated formgroup after the activating the filters
  updatedTabFormGroup : FormGroup = new FormGroup([]);

  //emitted on click of search/removal of the search text
  searchText = new Subject();
  
  //holds the current number of the total active filters applied
  totalActiveFilterCount: number;

  //holds the initial value of the Formgroup as object
  initialTabValues:unknown = {};

  //holds the Formgroup used for further operations
  nestedTabsFormGroup: FormGroup = new FormGroup([]);

  //holds the map of active filters key as section label, value as list of fields which is used by the user
  listOfActiveFilters = new Map<string, any[]>;

  //holds the map of active filters , where key is section label, 
  //value as {fieldname: fieldvalue}, which is updated for everychange in the fieldvalue of respective fields within the section
  listOfActiveFields = new Map<string, any>;

  //holds the map of Sections, where key is Section label , 
  //value is the control path within the formgroup for that section which is used for deactivating a section after it is applied
  sectionLabelControlPathMap = new Map<string,string[]>;

  /**
   * Method used for the setting the initial state of the filter component
   * @param form 
   */
  setInitialFilterValues(form: FormGroup) {
    this.initialTabValues = form.value;
    !this.totalActiveFilterCount && (this.nestedTabsFormGroup = form);
  }

  /**
   * Method called on click of Cancel button
   * @returns
   */
  cancelUnappliedFilters() {
    this.nestedTabsFormGroup = this.updatedTabFormGroup;
  }

  /**
   * Method called on click of the reset on the section
   * @param tabIndex
   * @param sectionIndex
   * @returns
   */
  resetInsideSectionFilter(path: string[]) {
    this.nestedTabsFormGroup?.get([...path])
      ?.setValue(this.initialTabValues[path[0]][path[1]]);
    this.nestedTabsFormGroup.markAsDirty();
  }

  /**
   * Used for deactivating the filters on click of 'x' button of the selected chips section
   * @param selectedSection
   */
  deactiveBciFilter(selectedSection: string) {
    this.resetInsideSectionFilter(this.sectionLabelControlPathMap.get(selectedSection));
  }

  /**
   * Method to update active filters map based on the changes in field values
   * @param action 
   * @param section 
   * @param field 
   * @param value 
   */
  updateActiveFiltersList(action: string, section: string, field: string, value: any) {

    //Prepare List of Active Fields
    const hasField = this.listOfActiveFields.has(section);
    if(action === Actions.Add && !hasField) {
      const obj = {};
      obj[field] = value;
      this.listOfActiveFields.set(section,obj);
    } if(action === Actions.Add && hasField) {
      const obj = this.listOfActiveFields.get(section);
      obj[field] = value;
      this.listOfActiveFields.set(section,obj);
    } else if(hasField && action === Actions.Remove) {
      const obj = this.listOfActiveFields.get(section);
      delete obj[field];
      this.listOfActiveFields.set(section,obj);
    }

    this.listOfActiveFields.forEach((value,key) => {
      if(Object.values(value).length > 0)
        this.listOfActiveFilters.set(key,Object.values(value));
      else 
        this.listOfActiveFilters.delete(key);
    })
  }

  /**
   * Method used to keep track of the updated formgroup on activating the filters
   */
  updateFormGroup() {
    this.updatedTabFormGroup = this.nestedTabsFormGroup;
  }

  /**
   * Method used to compare values of old and new for a field using path ex: [tab1,section1,field1]
   * @param path
   * @param form
   * @returns
   */
  comparePreviousValue(path:string[],form: FormGroup) {
    const prevValue = this.initialTabValues[path[0]][path[1]][path[2]] as any;
    const currValue = form.get([...path]).value as any;

    if(Array.isArray(prevValue) && Array.isArray(currValue)) {
      return prevValue.length !== currValue.length;
    }
    return prevValue !== currValue;
  }

  /**
   * Method to check the field label contains the search text
   * @param value 
   * @param searchText 
   * @returns 
   */
  checkFieldLabelContainsSearchString(value, searchText: string): boolean {
    return value?.toLocaleLowerCase().trim().includes(searchText.toLocaleLowerCase()); // Check for a non-empty string
  }
}
