import 'styling/_ResultsFiltersPreferences';
import * as _ from 'underscore';
import { BreadcrumbEvents, IPopulateBreadcrumbEventArgs } from '../../events/BreadcrumbEvents';
import { InitializationEvents } from '../../events/InitializationEvents';
import { PreferencesPanelEvents } from '../../events/PreferencesPanelEvents';
import { IBuildingQueryEventArgs, QueryEvents } from '../../events/QueryEvents';
import { exportGlobally } from '../../GlobalExports';
import { MODEL_EVENTS } from '../../models/Model';
import { QueryStateModel, QUERY_STATE_ATTRIBUTES } from '../../models/QueryStateModel';
import { l } from '../../strings/Strings';
import { getHeadingTag } from '../../utils/AccessibilityUtils';
import { AccessibleButton } from '../../utils/AccessibleButton';
import { $$ } from '../../utils/Dom';
import { LocalStorageUtils } from '../../utils/LocalStorageUtils';
import { SVGDom } from '../../utils/SVGDom';
import { SVGIcons } from '../../utils/SVGIcons';
import { Utils } from '../../utils/Utils';
import { analyticsActionCauseList, IAnalyticsCustomFiltersChangeMeta } from '../Analytics/AnalyticsActionListMeta';
import { Component } from '../Base/Component';
import { IComponentBindings } from '../Base/ComponentBindings';
import { ComponentOptions } from '../Base/ComponentOptions';
import { Initialization } from '../Base/Initialization';
import { Checkbox } from '../FormWidgets/Checkbox';
import { FormGroup } from '../FormWidgets/FormGroup';
import { MultiSelect } from '../FormWidgets/MultiSelect';
import { TextInput } from '../FormWidgets/TextInput';
import { Tab } from '../Tab/Tab';

export interface IResultFilterPreference {
  selected?: boolean;
  custom?: boolean;
  tab?: string[];
  caption: string;
  expression: string;
}

export interface IResultsFiltersPreferencesOptions {
  filters?: {
    [caption: string]: { expression: string; tab?: string[] };
  };
  includeInBreadcrumb?: boolean;
  showAdvancedFilters?: boolean;
}

/**
 * The `ResultFiltersPreferences` component allows end users to create custom filters to apply to queries. These filters
 * are saved to local storage.
 *
 * Only advanced end users who understand the Coveo query syntax should use this feature (see
 * [Coveo Query Syntax Reference](https://docs.coveo.com/en/1552/searching-with-coveo/coveo-cloud-query-syntax)).
 *
 * This component is normally accessible through the [`Settings`]{@link Settings} menu. Its usual location in the DOM is
 * inside the [`PreferencesPanel`]{@link PreferencesPanel} element.
 *
 * See also the {@link ResultsPreferences} component.
 */
export class ResultsFiltersPreferences extends Component {
  static ID = 'ResultsFiltersPreferences';

  static doExport = () => {
    exportGlobally({
      ResultsFiltersPreferences: ResultsFiltersPreferences
    });
  };

