export interface DesktopLinks {
  label: string;
  url: string;
  menuLinkId: string;
}
export interface DonateLink {
  url: string;
  label: string;
}
export interface ComponentLabels {
  open: string;
  close: string;
  expand?: string;
  label?: string;
}

import {Component, Element, Event, EventEmitter, h, Listen, Prop, State} from '@stencil/core';
import ResizeObserver from 'resize-observer-polyfill';
import {MenuType, ColorVariant, SiteLogoSize} from '../../utils/utils';

@Component({
  tag: 'hy-site-header',
  styleUrl: 'site-header.scss',
  shadow: true,
})
export class SiteHeader {
  @Element() el: HTMLElement;
  @Prop() isGroup: boolean = false;
  @Prop() dataMenuLanguage: string;
  @Prop() dataMenuDonate: string;
  @Prop() dataSiteHeaderLabels: string;
  @Prop() dataSiteSearchLabels: string;
  @Prop() logoUrl?: string;
  @Prop() logoLabel?: string;
  @Prop() siteLabel?: string;
  @Prop() siteUrl?: string;
  @Prop() menuLabel: string = 'Menu';
  @Prop() menuLabelOpen?: string;
  @Prop() menuLabelClose?: string;
  @Prop({reflect: true}) menuType: MenuType = MenuType.default;
  /*
  First level menu links to be displayed on Desktop screens.
  * */
  @Prop() dataDesktopLinks: DesktopLinks[] | string;
  @Prop() dataMainMenuLinks: DesktopLinks[] | string;
  @Prop() dataSearchTools: DesktopLinks[] | string;

  @State() isMobile: boolean;
  @State() isMenuOpen: boolean = false;
  @State() isDesktopMenuOpen: boolean = false;

  @Event() headerScrollUp: EventEmitter;
  @Event() headerScrollDown: EventEmitter;
  @Event() menuMobileToggled: EventEmitter;

  private ro: ResizeObserver;
  private donateLink: DonateLink[];
  private menuLabels: ComponentLabels[];
  private searchLabels: ComponentLabels[];
  private languageLabels: ComponentLabels[];

  @State() lastScrollTop = 0;
  @State() delta = 5;
  @State() navbarHeight = 0;
  @State() didScroll = false;
  @State() intervalId;

  // Listener for toggling mobile menu panel on or off.
  @Listen('mobileMenuToggle') mobileMenuToggle() {
    this.isMenuOpen = !this.isMenuOpen;
    this.menuMobileToggled.emit();
  }

  @Listen('scroll', {target: 'window'})
  handleScroll() {
    if (this.el.getAttribute('menu-type') === 'desktop') {
      this.didScroll = true;
    }
  }

  componentDidLoad() {
    // Set the browser resize observer to gather information about browser width.
    this.ro = new ResizeObserver((entries) => {
      for (const entry of entries) {
        this.applySizeClasses(entry.contentRect.width);
      }
    });
    this.ro.observe(document.body);

    // Pass the dataMenuLanguage prop to menu component.
    this.el.children[0].setAttribute('data-menu-language', this.dataMenuLanguage);

    this.navbarHeight = this.el.getBoundingClientRect().height;
  }

  componentWillLoad() {
    // Check for site header labels and set them to variables accordingly.
    if (this.dataSiteHeaderLabels) {
      const labels = JSON.parse(this.dataSiteHeaderLabels);
      this.menuLabels = labels.menu_labels;
      this.languageLabels = labels.language_labels;
      this.searchLabels = labels.search_labels;

      this.el.children[0].setAttribute('menu-button-breadcrumb-home', this.menuLabels['home']);
      this.el.children[0].setAttribute('menu-button-breadcrumb-main', this.menuLabels['main']);
      this.el.children[0].setAttribute('menu-button-breadcrumb-logourl', this.logoUrl);
    }

    // Check for the donation link information and set it to variables accordingly.
    // Also pass the donation link data to menu-component.
    if (this.dataMenuDonate) {
      this.donateLink = JSON.parse(this.dataMenuDonate);
      this.el.children[0].setAttribute('data-menu-donate', this.dataMenuDonate);
    }
  }

