/**
 * @license
 * Copyright 2021 The Go Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

/**
 * TreeNavController is the navigation tree component of the documentation page.
 * It adds accessiblity attributes to a tree, observes the heading elements
 * focus the topmost link for headings visible on the page, and implements the
 * WAI-ARIA Treeview Design Pattern with full
 * [keyboard support](https://www.w3.org/TR/wai-aria-practices/examples/treeview/treeview-2/treeview-2a.html#kbd_label).
 */
export class TreeNavController {
  treeitems: TreeItem[];

  /**
   * firstChars is the first character of each treeitem in the same order
   * as this.treeitems. We use this array to set focus by character when
   * navigating the tree with a keyboard.
   */
  private firstChars: string[];
  private firstTreeitem: TreeItem | null;
  private lastTreeitem: TreeItem | null;
  private observerCallbacks: ((t: TreeItem) => void)[];

  constructor(private el: HTMLElement) {
    this.treeitems = [];
    this.firstChars = [];
    this.firstTreeitem = null;
    this.lastTreeitem = null;
    this.observerCallbacks = [];
    this.init();
  }

  private init(): void {
    this.el.style.setProperty('--js-tree-height', this.el.clientHeight + 'px');
    this.findTreeItems();
    this.updateVisibleTreeitems();
    this.observeTargets();
    if (this.firstTreeitem) {
      this.firstTreeitem.el.tabIndex = 0;
    }
  }

  private observeTargets() {
    this.addObserver(treeitem => {
      this.expandTreeitem(treeitem);
      this.setSelected(treeitem);
      // The current version of TypeScript is not aware of HTMLElement.scrollIntoViewIfNeeded.
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      if ((treeitem.el as any)?.scrollIntoViewIfNeeded) {
        // The current version of TypeScript is not aware of HTMLElement.scrollIntoViewIfNeeded.
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        (treeitem.el as any)?.scrollIntoViewIfNeeded();
      }
    });

    const targets = new Map<string, boolean>();
    const observer = new IntersectionObserver(
      entries => {
        for (const entry of entries) {
          targets.set(entry.target.id, entry.isIntersecting || entry.intersectionRatio === 1);
        }
        for (const [id, isIntersecting] of targets) {
          if (isIntersecting) {
            const active = this.treeitems.find(t =>
              (t.el as HTMLAnchorElement)?.href.endsWith(`#${id}`)
            );
            if (active) {
              for (const fn of this.observerCallbacks) {
                fn(active);
              }
            }
            break;
          }
        }
      },
      {
        threshold: 1.0,
        rootMargin: '-60px 0px 0px 0px',
      }
    );

    for (const href of this.treeitems.map(t => t.el.getAttribute('href'))) {
      if (href) {
        const id = href.replace(window.location.origin, '').replace('/', '').replace('#', '');
        const target = document.getElementById(id);
        if (target) {
          observer.observe(target);
        }
      }
    }
  }

  addObserver(fn: (t: TreeItem) => void, delay = 200): void {
    this.observerCallbacks.push(debounce(fn, delay));
  }

  setFocusToNextItem(currentItem: TreeItem): void {
    let nextItem = null;
    for (let i = currentItem.index + 1; i < this.treeitems.length; i++) {
      const ti = this.treeitems[i];
      if (ti.isVisible) {
        nextItem = ti;
        break;
      }
    }
    if (nextItem) {
      this.setFocusToItem(nextItem);
    }
  }

  setFocusToPreviousItem(currentItem: TreeItem): void {
    let prevItem = null;
    for (let i = currentItem.index - 1; i > -1; i--) {
      const ti = this.treeitems[i];
      if (ti.isVisible) {
        prevItem = ti;
        break;
      }
    }
    if (prevItem) {
      this.setFocusToItem(prevItem);
    }
  }

  setFocusToParentItem(currentItem: TreeItem): void {
    if (currentItem.groupTreeitem) {
      this.setFocusToItem(currentItem.groupTreeitem);
    }
  }

  setFocusToFirstItem(): void {
    this.firstTreeitem && this.setFocusToItem(this.firstTreeitem);
  }

  setFocusToLastItem(): void {
    this.lastTreeitem && this.setFocusToItem(this.lastTreeitem);
  }

