export interface ShortcutLinks {
  shortcut_title: string;
  shortcut_url: string;
  shortcut_is_external: string;
  shortcut_aria_label: string;
}

export interface DesktopLinks {
  label: string;
  labelExtra: string;
  url: string;
  description: string;
  menuLinkId: string;
  isActive: string;
  shortcutsTitle: string;
  closeButtonTitle: string;
  items: Array<DesktopLinks>;
  shortcuts: Array<ShortcutLinks>;
}

import {ColorVariant} from '../../../utils/utils';
import {Component, h, Element, Prop, State, Watch} from '@stencil/core';

@Component({
  tag: 'hy-desktop-menu-links',
  styleUrl: 'hy-desktop-menu-links.scss',
  shadow: true,
})
export class HyDesktopMenuLinks {
  @Element() el: HTMLElement;
  /*
  First level menu links to be displayed on Desktop screens.
  * */
  @Prop() dataDesktopLinks: DesktopLinks[] | string;
  private _dataDesktopLinks: DesktopLinks[];
  @State() firstLevelLinksList: Array<object> = [];
  @State() menuLinkItems: Array<object> = [];
  @State() hasToolbar: boolean = false;
  @State() isDesktopMenuOpen: boolean = false;

  private _submenuLeftMargin: number = 32;
  private _headerBorderOffset: number = 8;

  @Watch('dataDesktopLinks')
  dataDesktopLinksWatcher(data: DesktopLinks[] | string) {
    this._dataDesktopLinks = typeof data === 'string' ? JSON.parse(data) : data;
  }

  componentWillLoad() {
    this.dataDesktopLinksWatcher(this.dataDesktopLinks);
  }

  showBackdropShadow(state = 'close', top = 0) {
    let hyHeader = this.el.closest('.hy-site-header') as HTMLElement;
    let hyBackdropDiv = hyHeader.children[0] as HTMLElement;

    if (hyBackdropDiv) {
      if (state === 'open') {
        hyBackdropDiv.classList.add('is-active');
        hyBackdropDiv.style.top = `${top}px`;
      }

      if (state === 'close') {
        hyBackdropDiv.classList.remove('is-active');
        hyBackdropDiv.style.top = '0';
      }
    }
  }

  handleDesktopMenuClose() {
    this.isDesktopMenuOpen = false;
    this.showBackdropShadow();

    const menuItems = this.el.shadowRoot.querySelectorAll(`.desktop-menu-link`);
    const menuPanelItems = this.el.shadowRoot.querySelectorAll('.hy-desktop-menu-panel');
    const activeMenuItem = this.el.shadowRoot.querySelector(`.desktop-menu-link[aria-expanded="true"]`) as HTMLElement;

    // Return focus to the button of the last desktop panel that was active.
    if (activeMenuItem !== null) activeMenuItem.focus();

    // Reset elements by removing the active classes.
    menuItems.forEach((item) => {
      item.classList.remove('desktop-menu-link--is-active');
      item.setAttribute('aria-expanded', 'false');
    });
    menuPanelItems.forEach((item) => {
      item.classList.remove('hy-desktop-menu-panel--is-active');
      item.setAttribute('aria-hidden', 'true');
    });
  }

