/**
 * @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.handleResize();
    window.addEventListener('resize', this.handleResize);
    this.findTreeItems();
    this.updateVisibleTreeitems();
    this.observeTargets();
    if (this.firstTreeitem) {
      this.firstTreeitem.el.tabIndex = 0;
    }
  }

  private handleResize = (): void => {
    this.el.style.setProperty('--js-tree-height', '100vh');
    this.el.style.setProperty('--js-tree-height', this.el.clientHeight + 'px');
  };

  private observeTargets() {
    this.addObserver(treeitem => {
      this.expandTreeitem(treeitem);
      this.setSelected(treeitem);
      // TODO: Fix scroll issue in https://golang.org/issue/47450.
      // treeitem.el.scrollIntoView({ block: 'nearest' });
    });

    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);
  };
}
