export interface BlockActionConfig {
  controlSelector: string;
  indicatorSelector: string;
  activeClass: string;
}

export const defaultConfig: BlockActionConfig = {
  controlSelector: ".block-action__control",
  indicatorSelector: ".block-action__indicator",
  activeClass: "is-indicating",
};

export default class BlockAction {
  private element: HTMLElement;
  private config: BlockActionConfig;
  private controlElement: HTMLElement | null = null;
  private indicatorElements: HTMLElement[] = [];

  constructor(element: HTMLElement, config?: Partial<BlockActionConfig>) {
    this.element = element;
    this.config = { ...defaultConfig, ...config };

    this.highlightIndicators = this.highlightIndicators.bind(this);
    this.unhighlightIndicators = this.unhighlightIndicators.bind(this);

    (this.element as any).ODS_BlockAction = this;

    this.init();
    return this;
  }

  private init(): void {
    this.controlElement = this.element.querySelector(
      this.config.controlSelector,
    ) as HTMLElement | null;
    this.indicatorElements = Array.from(
      this.element.querySelectorAll(this.config.indicatorSelector),
    ) as HTMLElement[];

    if (!this.controlElement || this.indicatorElements.length < 1) {
      return;
    }

    this.controlElement.addEventListener(
      "mouseenter",
      this.highlightIndicators,
    );
    this.controlElement.addEventListener(
      "mouseleave",
      this.unhighlightIndicators,
    );
    this.controlElement.addEventListener("focus", this.highlightIndicators);
    this.controlElement.addEventListener("blur", this.unhighlightIndicators);
  }

  private highlightIndicators(): void {
    this.indicatorElements.forEach((el) =>
      el.classList.add(this.config.activeClass),
    );
  }

  private unhighlightIndicators(): void {
    this.indicatorElements.forEach((el) =>
      el.classList.remove(this.config.activeClass),
    );
  }

  public destroy(): void {
    this.indicatorElements.forEach((el) =>
      el.classList.remove(this.config.activeClass),
    );
    if (this.controlElement) {
      this.controlElement.removeEventListener(
        "mouseenter",
        this.highlightIndicators,
      );
      this.controlElement.removeEventListener(
        "mouseleave",
        this.unhighlightIndicators,
      );
      this.controlElement.removeEventListener(
        "focus",
        this.highlightIndicators,
      );
      this.controlElement.removeEventListener(
        "blur",
        this.unhighlightIndicators,
      );
    }
    this.controlElement = null;
    this.indicatorElements = [];
  }

  public update(): void {
    this.destroy();
    this.init();
  }

  static getInstance(el: HTMLElement): BlockAction | null {
    return el && (el as any).ODS_BlockAction
      ? (el as any).ODS_BlockAction
      : null;
  }
}
