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

// import {MenuItemVariants} 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({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;
    this.addBreadcrumb.emit({
      url: this.url,
      label: currentParent.parentElement.getAttribute('label'),
      bid: this.menuLinkId,
    });
  }

  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 && !this.isActive) {
      const currentParent = this.el.parentNode;
      this.addBreadcrumb.emit({
        url: this.url,
        label: currentParent.parentElement.getAttribute('label'),
        bid: this.menuLinkId,
      });

      if (this.menuType === MenuType.sidenav) {
        this.el.children[0].setAttribute('class', 'is-open');
      }
    }

    // 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'),
          });
        }
      });

      // If side navigation menu item has is-active state, prepare the menu items
      // for the last children.
      if (this.menuType === MenuType.sidenav) {
        parents.forEach((element) => {
          if (element.tagName.toLowerCase() === 'hy-menu-item') {
            element.classList.add('is-hidden--child');
          }
        });

        // If current active menu item have children, set the child
        // menu-level-container open.
        if (this.el.children.length > 0) {
          this.el.children[0].setAttribute('class', 'is-open');
        }
        // If current active menu item does not have any children, mock the
        // current menu item and parent menu item to behave like there would
        // be child menu items available.
        else {
          const parentMenuItem = this.el.parentElement.closest('hy-menu-item');
          const parentMenuItemAnchor = parentMenuItem.shadowRoot.querySelector('a.hy-menu-item--sidenav');
          parentMenuItem.classList.remove('is-hidden--child');
          parentMenuItemAnchor.classList.add('is-active--heading');
          const menuItemSiblings = Array.prototype.slice.call(this.el.closest('hy-menu-level-container').children);
          menuItemSiblings.forEach((element) => {
            if (element.tagName.toLowerCase() === 'hy-menu-item') {
              element.classList.add('is-active--child');
            }
          });
        }
      }
    }
  }

  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,
              }}
            >
              <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 this.isParent ? (
          <Host class={classAttributes.join(' ')}>
            <a href={this.url} class={anchorClassAttributes.join(' ')}>
              <span class={'hy-menu-item__label__icon'}>
                <hy-icon icon={'hy-icon-arrow-left'} fill={'currentColor'} size={18} />
              </span>
              <span class={'hy-menu-item__label'}>{this.label}</span>
            </a>
          </Host>
        ) : (
          <Host class={classAttributes.join(' ')}>
            <a aria-current={this.isHeading.toString()} href={this.url} class={anchorClassAttributes.join(' ')}>
              <span class={'hy-menu-item__label'}>{this.label}</span>
              {this.hasChildren && (
                <span class={'hy-menu-item__label__icon'}>
                  <hy-icon icon={'hy-icon-caret-right'} fill={'currentColor'} size={12} />
                </span>
              )}
            </a>
            {this.hasChildren && <slot />}
          </Host>
        );
    }
  }
}