  /**
   * The options for the component
   * @componentOptions
   */
  static options: IResultsFiltersPreferencesOptions = {
    /**
     * Specifies whether to display the active filter(s) in the [`Breadcrumb`]{@link Breadcrumb}.
     *
     * Default value is `true`.
     */
    includeInBreadcrumb: ComponentOptions.buildBooleanOption({ defaultValue: true }),

    /**
     * Specifies whether to show the **Create** button that allows the end user to create filters.
     *
     * If you set this option to `false`, only the pre-populated
     * [`filters`]{@link ResultsFiltersPreferences.options.filters} are available to the end user.
     *
     * Default value is `true`.
     */
    showAdvancedFilters: ComponentOptions.buildBooleanOption({ defaultValue: true }),

    /**
     * Specifies the default filters which all end users can apply.
     *
     * End users cannot modify or delete these filters. These filters do not count as "user-made" filters, but rather as
     * "built-in" filters created by the developer of the search page.
     *
     * **Note:**
     * > You cannot set this option directly in the component markup as an HTML attribute. You must either set it in the
     * > [`init`]{@link init} call of your search interface (see
     * > [Passing Component Options in the init Call](https://docs.coveo.com/en/346/#passing-component-options-in-the-init-call)),
     * > or before the `init` call, using the `options` top-level function (see
     * > [Passing Component Options Before the init Call](https://docs.coveo.com/en/346/#passing-component-options-before-the-init-call)).
     *
     * Filters should follow this definition:
     *
     * `filters : { [caption : string] : { expression : string, tab? : string[] } }`;
     *
     * **Example:**
     *
     * var myFilters = {
     *   "Only Google Drive Items" : {
     *     expression : "@connectortype == 'GoogleDriveCrawler'",
     *     tab : ["Tab1", "Tab2"]
     *   },
     *
     *   "Another Filter" : {
     *     expression : [ ... another expression ... ]
     *   },
     *
     *   [ ... ]
     * };
     *
     * ```javascript
     * // You can set the option in the 'init' call:
     * Coveo.init(document.querySelector("#search"), {
     *   ResultsFiltersPreferences : {
     *     filters : myFilters
     *   }
     * });
     *
     * // Or before the 'init' call, using the 'options' top-level function:
     * // Coveo.options(document.querySelector("#search"), {
     * //   ResultsFiltersPreferences : {
     *        filters : myFilters
     *      }
     * // });
     * ```
     *
     * Default value is `undefined`.
     */
    filters: <any>ComponentOptions.buildJsonOption()
  };

  public preferences: { [caption: string]: IResultFilterPreference };
  public container: HTMLFieldSetElement;
  private preferencePanelLocalStorage: LocalStorageUtils<{ [caption: string]: IResultFilterPreference }>;
  private preferencePanel: HTMLElement;
  private preferenceContainer: HTMLElement;
  private preferencePanelCheckboxInput: { [caption: string]: Checkbox } = {};
  private advancedFilters: HTMLElement;
  private advancedFiltersBuilder: HTMLElement;
  private advancedFiltersTextInputCaption: TextInput;
  private advancedFiltersTextInputExpression: TextInput;
  private advancedFiltersTabSelect: MultiSelect;
  private advancedFilterFormValidate: HTMLFormElement;
  private isFullBreadcrumbClear: boolean;

  /**
   * Creates a new `ResultsFiltersPreferences` component.
   * @param element The HTMLElement on which to instantiate the component.
   * @param options The options for the `ResultsFiltersPreferences` component.
   * @param bindings The bindings that the component requires to function normally. If not set, these will be
   * automatically resolved (with a slower execution time).
   */
  constructor(public element: HTMLElement, public options: IResultsFiltersPreferencesOptions, public bindings: IComponentBindings) {
    super(element, ResultsFiltersPreferences.ID, bindings);

    this.options = ComponentOptions.initComponentOptions(element, ResultsFiltersPreferences, options);

    this.preferencePanel = $$(this.element).closest(Component.computeCssClassNameForType('PreferencesPanel'));
    if (!this.preferencePanel) {
      this.logger.warn(`Cannot instantiate ResultsFilterPreferences, as there is no "CoveoPreferencesPanel" in your page !`);
      return;
    }
    this.preferencePanelLocalStorage = new LocalStorageUtils<{ [caption: string]: IResultFilterPreference }>(ResultsFiltersPreferences.ID);
    this.mergeLocalPreferencesWithStaticPreferences();

    this.bindPreferencePanelEvent();
    this.bindBreadcrumbEvent();
    this.bindQueryEvent();

    // We need to wait after all components are initialized before building the dom, because this component interacts with Tab
    // And we don't know if Tab(s) are initialized before or after this component.
    this.bind.oneRootElement(InitializationEvents.afterComponentsInitialization, () => this.createDom());

    this.bind.oneQueryState(MODEL_EVENTS.CHANGE_ONE, QUERY_STATE_ATTRIBUTES.T, () => this.fromPreferencesToCheckboxInput());
  }