  setSelected(currentItem: TreeItem): void {
    for (const l1 of this.el.querySelectorAll('[aria-expanded="true"]')) {
      if (l1 === currentItem.el) continue;
      if (!l1.nextElementSibling?.contains(currentItem.el)) {
        l1.setAttribute('aria-expanded', 'false');
      }
    }
    for (const l1 of this.el.querySelectorAll('[aria-selected]')) {
      if (l1 !== currentItem.el) {
        l1.setAttribute('aria-selected', 'false');
      }
    }
    currentItem.el.setAttribute('aria-selected', 'true');
    this.updateVisibleTreeitems();
    this.setFocusToItem(currentItem, false);
  }

  expandTreeitem(treeitem: TreeItem): void {
    let currentItem: TreeItem | null = treeitem;
    while (currentItem) {
      if (currentItem.isExpandable) {
        currentItem.el.setAttribute('aria-expanded', 'true');
      }
      currentItem = currentItem.groupTreeitem;
    }
    this.updateVisibleTreeitems();
  }

  expandAllSiblingItems(currentItem: TreeItem): void {
    for (const ti of this.treeitems) {
      if (ti.groupTreeitem === currentItem.groupTreeitem && ti.isExpandable) {
        this.expandTreeitem(ti);
      }
    }
  }

  collapseTreeitem(currentItem: TreeItem): void {
    let groupTreeitem = null;

    if (currentItem.isExpanded()) {
      groupTreeitem = currentItem;
    } else {
      groupTreeitem = currentItem.groupTreeitem;
    }

    if (groupTreeitem) {
      groupTreeitem.el.setAttribute('aria-expanded', 'false');
      this.updateVisibleTreeitems();
      this.setFocusToItem(groupTreeitem);
    }
  }

  setFocusByFirstCharacter(currentItem: TreeItem, char: string): void {
    let start: number, index: number;
    char = char.toLowerCase();

    // Get start index for search based on position of currentItem
    start = currentItem.index + 1;
    if (start === this.treeitems.length) {
      start = 0;
    }

    // Check remaining slots in the menu
    index = this.getIndexFirstChars(start, char);

    // If not found in remaining slots, check from beginning
    if (index === -1) {
      index = this.getIndexFirstChars(0, char);
    }

    // If match was found...
    if (index > -1) {
      this.setFocusToItem(this.treeitems[index]);
    }
  }

  private findTreeItems() {
    const findItems = (el: HTMLElement, group: TreeItem | null) => {
      let ti = group;
      let curr = el.firstElementChild as HTMLElement;
      while (curr) {
        if (curr.tagName === 'A' || curr.tagName === 'SPAN') {
          ti = new TreeItem(curr, this, group);
          this.treeitems.push(ti);
          this.firstChars.push(ti.label.substring(0, 1).toLowerCase());
        }
        if (curr.firstElementChild) {
          findItems(curr, ti);
        }
        curr = curr.nextElementSibling as HTMLElement;
      }
    };
    findItems(this.el as HTMLElement, null);
    this.treeitems.map((ti, idx) => (ti.index = idx));
  }

  private updateVisibleTreeitems(): void {
    this.firstTreeitem = this.treeitems[0];

    for (const ti of this.treeitems) {
      let parent = ti.groupTreeitem;
      ti.isVisible = true;
      while (parent && parent.el !== this.el) {
        if (!parent.isExpanded()) {
          ti.isVisible = false;
        }
        parent = parent.groupTreeitem;
      }
      if (ti.isVisible) {
        this.lastTreeitem = ti;
      }
    }
  }

  private setFocusToItem(treeitem: TreeItem, focusEl = true) {
    treeitem.el.tabIndex = 0;
    if (focusEl) {
      treeitem.el.focus();
    }
    for (const ti of this.treeitems) {
      if (ti !== treeitem) {
        ti.el.tabIndex = -1;
      }
    }
  }

  private getIndexFirstChars(startIndex: number, char: string): number {
    for (let i = startIndex; i < this.firstChars.length; i++) {
      if (this.treeitems[i].isVisible && char === this.firstChars[i]) {
        return i;
      }
    }
    return -1;
  }
}

class TreeItem {
  el: HTMLElement;
  groupTreeitem: TreeItem | null;
  label: string;
  isExpandable: boolean;
  isVisible: boolean;
  depth: number;
  index: number;

  private tree: TreeNavController;
  private isInGroup: boolean;

