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

@Component({
  tag: 'hy-menu-sidebar',
  styleUrl: 'menu-sidebar.scss',
  shadow: false,
})
export class MenuSidebar {
  @Element() el: HTMLElement;
  /**
   * Is menu open boolean.
   */
  @Prop() menuIsOpen = false;
  /**
   * Menu type. Defaults to sidenav.
   */
  @Prop() menuType: MenuType = MenuType.sidenav;
  /**
   * Upper menus panel boolean.
   */
  @Prop() panelOpen = false;
  /**
   * Label for panel toggle button.
   */
  @Prop() panelToggleLabel?: string;
  /**
   * Label for panel toggle button.
   */
  @Prop() panelToggleAriaLabel?: string;
  /**
   * Label for panel toggle button.
   */
  @Prop() panelToggleCloseLabel?: string;
  /**
   * Label for panel toggle button.
   */
  @Prop() panelToggleCloseAriaLabel?: string;
  /**
   * Url for logo.
   */
  @Prop() logoUrl?: string;
  /**
   * Logo label
   */
  @Prop() logoLabel?: string;
  /**
   * Logo size
   */
  @Prop() size: SiteLogoSize = SiteLogoSize.big;
  /**
   * Isdemo
   */
  @Prop() isDemo: boolean = false;
  /**
   * Previous panel to be toggled to keep track.
   */
  @Prop({mutable: true}) minHeight: any = null;
  @State() previousPanel: HTMLElement;
  /**
   * Previous item to be toggle to keep track.
   */
  @State() previousItem;
  //@State() previousItem: HTMLElement;

  @Listen('panelToggle') panelToggle(e) {
    if (this.menuIsOpen) {
      this.closeWholeTree();
      const body = document.querySelector('body') as HTMLElement;

      this.panelOpen = !this.panelOpen;
      this.panelOpen
        ? body.classList.add('hy-menu-sidepanel__no-scroll')
        : body.classList.remove('hy-menu-sidepanel__no-scroll');
    } else {
      this.panelOpen = !this.panelOpen;
      const body = document.querySelector('body') as HTMLElement;
      this.panelOpen
        ? body.classList.add('hy-menu-sidepanel__no-scroll')
        : body.classList.remove('hy-menu-sidepanel__no-scroll');
    }

    e.preventDefault();
    e.stopPropagation();
  }

  componentWillLoad() {
    const sideBar = document.querySelector('.layout-sidebar-first');
    if (sideBar) {
      if (this.menuIsOpen) {
        sideBar.classList.add('menu-is-open');
      } else if (sideBar.classList.contains('menu-is-open')) {
        sideBar.classList.remove('menu-is-open');
      }
    }
  }

  componentDidLoad() {
    const sidebarContainer = document.querySelector('.hy-menu-sidebar--container');
    if (sidebarContainer) {
      sidebarContainer.addEventListener('click', (e) => {
        if ((e.target as HTMLElement).classList.contains('sidebar-open')) {
          this.closeWholeTree();
        }
      });
    }
    const sidepanelContainer = document.querySelector('.hy-menu-sidepanel--container');
    if (sidepanelContainer) {
      sidepanelContainer.addEventListener('click', (e) => {
        if ((e.target as HTMLElement).classList.contains('sidepanel-open')) {
          this.panelToggle(e);
        }
      });
    }

    const panels = document.querySelectorAll('.hy-menu-level-container');
    if (panels) {
      const height = Math.max.apply(
        Math,
        [...panels].map((panel) => panel.scrollHeight)
      );
      this.minHeight = height;
    }
  }

  componentWillUpdate() {
    const sideBar = document.querySelector('.layout-sidebar-first');

    if (this.menuIsOpen) {
      sideBar.classList.add('menu-is-open');
    } else if (sideBar.classList.contains('menu-is-open')) {
      sideBar.classList.remove('menu-is-open');
    }
  }