  public createDom() {
    this.container = <HTMLFieldSetElement>new FormGroup([], l('ResultsFilteringExpression')).build();
    this.element.appendChild(this.container);
    this.buildCheckboxesInput();
    if (this.options.showAdvancedFilters) {
      this.buildAdvancedFilters();
    }
  }

  public save() {
    this.fromCheckboxInputToPreferences();
    const toSave = _.omit(this.preferences, 'tab');
    this.logger.info('Saving preferences', toSave);
    this.preferencePanelLocalStorage.save(toSave);
  }

  public exitWithoutSave() {
    this.fromPreferencesToCheckboxInput();
    this.hideAdvancedFilterBuilder();
  }

  private bindPreferencePanelEvent() {
    this.bind.on(this.preferencePanel, PreferencesPanelEvents.savePreferences, () => this.save());
    this.bind.on(this.preferencePanel, PreferencesPanelEvents.exitPreferencesWithoutSave, () => this.exitWithoutSave());
  }

  private bindBreadcrumbEvent() {
    if (this.options.includeInBreadcrumb) {
      this.bind.onRootElement(BreadcrumbEvents.populateBreadcrumb, (args: IPopulateBreadcrumbEventArgs) =>
        this.handlePopulateBreadcrumb(args)
      );
      this.bind.onRootElement(BreadcrumbEvents.clearBreadcrumb, () => this.handleClearBreadcrumb());
    }
  }

  private bindQueryEvent() {
    this.bind.onRootElement(QueryEvents.buildingQuery, (args: IBuildingQueryEventArgs) => this.handleBuildingQuery(args));
  }

  private handleBuildingQuery(args: IBuildingQueryEventArgs) {
    _.each(this.getActiveFilters(), filter => {
      if (Utils.isNonEmptyString(filter.expression)) {
        args.queryBuilder.advancedExpression.add(filter.expression);
      }
    });
  }

  private handlePopulateBreadcrumb(args: IPopulateBreadcrumbEventArgs) {
    const actives = this.getActiveFilters();
    if (Utils.isNonEmptyArray(actives)) {
      const container = $$('div', { className: 'coveo-results-filter-preferences-breadcrumb' });
      const title = $$(getHeadingTag(args.headingLevel, 'span'), { className: 'coveo-title' });
      title.text(l('FiltersInYourPreferences') + ':');
      container.el.appendChild(title.el);

      const valuesContainer = $$('span', { className: 'coveo-values' });
      container.el.appendChild(valuesContainer.el);

      for (var i = 0; i < actives.length; i++) {
        valuesContainer.el.appendChild(this.buildBreadcrumb(actives[i]));
      }
      args.breadcrumbs.push({ element: container.el });
    }
  }

  private handleClearBreadcrumb() {
    this.isFullBreadcrumbClear = true;
    _.each(this.getActiveFilters(), filter => {
      filter.selected = false;
    });
    this.fromPreferencesToCheckboxInput();
    this.isFullBreadcrumbClear = false;
  }

  private buildAdvancedFilters() {
    this.advancedFilters = $$('div', { className: 'coveo-advanced-filters' }, l('Create')).el;
    new AccessibleButton()
      .withElement(this.advancedFilters)
      .withoutLabelOrTitle()
      .withSelectAction(() => this.openAdvancedFilterSectionOrSaveFilters())
      .build();

    this.buildAdvancedFilterInput();
    this.buildAdvancedFilterFormValidate();
    this.advancedFiltersBuilder = $$('div', { className: 'coveo-advanced-filters-builder' }).el;
    this.advancedFiltersBuilder.appendChild(this.advancedFilterFormValidate);
    const onlineHelp = $$(
      'a',
      {
        href: 'https://docs.coveo.com/en/2053/index-content/inspect-items-with-the-content-browser#result-filtering-expressions',
        className: 'coveo-online-help'
      },
      '?'
    );

    const title = $$(this.container).find('.coveo-form-group-label');

    onlineHelp.insertAfter(title);
    $$(this.advancedFilters).insertAfter(title);
    this.container.appendChild(this.advancedFiltersBuilder);
  }