  constructor(el: HTMLElement, treeObj: TreeNavController, group: TreeItem | null) {
    el.tabIndex = -1;
    this.el = el;
    this.groupTreeitem = group;
    this.label = el.textContent?.trim() ?? '';
    this.tree = treeObj;
    this.depth = (group?.depth || 0) + 1;
    this.index = 0;

    const parent = el.parentElement;
    if (parent?.tagName.toLowerCase() === 'li') {
      parent?.setAttribute('role', 'none');
    }
    el.setAttribute('aria-level', this.depth + '');
    if (el.getAttribute('aria-label')) {
      this.label = el?.getAttribute('aria-label')?.trim() ?? '';
    }

    this.isExpandable = false;
    this.isVisible = false;
    this.isInGroup = !!group;

    let curr = el.nextElementSibling;
    while (curr) {
      if (curr.tagName.toLowerCase() == 'ul') {
        const groupId = `${group?.label ?? ''} nav group ${this.label}`.replace(/[\W_]+/g, '_');
        el.setAttribute('aria-owns', groupId);
        el.setAttribute('aria-expanded', 'false');
        curr.setAttribute('role', 'group');
        curr.setAttribute('id', groupId);
        this.isExpandable = true;
        break;
      }

      curr = curr.nextElementSibling;
    }
    this.init();
  }

  private init() {
    this.el.tabIndex = -1;
    if (!this.el.getAttribute('role')) {
      this.el.setAttribute('role', 'treeitem');
    }
    this.el.addEventListener('keydown', this.handleKeydown.bind(this));
    this.el.addEventListener('click', this.handleClick.bind(this));
    this.el.addEventListener('focus', this.handleFocus.bind(this));
    this.el.addEventListener('blur', this.handleBlur.bind(this));
  }

  isExpanded() {
    if (this.isExpandable) {
      return this.el.getAttribute('aria-expanded') === 'true';
    }

    return false;
  }

  isSelected() {
    return this.el.getAttribute('aria-selected') === 'true';
  }

  private handleClick(event: MouseEvent) {
    // only process click events that directly happened on this treeitem
    if (event.target !== this.el && event.target !== this.el.firstElementChild) {
      return;
    }
    if (this.isExpandable) {
      if (this.isExpanded() && this.isSelected()) {
        this.tree.collapseTreeitem(this);
      } else {
        this.tree.expandTreeitem(this);
      }
      event.stopPropagation();
    }
    this.tree.setSelected(this);
  }

  private handleFocus() {
    let el = this.el;
    if (this.isExpandable) {
      el = (el.firstElementChild as HTMLElement) ?? el;
    }
    el.classList.add('focus');
  }

  private handleBlur() {
    let el = this.el;
    if (this.isExpandable) {
      el = (el.firstElementChild as HTMLElement) ?? el;
    }
    el.classList.remove('focus');
  }

  private handleKeydown(event: KeyboardEvent) {
    if (event.altKey || event.ctrlKey || event.metaKey) {
      return;
    }

    let captured = false;
    switch (event.key) {
      case ' ':
      case 'Enter':
        if (this.isExpandable) {
          if (this.isExpanded() && this.isSelected()) {
            this.tree.collapseTreeitem(this);
          } else {
            this.tree.expandTreeitem(this);
          }
          captured = true;
        } else {
          event.stopPropagation();
        }
        this.tree.setSelected(this);
        break;

      case 'ArrowUp':
        this.tree.setFocusToPreviousItem(this);
        captured = true;
        break;

      case 'ArrowDown':
        this.tree.setFocusToNextItem(this);
        captured = true;
        break;

      case 'ArrowRight':
        if (this.isExpandable) {
          if (this.isExpanded()) {
            this.tree.setFocusToNextItem(this);
          } else {
            this.tree.expandTreeitem(this);
          }
        }
        captured = true;
        break;

      case 'ArrowLeft':
        if (this.isExpandable && this.isExpanded()) {
          this.tree.collapseTreeitem(this);
          captured = true;
        } else {
          if (this.isInGroup) {
            this.tree.setFocusToParentItem(this);
            captured = true;
          }
        }
        break;

      case 'Home':
        this.tree.setFocusToFirstItem();
        captured = true;
        break;

      case 'End':
        this.tree.setFocusToLastItem();
        captured = true;
        break;

      default:
        if (event.key.length === 1 && event.key.match(/\S/)) {
          if (event.key == '*') {
            this.tree.expandAllSiblingItems(this);
          } else {
            this.tree.setFocusByFirstCharacter(this, event.key);
          }
          captured = true;
        }
        break;
    }

    if (captured) {
      event.stopPropagation();
      event.preventDefault();
    }
  }
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function debounce<T extends (...args: any[]) => any>(func: T, wait: number) {
  let timeout: ReturnType<typeof setTimeout> | null;
  return (...args: Parameters<T>) => {
    const later = () => {
      timeout = null;
      func(...args);
    };
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(later, wait);
  };
}