  handleDesktopMenuToggle(id) {
    this.isDesktopMenuOpen = true;
    const menuItems = this.el.shadowRoot.querySelectorAll(`.desktop-menu-link`);
    const menuPanelItems = this.el.shadowRoot.querySelectorAll('.hy-desktop-menu-panel'); // all panels
    const activeMenuItem = this.el.shadowRoot.querySelector(`.desktop-menu-link[link-id="${id}"]`) as HTMLElement;
    const activeMenuItemSibling = activeMenuItem.nextElementSibling as HTMLElement; // current panel

    // Reset elements by removing the active classes.
    menuItems.forEach((item) => {
      item.classList.remove('desktop-menu-link--is-active');
      item.setAttribute('aria-expanded', 'false');
    });
    menuPanelItems.forEach((item) => {
      item.classList.remove('hy-desktop-menu-panel--is-active');
      item.setAttribute('aria-hidden', 'true');
    });

    // Add active classes to the currently active item and its sibling element.
    activeMenuItem.classList.add('desktop-menu-link--is-active');
    activeMenuItem.setAttribute('aria-expanded', 'true');
    activeMenuItemSibling.classList.add('hy-desktop-menu-panel--is-active');
    if (this.hasToolbar) {
      activeMenuItemSibling.classList.add('hy-desktop-menu-panel--is-active--has-toolbar');
    }
    activeMenuItemSibling.setAttribute('aria-hidden', 'false');

    // Add panels top value automatically with the correct header height
    const headerHeight = `${
      this.el.parentElement.offsetTop + this.el.parentElement.offsetHeight + this._headerBorderOffset
    }px`;
    activeMenuItemSibling.style.top = headerHeight;

    // Add shadow backdrop
    let rect = activeMenuItemSibling.getBoundingClientRect();
    this.showBackdropShadow('open', rect.bottom);

    // Position submenu block under the activated top menu item.
    let activeButtonRect = activeMenuItem.getBoundingClientRect();
    const menuPanelLeftPosition = activeButtonRect.left - this._submenuLeftMargin;
    activeMenuItemSibling.style.paddingLeft = `${menuPanelLeftPosition}px`;

    // Position shortcuts block.
    let shortcutsDiv = activeMenuItemSibling.querySelectorAll('ul.shortcuts-panel')[0] as HTMLElement; // shortcuts block
    if (shortcutsDiv) {
      let subMenuDiv = activeMenuItemSibling.querySelectorAll(
        '.hy-desktop-menu-panel__desktop-menu__menu-items'
      )[0] as HTMLElement; // 2nd level menu block

      let spaceLeftAfterSubmenu = subMenuDiv.getBoundingClientRect().right + shortcutsDiv.offsetWidth;
      if (spaceLeftAfterSubmenu >= document.body.scrollWidth) {
        // Shortcuts should be placed to the left.
        let shortcutsLeftPosition = subMenuDiv.getBoundingClientRect().left - shortcutsDiv.offsetWidth;
        shortcutsDiv.style.left = shortcutsLeftPosition.toString().concat('px');
      } else {
        // Shortcuts should be placed to the right.
        let shortcutsLeftPosition = subMenuDiv.getBoundingClientRect().right;
        shortcutsDiv.style.left = shortcutsLeftPosition.toString().concat('px');
      }
    }
  }

  handleDesktopMenuClick(id) {
    const activeMenuItem = this.el.shadowRoot.querySelector(`.desktop-menu-link[link-id="${id}"]`);
    const activeMenuItemSibling = activeMenuItem.nextElementSibling as HTMLElement; // current panel

    if (!this.isDesktopMenuOpen) {
      // Add active classes to the currently active item and its sibling element.
      this.isDesktopMenuOpen = true;
      activeMenuItem.classList.add('desktop-menu-link--is-active');
      activeMenuItem.setAttribute('aria-expanded', 'true');
      activeMenuItemSibling.classList.add('hy-desktop-menu-panel--is-active');

      if (this.hasToolbar) {
        activeMenuItemSibling.classList.add('hy-desktop-menu-panel--is-active--has-toolbar');
      }
      activeMenuItemSibling.setAttribute('aria-hidden', 'false');

      let rect = activeMenuItemSibling.getBoundingClientRect();
      this.showBackdropShadow('open', rect.bottom);
    } else {
      // Remove active classes to the currently active item and its sibling element.
      this.isDesktopMenuOpen = false;
      activeMenuItem.classList.remove('desktop-menu-link--is-active');
      activeMenuItem.setAttribute('aria-expanded', 'false');
      activeMenuItemSibling.classList.remove('hy-desktop-menu-panel--is-active');
      if (this.hasToolbar) {
        activeMenuItemSibling.classList.remove('hy-desktop-menu-panel--is-active--has-toolbar');
      }

      activeMenuItemSibling.setAttribute('aria-hidden', 'true');

      this.showBackdropShadow();
    }
  }