  private buildAdvancedFilterInput() {
    this.advancedFiltersTextInputCaption = new TextInput(() => {}, l('Caption'));

    this.advancedFiltersTextInputCaption.getInput().setAttribute('required', '');

    this.advancedFiltersTextInputExpression = new TextInput(() => {}, l('Expression'));

    this.advancedFiltersTextInputExpression.getInput().setAttribute('required', '');

    this.advancedFiltersTabSelect = new MultiSelect(() => {}, this.getAllTabs(), l('Tab'));
  }

  private buildAdvancedFilterFormValidate() {
    this.advancedFilterFormValidate = <HTMLFormElement>$$('form').el;

    const formSubmit = $$('input', {
      type: 'submit'
    });

    const saveFormButton = $$(
      'span',
      {
        className: 'coveo-save'
      },
      SVGIcons.icons.save
    );
    SVGDom.addClassToSVGInContainer(saveFormButton.el, 'coveo-save-svg');
    new AccessibleButton()
      .withElement(saveFormButton.el)
      .withLabel(l('Save'))
      .withSelectAction(() => formSubmit.el.click())
      .build();

    const closeFormButton = $$(
      'span',
      {
        className: 'coveo-close'
      },
      SVGIcons.icons.close
    );
    SVGDom.addClassToSVGInContainer(closeFormButton.el, 'coveo-close-svg');
    new AccessibleButton()
      .withElement(closeFormButton.el)
      .withLabel(l('Close'))
      .withSelectAction(() => this.hideAdvancedFilterBuilder())
      .build();

    const saveAndCloseContainer = $$('div', {
      className: 'coveo-choice-container coveo-close-and-save'
    });

    saveAndCloseContainer.el.appendChild(saveFormButton.el);
    saveAndCloseContainer.el.appendChild(closeFormButton.el);

    const inputCaption = this.advancedFiltersTextInputCaption.build();
    $$(inputCaption).addClass('coveo-caption');

    const filtersTabSelect = this.advancedFiltersTabSelect.build();
    $$(filtersTabSelect).addClass('coveo-tab');

    const filtersExpression = this.advancedFiltersTextInputExpression.build();
    $$(filtersExpression).addClass('coveo-expression');

    _.each([inputCaption, filtersExpression, filtersTabSelect, saveAndCloseContainer.el, formSubmit.el], (el: HTMLElement) => {
      this.advancedFilterFormValidate.appendChild(el);
    });

    $$(this.advancedFilterFormValidate).on('submit', (e: Event) => this.validateAndSaveAdvancedFilter(e));
  }

  private getAllTabs() {
    const tabRef = Component.getComponentRef('Tab');
    if (tabRef) {
      const tabsElement = $$(this.root).findAll('.' + Component.computeCssClassName(tabRef));
      return _.map(tabsElement, (tabElement: HTMLElement) => {
        let tab = <Tab>Component.get(tabElement);
        return tab.options.id;
      });
    } else {
      return [];
    }
  }

  private getPreferencesBoxInputToBuild() {
    return _.map(this.preferences, (filter: IResultFilterPreference) => {
      return {
        label: filter.caption,
        tab: filter.tab,
        expression: filter.expression
      };
    });
  }

