import { Overlay, OverlayModule } from '@angular/cdk/overlay';
import {
  ChangeDetectionStrategy,
  Component,
  computed,
  inject,
  input,
  model,
  output,
} from '@angular/core';
import { IconButtonComponent } from '@isa/ui/buttons';
import { FilterMenuComponent } from './filter-menu.component';
import { FilterService } from '../../core';

/**
 * A button component that toggles the visibility of a filter menu.
 * It emits events when the menu is opened, closed, reset, or applied.
 */
@Component({
  selector: 'filter-filter-menu-button',
  templateUrl: './filter-menu-button.component.html',
  styleUrls: ['./filter-menu-button.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [IconButtonComponent, OverlayModule, FilterMenuComponent],
})
export class FilterMenuButtonComponent {
  scrollStrategy = inject(Overlay).scrollStrategies.block();

  #filter = inject(FilterService);

  selectedFilters = this.#filter.selectedFilterCount;

  /**
   * Tracks the open state of the filter menu.
   */
  open = model<boolean>(false);

  /**
   * Emits an event when the filter menu is closed.
   */
  closed = output<void>();

  /**
   * Emits an event when the filter menu is opened.
   */
  opened = output<void>();

  /**
   * Emits an event when the filter menu is reset.
   */
  reseted = output<void>();

  /**
   * Emits an event when the filter menu is applied.
   */
  applied = output<void>();

  /**
   * Determines whether to roll back changes when the menu is closed.
   */
  rollbackOnClose = input<boolean>(false);

  /**
   * Toggles the open state of the filter menu.
   * Emits `opened` or `closed` events based on the new state.
   */
  toggle() {
    const open = this.open();
    this.open.set(!open);

    if (open) {
      this.closed.emit();
    } else {
      this.opened.emit();
    }
  }

  constructor() {
    /**
     * Subscribes to the `closed` event to roll back changes if `rollbackOnClose` is true.
     */
    this.closed.subscribe(() => {
      if (this.rollbackOnClose()) {
        setTimeout(() => {
          this.#filter.rollback();
        });
      }
    });

    /**
     * Subscribes to the `applied` event to automatically close the menu.
     */
    this.applied.subscribe(() => {
      this.toggle();
    });
  }
}
