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

@Component({
  tag: 'hy-menu-item',
  styleUrl: 'menu-item.scss',
  shadow: true,
})
export class MenuItem {
  @Element() el: HTMLElement;
  @Event() addBreadcrumb: EventEmitter;
  @Event() menuContainerActiveTrail: EventEmitter;
  @Event() menuContainerToggled: EventEmitter;
  @Event() routeClicked: EventEmitter;
  @Prop() inActiveTrail: boolean = false;
  @Prop() isActive: boolean = false;
  @Prop() isActiveChild?: boolean = false;
  @Prop() isHeading: boolean = false;
  @Prop() isParent: boolean = false;
  @Prop() isDemo: boolean = false;
  @Prop() menuItemAlternative: boolean = false;
  @Prop() menuLinkId: string = '';
  @Prop() menuType: MenuType = MenuType.desktop;
  @Prop() menuButtonSubmenuExpand?: string = '';
  @Prop() menuButtonBreadcrumbMain?: string;
  @Prop({mutable: true}) ariaExpanded: boolean = false;
  @Prop({mutable: true, reflect: true}) depth: number = 0;
  @Prop({mutable: true}) hasChildren: boolean = null;
  @Prop({mutable: true}) label: string = '';
  @Prop({mutable: true}) parentAsHeading: string = '';
  @Prop({mutable: true, reflect: true}) parentExpanded: boolean = false;
  @Prop({mutable: true}) url: string = '';

  // Listener for submenu expand button. Listener will toggle menu level
  // container and add its parent to breadcrumbs.
  @Listen('handleClick', {capture: true}) handleClick() {
    this.menuContainerToggled.emit({
      triggerItem: this.menuLinkId,
      triggerType: 'add',
    });
    const currentParent = this.el.parentNode;

    let parentLabel = currentParent.parentElement.getAttribute('label')
      ? currentParent.parentElement.getAttribute('label')
      : this.menuButtonBreadcrumbMain;

    let isMainMenu = parentLabel == this.menuButtonBreadcrumbMain;

    this.addBreadcrumb.emit({
      url: this.url,
      label: parentLabel,
      bid: this.menuLinkId,
      isMainMenu: isMainMenu,
    });
  }

  componentWillLoad() {
    // If is-active class is added by system, add it to menu component as well.
    if (this.el.classList.contains('is-active')) {
      this.isActive = true;
    }

    // Notify breadcrumbs if item is in active trail.
    if (this.inActiveTrail) {
      const currentParent = this.el.parentNode;

      let parentLabel = currentParent.parentElement.getAttribute('label')
        ? currentParent.parentElement.getAttribute('label')
        : this.menuButtonBreadcrumbMain;
      this.addBreadcrumb.emit({
        url: this.url,
        label: parentLabel,
        bid: this.menuLinkId,
      });
    }

    // If current menu item is active, trigger all parent menuLevelContainer
    // elements in the same active-trail to open the menu.
    if (this.isActive) {
      const getParents = (elem) => {
        let parents = [];
        while (elem.parentNode && elem.parentNode.nodeName.toLowerCase() != 'hy-menu') {
          elem = elem.parentNode;
          parents.push(elem);
        }
        return parents;
      };

      const parents = getParents(this.el);
      parents.forEach((element) => {
        if (element.tagName.toLowerCase() === 'hy-menu-item') {
          this.menuContainerActiveTrail.emit({
            triggerItem: element.getAttribute('menu-link-id'),
          });
        }
      });
    }
  }

  componentWillRender() {
    // Assign depth value to current menu item instance; 1st level, 2nd level, etc.
    this.hasChildren = this.el.getElementsByTagName('hy-menu-level-container').length >= 1;
    let parentMenuItem = this.el.closest('hy-menu-item');
    let nextParentMenuItem;
    this.depth = 0;
    while (parentMenuItem) {
      nextParentMenuItem = parentMenuItem.parentElement.closest('hy-menu-item');
      if (nextParentMenuItem === parentMenuItem) {
        break;
      } else {
        if (nextParentMenuItem !== null) {
          this.parentAsHeading = nextParentMenuItem;
        }
        parentMenuItem = nextParentMenuItem;
        this.depth = this.depth + 1;
      }
    }
  }

  render() {
    switch (this.menuType) {
      case MenuType.desktop:
        return (
          <Host
            class={{
              'is-active': this.isActive,
              'hy-menu-item': true,
              'hy-menu-item--alternative': this.menuItemAlternative,
              'hy-menu-item--desktop': true,
              'is-demo': this.isDemo,
            }}
          >
            <a
              aria-current={this.isHeading.toString()}
              href={this.url}
              class={{
                'is-active': this.isActive,
                'in-active-trail': this.inActiveTrail,
                'is-heading': this.isHeading,
                'hy-menu-item--desktop': true,
                'is-demo': this.isDemo,
              }}
            >
              {this.depth == 1 && (
                <span class="hy-menu-item__heading__icon">
                  <hy-icon icon={'hy-icon-arrow-right'} size={40} />
                </span>
              )}
              {this.depth == 2 && (
                <span class="hy-menu-item__heading__icon">
                  <hy-icon icon={'hy-icon-caret-right'} size={12} />
                </span>
              )}
              <span class={'hy-menu-item__label'}>{this.label}</span>
            </a>
            {this.hasChildren && <slot />}
          </Host>
        );
      case MenuType.mobile:
        return (
          <Host
            class={{
              'is-active': this.isActive,
              'hy-menu-item': true,
              'hy-menu-item--alternative': this.menuItemAlternative,
              'hy-menu-item--mobile': true,
              'is-demo': this.isDemo,
            }}
          >
            <a
              aria-current={this.isHeading.toString()}
              href={this.url}
              class={{
                'is-active': this.isActive,
                'in-active-trail': this.inActiveTrail,
                'is-heading': this.isHeading,
                'hy-menu-item--mobile': true,
                'is-demo': this.isDemo,
                first: this.depth == 1,
              }}
            >
              <span class={'hy-menu-item__label'}>{this.label}</span>
            </a>

            {this.hasChildren && (
              <button
                aria-haspopup={'true'}
                aria-label={`Open submenu for ${this.label}`}
                onClick={() => this.handleClick()}
                class={'hy-menu-item__button'}
              >
                <hy-icon icon={'hy-icon-caret-right'} size={14} />
              </button>
            )}

            {this.hasChildren && <slot />}
          </Host>
        );

      case MenuType.sidenav:
        let classAttributes = [
          'hy-menu-item--sidenav',
          this.isDemo ? 'is-demo' : '',
          this.isActive ? 'is-active' : '',
          this.isParent ? 'is-parent' : '',
          this.isActiveChild ? 'is-active--child' : '',
          this.inActiveTrail ? 'in-active-trail' : '',
          this.depth != null ? 'hy-menu-item--level-' + this.depth : '',
          this.isActive && this.hasChildren ? 'is-active--heading' : '',
        ];
        let anchorClassAttributes = [...classAttributes, this.isHeading ? 'is-heading' : ''];
        classAttributes = [...classAttributes, 'hy-menu-item'];
        return (
          <li class={classAttributes.join(' ')}>
            <a class={anchorClassAttributes.join(' ')} href={this.url}>
              {this.label}
            </a>

            {this.hasChildren && <slot />}
          </li>
        );
    }
  }
}