  private buildCheckboxesInput() {
    if (this.preferenceContainer != undefined) {
      this.preferenceContainer.remove();
    }
    const toBuild = this.getPreferencesBoxInputToBuild();
    if (Utils.isNonEmptyArray(toBuild)) {
      this.preferenceContainer = $$('div', {
        className: 'coveo-choices-container'
      }).el;

      _.each(toBuild, filterToBuild => {
        const checkbox = new Checkbox((checkbox: Checkbox) => {
          this.save();
          const filter = this.preferences[checkbox.getValue()];

          if (!this.queryController.firstQuery && !this.isFullBreadcrumbClear) {
            this.fromFilterToAnalyticsEvent(filter, filter.selected ? 'selected' : 'unselected');
            this.queryController.executeQuery({
              closeModalBox: false
            });
          }
        }, filterToBuild.label);
        $$(checkbox.build()).addClass('coveo-choice-container');
        this.preferencePanelCheckboxInput[filterToBuild.label] = checkbox;
        this.preferenceContainer.appendChild(checkbox.getElement());
      });

      _.each($$(this.preferenceContainer).findAll('.coveo-choice-container'), (choiceContainer: HTMLElement) => {
        choiceContainer.appendChild($$('div', { className: 'coveo-section coveo-section-edit-delete' }).el);
      });

      $$(this.container).append(this.preferenceContainer);
      this.buildEditAdvancedFilter();
      this.buildDeleteAdvancedFilter();
      this.fromPreferencesToCheckboxInput();
    }
  }

  private buildDeleteAdvancedFilter() {
    _.each(this.preferences, filter => {
      if (filter.custom) {
        const deleteElement = $$(
          'span',
          {
            className: 'coveo-delete'
          },
          SVGIcons.icons.delete
        ).el;
        new AccessibleButton()
          .withElement(deleteElement)
          .withLabel(l('Delete'))
          .withSelectAction(() => this.confirmDelete(filter, filterElement))
          .build();
        SVGDom.addClassToSVGInContainer(deleteElement, 'coveo-delete-svg');
        const filterElement = this.getFilterElementByCaption(filter.caption);
        const insertInto = $$(filterElement).find('.coveo-section-edit-delete');
        insertInto.appendChild(deleteElement);
      }
    });
  }

  private buildEditAdvancedFilter() {
    _.each(this.preferences, filter => {
      if (filter.custom) {
        const editElement = $$(
          'span',
          {
            className: 'coveo-edit'
          },
          SVGIcons.icons.edit
        );
        new AccessibleButton()
          .withElement(editElement)
          .withLabel(l('Edit'))
          .withSelectAction(() => this.editElement(filter, filterElement))
          .build();
        SVGDom.addClassToSVGInContainer(editElement.el, 'coveo-edit-svg');
        const filterElement = this.getFilterElementByCaption(filter.caption);
        const insertInto = $$(filterElement).find('.coveo-section-edit-delete');
        insertInto.appendChild(editElement.el);
      }
    });
  }

  private buildBreadcrumb(filter: IResultFilterPreference): HTMLElement {
    const elem = $$('span', { className: 'coveo-value' });

    const caption = $$('span', { className: 'coveo-caption' });
    caption.text(filter.caption);
    elem.el.appendChild(caption.el);

    const clear = $$('span', { className: 'coveo-clear' }, SVGIcons.icons.mainClear);
    elem.el.appendChild(clear.el);

    const onSelectAction = () => {
      filter.selected = false;
      this.fromFilterToAnalyticsEvent(filter, 'cleared from breadcrumb');
      this.fromPreferencesToCheckboxInput();
    };

    new AccessibleButton().withElement(elem).withLabel(l('RemoveFilterOn', filter.caption)).withSelectAction(onSelectAction).build();

    return elem.el;
  }

  private confirmDelete(filter: IResultFilterPreference, filterElement: HTMLElement) {
    if (confirm(l('AreYouSureDeleteFilter', filter.caption, filter.expression))) {
      const isSelected = filter.selected;
      this.deleteFilterPreference(filter, filterElement);
      if (isSelected) {
        this.fromFilterToAnalyticsEvent(filter, 'deleted');
        this.queryController.executeQuery({
          closeModalBox: false
        });
      }
    }
  }