  componentDidLoad() {
    let hyToolbar = document.querySelectorAll('#toolbar-administration')[0];
    if (hyToolbar) {
      this.hasToolbar = true;
    }

    const links = this._dataDesktopLinks as Array<DesktopLinks>;

    let menuLinkItems = [];

    links.map(
      ({
        menuLinkId: id,
        shortcuts,
        items,
        url,
        description,
        label,
        labelExtra,
        isActive,
        shortcutsTitle,
        closeButtonTitle,
      }) => {
        let classAttributes = [
          'desktop-menu-link',
          isActive === 'true' ? 'desktop-menu-link--is-active-trail' : '',
        ].join(' ');

        menuLinkItems.push(
          <li>
            <button
              type="button"
              class={classAttributes}
              link-id={id}
              onClick={() => this.handleDesktopMenuClick(id)}
              onMouseOver={() => this.handleDesktopMenuToggle(id)}
              onFocus={() => this.handleDesktopMenuToggle(id)}
              aria-expanded="false"
            >
              {label}
              <span class="desktop-menu-link__heading__icon">
                <hy-icon icon={'hy-icon-caret-down'} size={32} />
              </span>
            </button>
            <div class="hy-desktop-menu-panel" onMouseLeave={() => this.handleDesktopMenuClose()} aria-hidden="true">
              <div class="hy-desktop-menu-panel__desktop-menu">
                <div class="hy-desktop-menu-panel__desktop-menu__menu-items">
                  <a
                    aria-current={label}
                    href={url}
                    class="hy-desktop-menu-panel__desktop-menu__first-level-menu-item"
                    menu-link-id={id}
                  >
                    <span class="heading-icon">
                      <hy-icon icon={'hy-icon-arrow-right'} size={40} />
                    </span>
                    {labelExtra ? <span class="label">{labelExtra}</span> : <span class="label">{label}</span>}
                    {description && <span class="description">{description}</span>}
                  </a>
                  <ul class={'hy-desktop-menu-panel__desktop-menu__second-level-menu'} menu-link-id={id}>
                    {items.map(({label, url}) => (
                      <li>
                        <a href={url}>
                          <span class="heading-icon">
                            <hy-icon icon={'hy-icon-caret-right'} size={12} />
                          </span>
                          <span class="label">{label}</span>
                        </a>
                      </li>
                    ))}
                  </ul>
                </div>
                {shortcuts.length > 0 && (
                  <ul class="shortcuts-panel">
                    <h2 class="shortcuts-panel__title">{shortcutsTitle}</h2>
                    {shortcuts.map(
                      ({shortcut_title, shortcut_url, shortcut_is_external, shortcut_aria_label}, index) => {
                        let target = shortcut_is_external ? '_blank' : '_self';

                        let shortcutClass = [
                          'shortcuts-panel__shortcut-item',
                          index == 0 ? 'shortcuts-panel__shortcut-item__first' : '',
                        ].join(' ');

                        return (
                          <li class={shortcutClass}>
                            <a
                              aria-current={shortcut_aria_label}
                              href={shortcut_url}
                              class="shortcut-item__link"
                              target={target}
                              aria-label={shortcut_aria_label}
                            >
                              <span class="label">{shortcut_title}</span>
                              <span class="icon">
                                <hy-icon icon={'hy-icon-arrow-right'} size={24} />
                              </span>
                            </a>
                          </li>
                        );
                      }
                    )}
                  </ul>
                )}
              </div>
              <button
                onClick={() => this.handleDesktopMenuClose()}
                class={{
                  'hy-desktop-menu-panel__panel-toggle': true,
                }}
                aria-label="Close menu"
              >
                <span class="hy-desktop-menu-panel__panel-toggle__label">
                  <span class="hy-desktop-menu-panel__panel-toggle__label__title">{closeButtonTitle}</span>
                  <hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.black} />
                </span>
              </button>
            </div>
          </li>
        );
      }
    );

    this.menuLinkItems = menuLinkItems;
  }

  render() {
    return (
      <nav role={'navigation'} class="hy-site-header__menu-desktop">
        <ul class="hy-site-header__menu-desktop-container">{this.menuLinkItems}</ul>
      </nav>
    );
  }
}