interface HTMLElementWithExpander extends HTMLDetailsElement {
  ODS_Expander?: Expander;
}

export default class Expander {
  private element: HTMLElementWithExpander;

  constructor(element: HTMLElement) {
    this.element = element as HTMLElementWithExpander;
    this.toggle = this.toggle.bind(this);
    this.element.ODS_Expander = this;
    this.init();
  }

  toggle() {
    const toggleGroup = this.element.getAttribute("data-toggle-group");
    if (toggleGroup) {
      this.syncGroup(toggleGroup);
    }
  }

  private syncGroup(groupName: string) {
    const isOpen = this.element.open;
    const groupElements = document.querySelectorAll(
      `[data-toggle-group="${groupName}"][data-expander]`,
    ) as NodeListOf<HTMLDetailsElement>;

    groupElements.forEach((element) => {
      if (element !== this.element) {
        if (element.open !== isOpen) {
          element.open = isOpen;
        }
      }
    });
  }

  init() {
    this.element.addEventListener("toggle", this.toggle);
  }

  update() {
    this.destroy();
    this.init();
  }

  destroy() {
    this.element.removeEventListener("toggle", this.toggle);
  }

  static getInstance(el: HTMLElementWithExpander | null): Expander | null {
    return el && el.ODS_Expander ? el.ODS_Expander : null;
  }
}