  private editElement(filter: IResultFilterPreference, filterElement: HTMLElement) {
    const oldCaption = this.preferences[filter.caption].caption;
    const oldTab = this.preferences[filter.caption].tab;
    const oldExpression = this.preferences[filter.caption].expression;
    this.deleteFilterPreference(filter, filterElement);
    this.openAdvancedFilterSectionOrSaveFilters();
    this.populateEditSection({ tab: oldTab, caption: oldCaption, expression: oldExpression });
  }

  private populateEditSection(toPopulate = { tab: [''], caption: '', expression: '' }) {
    this.advancedFiltersTextInputCaption.setValue(toPopulate.caption);
    this.advancedFiltersTextInputExpression.setValue(toPopulate.expression);
    this.advancedFiltersTabSelect.setValue(toPopulate.tab);
  }

  private deleteFilterPreference(filter: IResultFilterPreference, filterElement: HTMLElement) {
    this.preferencePanelLocalStorage.remove(filter.caption);
    delete this.preferences[filter.caption];
    $$($$(filterElement).closest('.coveo-choice-container')).detach();
  }

  private openAdvancedFilterSectionOrSaveFilters() {
    if ($$(this.advancedFiltersBuilder).hasClass('coveo-active')) {
      $$($$(this.advancedFilterFormValidate).find('input[type=submit]')).trigger('click');
      this.hideAdvancedFilterBuilder();
    } else {
      this.populateEditSection();
      this.showAdvancedFilterBuilder();
    }
  }

  private validateAndSaveAdvancedFilter(e: Event) {
    e.preventDefault();
    this.hideAdvancedFilterBuilder();
    const caption = this.advancedFiltersTextInputCaption.getValue();
    const expression = this.advancedFiltersTextInputExpression.getValue();
    const tabs = this.advancedFiltersTabSelect.getValue();
    this.preferences[caption] = {
      caption: caption,
      custom: true,
      expression: expression,
      tab: tabs,
      selected: true
    };
    this.buildCheckboxesInput();
    this.save();
    this.queryStateModel.set(QueryStateModel.attributesEnum.t, this.getActiveTab());
    this.advancedFiltersTextInputCaption.reset();
    this.advancedFiltersTextInputExpression.reset();
    this.advancedFiltersTabSelect.reset();
    this.container.appendChild(this.advancedFiltersBuilder);
    this.fromFilterToAnalyticsEvent(this.preferences[caption], 'saved');
    this.queryController.executeQuery({
      closeModalBox: false
    });
  }

  private fromPreferencesToCheckboxInput() {
    _.each(this.getActiveFilters(), (filter: IResultFilterPreference) => {
      this.preferencePanelCheckboxInput[filter.caption].select();
    });
    _.each(this.getInactiveFilters(), (filter: IResultFilterPreference) => {
      this.preferencePanelCheckboxInput[filter.caption].reset();
    });
    _.each(this.getDormantFilters(), (filter: IResultFilterPreference) => {
      this.preferencePanelCheckboxInput[filter.caption].select();
    });
  }

  private fromCheckboxInputToPreferences() {
    if (this.preferencePanelCheckboxInput) {
      const selecteds = _.map(
        _.filter(this.preferencePanelCheckboxInput, (checkbox: Checkbox) => checkbox.isSelected()),
        (selected: Checkbox) => selected.getValue()
      );
      _.each(this.preferences, (filter: IResultFilterPreference) => {
        if (_.contains(selecteds, filter.caption)) {
          filter.selected = true;
        } else {
          filter.selected = false;
        }
      });
    }
  }

  private getDormantFilters() {
    const activeTab = this.getActiveTab();
    return _.filter(this.preferences, (filter: IResultFilterPreference) => {
      return filter.selected && !this.filterIsInActiveTab(filter, activeTab);
    });
  }