  componentWillUpdate() {
    // Pass the necessary information to menu component. These props will be
    // used in mobile menu.
    this.el.children[0].setAttribute('open', this.isMenuOpen.toString());
    this.el.children[0].setAttribute('logo-label', this.logoLabel);
    this.el.children[0].setAttribute('logo-url', this.logoUrl);
    this.el.children[0].setAttribute('site-label', this.siteLabel);
    this.el.children[0].setAttribute('site-url', this.siteUrl);
    this.el.children[0].setAttribute('menu-button-submenu-expand', this.menuLabels['expand']);
    this.el.children[0].setAttribute('menu-button-breadcrumb-return', this.menuLabels['return']);
    this.el.children[0].setAttribute('menu-button-breadcrumb-home', this.menuLabels['home']);
    this.el.children[0].setAttribute('menu-button-breadcrumb-main', this.menuLabels['main']);
    this.el.children[0].setAttribute('menu-button-breadcrumb-logourl', this.logoUrl);
    this.el.children[0].setAttribute('menu-language-label-open', this.languageLabels['open']);
    this.el.children[0].setAttribute('menu-language-label-close', this.languageLabels['close']);
    this.el.children[0].setAttribute('label-front-page', this.menuLabels['front_page']);

    this.intervalId = setInterval(() => {
      this.timer();
    }, 250);
  }

  timer() {
    if (this.didScroll) {
      this.hasScrolled();
      this.didScroll = false;
    }
  }

  hasScrolled() {
    let topOffset = window.pageYOffset;
    const bodyElementClasses = document.querySelector('body').classList;

    if (
      bodyElementClasses.contains('hy-menu-sidepanel__no-scroll') ||
      bodyElementClasses.contains('hy-menu-sidebar__no-scroll')
    ) {
      return;
    }

    if (Math.abs(this.lastScrollTop - topOffset) <= this.delta) {
      return;
    }

    let hySiteHeader = this.el.shadowRoot.querySelector('.hy-site-header') as HTMLElement;
    // If current position > last position AND scrolled past navbar...
    if (topOffset > this.lastScrollTop && topOffset > this.navbarHeight) {
      // Scroll Down
      hySiteHeader.classList.remove('hy-site-header--sticky-visible');
      hySiteHeader.classList.remove('has-toolbar', 'has-toolbar--large');

      // Close Search panel
      //CludoSayt.hide();
      this.headerScrollDown.emit();
    } else {
      // Scroll Up
      if (topOffset < this.el.offsetTop + this.navbarHeight) {
        hySiteHeader.classList.remove('hy-site-header--sticky-active');
        hySiteHeader.classList.remove('hy-site-header--sticky-visible');
        hySiteHeader.classList.remove('hy-site-header--sticky-hidden');
        hySiteHeader.classList.remove('has-toolbar', 'has-toolbar--large');

        // Close desktop menu panel if it's open.
      } else {
        hySiteHeader.classList.add('hy-site-header--sticky-active');
        hySiteHeader.classList.remove('hy-site-header--sticky-hidden');
        hySiteHeader.classList.add('hy-site-header--sticky-visible');

        if (bodyElementClasses.contains('toolbar-horizontal')) {
          hySiteHeader.classList.add('has-toolbar');

          if (bodyElementClasses.contains('toolbar-tray-open')) {
            hySiteHeader.classList.add('has-toolbar--large');
          }
        }
      }
    }

    this.lastScrollTop = topOffset;
  }

  componentDidUnload() {
    this.ro.disconnect();
  }

  applySizeClasses(size: number) {
    // Set the menu-type based on the width of the browser.
    if (size <= 1200 && size > 960) {
      this.menuType = MenuType.tablet;
    } else if (size <= 960) {
      this.menuType = MenuType.mobile;
    } else {
      this.menuType = MenuType.desktop;
    }

    // Pass the menu type to menu component.
    this.isMobile = this.menuType === (MenuType.mobile || MenuType.tablet);
    const menuAttribute = this.menuType === MenuType.tablet ? MenuType.mobile : this.menuType;
    this.el.children[0].setAttribute('menu-type', menuAttribute);
  }