  @Listen('click')
  handlePanel(e) {
    const target = e.target;

    const targetElement = target.tagName.toLowerCase();
    const possibleTags = [targetElement].some((r) => ['svg', 'path'].indexOf(r) >= 0);

    if (target.classList.contains('hy-menu-item__label__icon') || possibleTags) {
      const menuItem = target.closest('.hy-menu-item-sidebar');
      const menuItemId = menuItem.getAttribute('data-link-id');
      const menuItemLevel = menuItem.getAttribute('item-level');
      const menuPanel = menuItem.closest('.hy-menu-level-container');
      const childList = menuItem.querySelector('.hy-menu-level-container');

      // If no previous, as in first time clicking menu
      if (!this.previousPanel) {
        this.updatePrevious(menuPanel, menuItem);
        this.togglePanel(menuItem, childList);
        return;
      }

      const prevId = this.previousItem.dataset.linkId;
      const prevLevel = this.previousItem.getAttribute('item-level');

      // If clicking same menu item again.
      if (menuItemId === prevId) {
        if (menuItem.classList.contains('is-active-item')) {
          this.togglePanel(menuItem, childList, true);
          if (menuItemLevel == 1) {
            this.menuIsOpen = false;
          }
        } else {
          this.togglePanel(menuItem, childList);
        }
        return;
      }

      // If clicking menu item on same level or going back up
      if (menuItemLevel <= prevLevel) {
        // If clicking already active, close children
        if (menuItem.classList.contains('is-active-item')) {
          this.togglePanel(menuItem, childList, true);
          this.updatePrevious(menuPanel, menuItem);
          return;
        }
        // Close previous panels
        this.togglePanel(this.previousItem, menuPanel, true);
        // Open newly clicked panel
        this.togglePanel(menuItem, childList);
        // Update previous
        this.updatePrevious(menuPanel, menuItem);
      } else if (menuItemLevel > prevLevel) {
        this.togglePanel(menuItem, childList);
        this.updatePrevious(menuPanel, menuItem);
      }
    }
    e.stopImmediatePropagation();
    e.stopPropagation();
  }

  updatePrevious(panel, item) {
    this.previousPanel = panel;
    this.previousItem = item;
  }

  closeWholeTree() {
    const sidebarLevel1 = document.querySelector('.hy-menu-level-container--level-1') as HTMLElement;
    const firstItem = document.querySelector(
      '.hy-menu-item-sidebar--sidenav.hy-menu-item--level-1.is-active-item'
    ) as HTMLElement;
    this.togglePanel(firstItem, sidebarLevel1, true);
    const body = document.querySelector('body') as HTMLElement;
    const container = document.querySelector('.hy-menu-sidebar--container') as HTMLElement;

    if (container.classList.contains('sidebar-open') && firstItem) {
      container.classList.remove('sidebar-open');
      body.classList.remove('hy-menu-sidebar__no-scroll');
    }
  }

  togglePanel(menuItem, panel, shouldClose = false) {
    const buttonElement = menuItem.querySelector('button');
    const level = menuItem.getAttribute('item-level');
    if (level == 1 && !this.menuIsOpen) {
      if (window.pageYOffset > 50 && !this.isDemo) {
        window.scrollTo({top: 0});
      }
      this.menuIsOpen = true;
    }
    if (shouldClose) {
      const children = panel.querySelectorAll('.hy-menu-item-sidebar');
      const activeChild = [...children].filter((c) => c.classList.contains('is-active-item'));
      if (level == 1 && activeChild) {
        this.menuIsOpen = false;
      }
      if (activeChild.length > 0) {
        for (let i = 0; i < activeChild.length; i++) {
          const element = activeChild[i];
          this.closeChildren(element);
        }
      }
      buttonElement.setAttribute('aria-expanded', 'false');
      this.closeChildren(menuItem);
      //this.menuIsOpen = level == 1 ? true : false;
      return;
    }
    buttonElement.setAttribute('aria-expanded', 'true');
    panel.classList.add('is-open');
    menuItem.classList.add('is-active-item');
  }