  private getActiveFilters() {
    const activeTab = this.getActiveTab();
    return _.filter(this.preferences, (filter: IResultFilterPreference) => {
      return filter.selected && this.filterIsInActiveTab(filter, activeTab);
    });
  }

  private getInactiveFilters() {
    const activeTab = this.getActiveTab();
    return _.filter(this.preferences, (filter: IResultFilterPreference) => {
      return !filter.selected || !this.filterIsInActiveTab(filter, activeTab);
    });
  }

  private getActiveTab() {
    return this.queryStateModel.get(QueryStateModel.attributesEnum.t);
  }

  private filterIsInActiveTab(filter: IResultFilterPreference, tab: string) {
    filter.tab = _.compact(filter.tab);
    return _.contains(filter.tab, tab) || Utils.isEmptyArray(filter.tab);
  }

  private getFilterElementByCaption(caption: string): HTMLElement {
    return $$(this.preferenceContainer).find("input[value='" + caption.replace(/'/g, "\\'") + "']").parentElement;
  }

  private fromResultsFilterOptionToResultsPreferenceInterface() {
    const ret: { [key: string]: IResultFilterPreference } = {};
    _.each(<any>this.options.filters, (filter: { expression: string; tab?: string[]; selected?: boolean }, caption: string) => {
      ret[caption] = {
        expression: filter.expression,
        tab: filter.tab,
        selected: filter.selected ? filter.selected : false,
        custom: false,
        caption: caption
      };
    });
    return ret;
  }

  private mergeLocalPreferencesWithStaticPreferences() {
    const staticPreferences = this.fromResultsFilterOptionToResultsPreferenceInterface();
    const localPreferences = this.preferencePanelLocalStorage.load();
    const localPreferencesWithoutRemoved = _.filter<IResultFilterPreference>(localPreferences, preference => {
      const isCustom = preference.custom;
      const existsInStatic = _.find<IResultFilterPreference>(staticPreferences, staticPreference => {
        return staticPreference.caption == preference.caption;
      });
      return isCustom || existsInStatic != undefined;
    });

    const localToMerge = {};
    _.each(localPreferencesWithoutRemoved, (filter: IResultFilterPreference) => {
      localToMerge[filter.caption] = {
        expression: filter.expression,
        tab: filter.tab,
        selected: filter.selected,
        custom: filter.custom,
        caption: filter.caption
      };
    });
    this.preferences = <{ [caption: string]: IResultFilterPreference }>Utils.extendDeep(staticPreferences, localToMerge);
  }

  private fromFilterToAnalyticsEvent(filter: IResultFilterPreference, type: string) {
    this.usageAnalytics.logSearchEvent<IAnalyticsCustomFiltersChangeMeta>(analyticsActionCauseList.customfiltersChange, {
      customFilterName: filter.caption,
      customFilterExpression: filter.expression,
      customFilterType: type
    });
  }

  private enlargeModalBox() {
    const modalBoxContainer = $$(document.body).find('.coveo-modal-container');
    if (modalBoxContainer) {
      $$(modalBoxContainer).addClass('coveo-mod-big');
    }
  }

  private shrinkModalBox() {
    const modalBoxContainer = $$(document.body).find('.coveo-modal-container');
    if (modalBoxContainer) {
      $$(modalBoxContainer).removeClass('coveo-mod-big');
    }
  }

  private showAdvancedFilterBuilder() {
    if (this.advancedFiltersBuilder) {
      $$(this.advancedFiltersBuilder).addClass('coveo-active');
      this.enlargeModalBox();
    }
  }

  private hideAdvancedFilterBuilder() {
    if (this.advancedFiltersBuilder) {
      $$(this.advancedFiltersBuilder).removeClass('coveo-active');
      this.shrinkModalBox();
    }
  }
}

Initialization.registerAutoCreateComponent(ResultsFiltersPreferences);
