import {Component, Element, h, Host, Listen, Prop, State} from '@stencil/core';
import {MenuType} from '../../../utils/utils';

@Component({
  tag: 'hy-menu-level-container',
  styleUrl: 'menu-level-container.scss',
  shadow: false,
})
export class MenuLevelContainer {
  @Element() el: HTMLElement;
  @Prop() labelFrontPage?: string;
  @Prop() menuButtonSubmenuExpand?: string;
  @Prop() menuLevel: number;
  @Prop() menuType: MenuType = MenuType.mobile;
  @Prop({reflect: true}) activeTrailTriggered: boolean = false;
  @Prop({mutable: true, reflect: true}) depth: number = 0;
  @Prop({mutable: true}) headingItem: any;
  @Prop({mutable: true, reflect: true}) triggerItem: string;
  @State() menuIsOpen: boolean = false;

  // Add/Remove is-hidden class from each upper level menu-items
  // to make browsing more accessible.
  assignMenuItemClass(parentMenu: Element, type: string) {
    const items = Array.from(parentMenu.children);
    items.forEach((item) => {
      if (type === 'remove') {
        item.classList.remove('is-hidden');
      } else {
        item.classList.add('is-hidden');
      }
    });
  }
  // Listener for assigning active-trail for parent menu level container.
  @Listen('menuContainerActiveTrail', {target: 'document', capture: true})
  menuContainerActiveTrail(data) {
    const currentMenuContainer = this.el.getAttribute('trigger-item');
    if (currentMenuContainer === data.detail.triggerItem) {
      this.activeTrailTriggered = true;
      this.menuIsOpen = true;
      this.assignMenuItemClass(this.el.parentElement.closest('hy-menu-level-container'), 'add');
    }
  }

  // Listener for opening and closing menu level container.
  @Listen('menuContainerToggled', {target: 'document', capture: true})
  menuContainerToggled(data) {
    // Toggle submenu.
    if (this.triggerItem == data.detail.triggerItem) {
      this.activeTrailTriggered = false;
      this.menuIsOpen = data.detail.triggerType != 'remove';
      this.assignMenuItemClass(this.el.parentElement.closest('hy-menu-level-container'), data.detail.triggerType);

      // Scroll to .hy-menu top.
      let hyMenu = this.el.parentElement.closest('hy-menu');
      hyMenu.shadowRoot.querySelector('.hy-menu').scrollTop = 0;
    }
  }

  componentWillUpdate() {
    // Pass the menu type and menu-button-submenu-expand attributes to
    // the child menu item component.
    if (this.menuType) {
      const items = Array.from(this.el.children);
      items.forEach((item) => {
        item.setAttribute('menu-type', this.menuType);
        item.setAttribute('menu-button-submenu-expand', this.menuButtonSubmenuExpand);
      });
    }
  }

  componentWillRender() {
    // Assign depth value to current menu level container instance;
    // 1st level, 2nd level, etc.
    let parentMenu = this.el.closest('hy-menu-level-container');
    let nextParentMenu;
    this.depth = 0;
    while (parentMenu) {
      nextParentMenu = parentMenu.parentElement.closest('hy-menu-level-container');
      if (nextParentMenu === parentMenu) {
        break;
      } else {
        parentMenu = nextParentMenu;
        this.depth = this.depth + 1;
      }
    }

    // Set trigger item for each mobile menu level container and handle only submenus.
    // Add a heading element foreach level.
    if (this.menuType === MenuType.mobile) {
      if (this.menuLevel > 1) {
        const parentMenuItem = this.el.closest('hy-menu-item');
        this.triggerItem = parentMenuItem.getAttribute('menu-link-id');
        this.headingItem = {
          ...this.headingItem,
          url: parentMenuItem.getAttribute('url'),
        };
        this.headingItem = {
          ...this.headingItem,
          label: parentMenuItem.getAttribute('label'),
        };
        this.headingItem = {
          ...this.headingItem,
          isActive: window.location.pathname === this.headingItem.url,
        };
      } else {
        this.triggerItem = 'home';
      }
    }

    // Set is-active-child and menu-level attributes to all sibling menu-items.
    if (this.menuType === MenuType.sidenav) {
      const parentMenuItem = this.el.closest('hy-menu-item');
      if (parentMenuItem && parentMenuItem.classList.contains('is-active')) {
        this.menuIsOpen = true;
        const items = Array.from(this.el.children);
        items.forEach((item) => {
          item.setAttribute('is-active-child', 'true');
          item.setAttribute('menu-level', this.menuLevel.toString());
        });
      }
    }
  }

  render() {
    let classAttributes = ['hy-menu-level-container', 'hy-menu-level-container--level-' + this.depth];

    switch (this.menuType) {
      case MenuType.desktop:
        classAttributes = [...classAttributes, 'hy-menu-level-container--desktop'];
        //menu-type="sidenav"

        return (
          <Host class={classAttributes.join(' ')} menu-type="desktop">
            <slot />
          </Host>
        );

      case MenuType.mobile:
        classAttributes = [...classAttributes, 'hy-menu-level-container--mobile'];
        if (this.depth === 1) {
          classAttributes = [...classAttributes, 'is-open'];

          return (
            <Host aria-expanded={this.menuIsOpen.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
              <slot />
            </Host>
          );
        } else {
          classAttributes = [...classAttributes, this.menuIsOpen ? 'is-open' : null];

          return (
            <Host aria-expanded={this.menuIsOpen.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
              <hy-menu-item
                label={this.headingItem.label}
                url={this.headingItem.url}
                isHeading={true}
                isActive={this.headingItem.isActive}
                menu-type={'mobile'}
              />
              <slot />
            </Host>
          );
        }
      case MenuType.sidenav:
        classAttributes = [...classAttributes, 'hy-menu-level-container--sidenav'];

        if (this.depth === 1) {
          classAttributes = [...classAttributes, 'is-open'];

          return (
            <Host aria-expanded={this.menuIsOpen.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
              <slot />
            </Host>
          );
        } else {
          classAttributes = [...classAttributes, this.menuIsOpen ? 'is-open' : null];

          return (
            <Host aria-expanded={this.menuIsOpen.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
              <slot />
            </Host>
          );
        }
    }
  }
}