  render() {
    const logoSize = this.isMobile ? SiteLogoSize.small : SiteLogoSize.big;
    const logoSizeGroup = this.isMobile ? SiteLogoSize.small : SiteLogoSize.small;
    const logoColor = ColorVariant.black;
    const logoColorGroup = ColorVariant.white;
    let classAttributes = ['hy-site-header', 'hy-site-header--' + this.menuType];

    switch (this.menuType) {
      case MenuType.desktop:
        // Larger than 1200px screens
        return [
          <header class={classAttributes.join(' ')}>
            <div class={{'hy-backdrop': true, 'is-active': this.isMenuOpen}} />
            {this.isGroup && (
              <div class="hy-site-header__content-top">
                <div class={'hy-site-header__logo-container group '}>
                  <hy-site-logo
                    is-group={true}
                    size={logoSizeGroup}
                    color={logoColorGroup}
                    url={this.siteUrl}
                    label={this.siteLabel}
                  />
                  <hy-menu-main-group is-mobile={false} data-main-menu={this.dataMainMenuLinks} />
                </div>

                <div class={'menu--secondary menu--secondary--group'}>
                  <hy-menu-language
                    class={'menu--secondary__item is-first group'}
                    is-group={true}
                    is-mobile={false}
                    data-menu-language={this.dataMenuLanguage}
                    labels={this.languageLabels}
                  />
                  <hy-site-search
                    class={'menu--secondary__item group'}
                    size={14}
                    color={logoColorGroup}
                    is-group={true}
                    show-label={true}
                    labels={this.searchLabels}
                    search-labels={this.dataSiteSearchLabels}
                    search-tools={this.dataSearchTools}
                  />
                  {this.donateLink.map((i) => {
                    return (
                      <a class={'menu--secondary__item hy-link__donate group'} href={i.url}>
                        <hy-icon icon={'hy-icon-heart-support'} size={14} fill={logoColorGroup} />
                        <span class={'hy-link__donate__label group'}>{i.label}</span>
                      </a>
                    );
                  })}
                </div>
              </div>
            )}
            <div class={{'hy-site-header__content': true, group: this.isGroup}}>
              <div class={'hy-site-header__logo-container'}>
                {this.isGroup ? (
                  <a class={'group'} href={this.logoUrl}>
                    {this.logoLabel}
                  </a>
                ) : (
                  <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} />
                )}
              </div>

              <hy-desktop-menu-links data-desktop-links={this.dataDesktopLinks}></hy-desktop-menu-links>

              {!this.isGroup && (
                <div class={'menu--secondary'}>
                  <hy-menu-language
                    class={'menu--secondary__item is-first'}
                    is-mobile={false}
                    data-menu-language={this.dataMenuLanguage}
                    labels={this.languageLabels}
                  />
                  <hy-site-search
                    class={'menu--secondary__item'}
                    size={14}
                    color={ColorVariant.black}
                    show-label={true}
                    labels={this.searchLabels}
                    search-labels={this.dataSiteSearchLabels}
                    search-tools={this.dataSearchTools}
                  />
                  {this.donateLink.map((i) => {
                    return (
                      <a class={'menu--secondary__item hy-link__donate'} href={i.url}>
                        <hy-icon icon={'hy-icon-heart-support'} size={14} fill={ColorVariant.black} />
                        <span class={'hy-link__donate__label'}>{i.label}</span>
                      </a>
                    );
                  })}
                </div>
              )}
            </div>
          </header>,
        ];
      case MenuType.tablet:
        // 960px-1200px screens
        return (
          <header class={classAttributes.join(' ')}>
            <div class={{'hy-backdrop': true, 'is-active': this.isMenuOpen}} />
            {this.isGroup && (
              <div class="hy-site-header__content-top">
                <div class={'hy-site-header__logo-container group '}>
                  <hy-site-logo
                    is-group={true}
                    size={logoSizeGroup}
                    color={logoColorGroup}
                    url={this.siteUrl}
                    label={this.siteLabel}
                  />
                  <hy-menu-main-group is-mobile={false} data-main-menu={this.dataMainMenuLinks} />
                </div>

                <div class={'menu--secondary menu--secondary--group'}>
                  <hy-menu-language
                    class={'menu--secondary__item is-first group'}
                    is-group={true}
                    is-mobile={false}
                    data-menu-language={this.dataMenuLanguage}
                    labels={this.languageLabels}
                  />
                  <hy-site-search
                    class={'menu--secondary__item group'}
                    size={14}
                    color={logoColorGroup}
                    show-label={true}
                    is-group={true}
                    labels={this.searchLabels}
                    search-labels={this.dataSiteSearchLabels}
                    search-tools={this.dataSearchTools}
                  />
                  {this.donateLink.map((i) => {
                    return (
                      <a class={'menu--secondary__item hy-link__donate group'} href={i.url}>
                        <hy-icon icon={'hy-icon-heart-support'} size={14} fill={logoColorGroup} />
                        <span class={'hy-link__donate__label group'}>{i.label}</span>
                      </a>
                    );
                  })}
                </div>
              </div>
            )}
            <div class="hy-site-header__content">
              <div class={'hy-site-header__logo-container'}>
                {this.isGroup ? (
                  <a class={'group'} href={this.logoUrl}>
                    {this.logoLabel}
                  </a>
                ) : (
                  <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} />
                )}
              </div>
              {!this.isGroup && (
                <div class={'menu--secondary'}>
                  <hy-menu-language
                    class={'menu--secondary__item is-first'}
                    is-mobile={false}
                    data-menu-language={this.dataMenuLanguage}
                    labels={this.languageLabels}
                  />
                  <hy-site-search
                    class={'menu--secondary__item'}
                    size={14}
                    color={ColorVariant.black}
                    show-label={true}
                    labels={this.searchLabels}
                    search-labels={this.dataSiteSearchLabels}
                    search-tools={this.dataSearchTools}
                  />
                  {this.donateLink.map((i) => {
                    return (
                      <a class={'menu--secondary__item hy-link__donate'} href={i.url}>
                        <hy-icon icon={'hy-icon-heart-support'} size={14} fill={ColorVariant.black} />
                        <span class={'hy-link__donate__label'}>{i.label}</span>
                      </a>
                    );
                  })}
                </div>
              )}
              <div class={'hy-site-header__menu-container'}>
                <span
                  class={{
                    'hy-site-header__menu-label': true,
                    'is-visible': this.isMenuOpen,
                  }}
                >
                  {this.menuLabel}
                </span>
                <button
                  onClick={() => this.mobileMenuToggle()}
                  class={{
                    'hy-site-header__panel-toggle': true,
                    'is-open': this.isMenuOpen,
                  }}
                  aria-label={this.isMenuOpen ? this.menuLabels['close'] : this.menuLabels['open']}
                >
                  {this.isMenuOpen ? (
                    <span class="hy-site-header__panel-toggle__label">
                      {this.menuLabelClose}
                      <hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.black} />
                    </span>
                  ) : (
                    <span class="hy-site-header__panel-toggle__label">
                      {this.menuLabelOpen}
                      <hy-icon icon={'hy-icon-hamburger'} size={20} fill={ColorVariant.black} />
                    </span>
                  )}
                </button>
                <div
                  class={{
                    'is-open': this.isMenuOpen,
                    'hy-site-header__panel': true,
                  }}
                >
                  <slot name={'menu'} />
                </div>
              </div>
            </div>
          </header>
        );
      case MenuType.mobile:
        // Smaller than 960px screens
        return (
          <header class={classAttributes.join(' ')}>
            <div class={{'hy-backdrop': true, 'is-active': this.isMenuOpen}} />
            {this.isGroup && (
              <div class="hy-site-header__content-top">
                <div class={'hy-site-header__logo-container group '}>
                  <hy-site-logo size={logoSizeGroup} color={logoColorGroup} url={this.siteUrl} label={this.siteLabel} />
                </div>

                <hy-menu-main-group is-mobile={true} data-main-menu={this.dataMainMenuLinks} />

                <div class={'menu--secondary menu--secondary--group'}>
                  <hy-site-search
                    class={'menu--secondary__item group'}
                    size={14}
                    color={logoColorGroup}
                    is-group={true}
                    show-label={true}
                    labels={this.searchLabels}
                    search-labels={this.dataSiteSearchLabels}
                    search-tools={this.dataSearchTools}
                  />
                </div>
              </div>
            )}
            <div class="hy-site-header__content">
              <div class={'hy-site-header__logo-container'}>
                {this.isGroup ? (
                  <a class={'group'} href={this.logoUrl}>
                    {this.logoLabel}
                  </a>
                ) : (
                  <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} />
                )}
              </div>

              <div class={'hy-site-header__menu-container'}>
                {!this.isGroup && (
                  <hy-site-search
                    class={'menu--secondary__item'}
                    size={14}
                    color={ColorVariant.black}
                    show-label={true}
                    labels={this.searchLabels}
                    search-labels={this.dataSiteSearchLabels}
                    search-tools={this.dataSearchTools}
                  />
                )}
                <button
                  onClick={() => this.mobileMenuToggle()}
                  class={{
                    'hy-site-header__panel-toggle': true,
                    'is-open': this.isMenuOpen,
                  }}
                  aria-label={this.isMenuOpen ? this.menuLabels['close'] : this.menuLabels['open']}
                >
                  {this.isMenuOpen ? (
                    <span class="hy-site-header__panel-toggle__label">
                      {this.menuLabelClose}
                      <hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.black} />
                    </span>
                  ) : (
                    <span class="hy-site-header__panel-toggle__label">
                      {this.menuLabelOpen}
                      <hy-icon icon={'hy-icon-hamburger'} size={20} fill={ColorVariant.black} />
                    </span>
                  )}
                </button>
                <div
                  class={{
                    'is-open': this.isMenuOpen,
                    'hy-site-header__panel': true,
                  }}
                >
                  <slot name={'menu'} />
                </div>
              </div>
            </div>
          </header>
        );
    }
  }
}