  closeChildren(menuItem) {
    if (menuItem.classList.contains('is-active-item')) {
      menuItem.classList.remove('is-active-item');
    }
    if (menuItem.classList.contains('has-children')) {
      const menuButton = menuItem.querySelector('button');
      menuButton.setAttribute('aria-expanded', 'false');
      const childList = menuItem.querySelector('.hy-menu-level-container');
      childList.classList.remove('is-open');
      const childItems = childList.querySelectorAll('.hy-menu-item-sidebar');
      if (childList.classList.contains('is-active')) {
        childList.classList.remove('is-active');
      }
      childItems.forEach((element) => {
        element.classList.remove('is-active-item');
        if (element.classList.contains('has-children')) {
          const menuButton = element.querySelector('button');
          menuButton.setAttribute('aria-expanded', 'false');
          this.closeChildren(element);
        } else {
          return;
        }
      });
    }
  }

  render() {
    const logoColor = ColorVariant.black;
    const panelClassAttributes = ['hy-menu-sidepanel--container', this.panelOpen ? 'sidepanel-open' : ''].join(' ');
    switch (this.menuType) {
      case MenuType.sidepanel:
        return (
          <div
            class="hy-menu-sidebar__container"
            style={{
              '--minHeight': `${this.minHeight}px` as 'minHeight',
            }}
          >
            <button
              aria-label={this.panelToggleAriaLabel}
              class="hy-menu-sidebar__panel-toggle"
              onClick={(e) => this.panelToggle(e)}
            >
              <hy-icon icon={'hy-icon-caret-left'} fill={'currentColor'} size={10} />
              <hy-icon icon={'hy-icon-caret-left'} fill={'currentColor'} size={10} />

              {this.panelToggleLabel}
            </button>
            <div
              class={panelClassAttributes}
              aria-hidden={this.panelOpen ? 'false' : 'true'}
              aria-expanded={this.panelOpen ? 'true' : 'false'}
            >
              <div class="hy-menu-sidepanel__nav-container">
                <div class="hy-menu-sidepanel__logo-container">
                  <div
                    class="hy-menu-sidepanel__logo"
                    aria-hidden={this.panelOpen ? 'false' : 'true'}
                    tabindex={this.panelOpen ? '0' : '-1'}
                  >
                    <hy-site-logo size={56} color={logoColor} url={this.logoUrl} label={this.logoLabel} />
                  </div>
                  <button
                    aria-label={this.panelToggleCloseAriaLabel}
                    aria-hidden={this.panelOpen ? 'false' : 'true'}
                    tabindex={this.panelOpen ? '0' : '-1'}
                    class="hy-menu-sidebar__panel-toggle"
                    onClick={(e) => this.panelToggle(e)}
                  >
                    <hy-icon icon={'hy-icon-remove'} fill={'currentColor'} size={10} />

                    {this.panelToggleCloseLabel}
                  </button>
                </div>
                <nav
                  role={'navigation'}
                  aria-hidden={this.panelOpen ? 'false' : 'true'}
                  tabindex={this.panelOpen ? '0' : '-1'}
                  class={{
                    'hy-menu': true,
                    'hy-menu-sidepanel': true,
                    'is-demo': this.isDemo,
                  }}
                >
                  <slot />
                </nav>
              </div>
            </div>
          </div>
        );

      case MenuType.sidenav:
        return (
          <div
            class="hy-menu-sidebar--container"
            style={{
              '--minHeight': `${this.minHeight}px` as 'minHeight',
            }}
          >
            <div class="hy-menu-sidebar__logo">
              <hy-site-logo size={56} color={logoColor} url={this.logoUrl} label={this.logoLabel} />
            </div>
            <button
              aria-label={this.panelToggleAriaLabel}
              class="hy-menu-sidebar__panel-toggle"
              onClick={(e) => this.panelToggle(e)}
            >
              <hy-icon icon={'hy-icon-caret-left'} fill={'currentColor'} size={10} />
              <hy-icon icon={'hy-icon-caret-left'} fill={'currentColor'} size={10} />

              {this.panelToggleLabel}
            </button>
            <nav
              role={'navigation'}
              aria-hidden={this.menuIsOpen ? 'false' : 'true'}
              class={{
                'hy-menu': true,
                'hy-menu-sidebar': true,
                'is-demo': this.isDemo,
              }}
            >
              <slot />
            </nav>
          </div>
        );
    }
  }
}