/**
 * @module tgam-patterns-sticky-header
 */

import { animationTime } from "./animation-times";
import ee from "./event-emitter";
import EVENT_NAMES from "./event-names";

const headerNavSelector = ".c-header-nav";
const headerNavFixedClass = "c-header-nav--fixed";
const headerSelector = ".c-header-title";
const sectionShowTitleClass = "c-header-title--show";
const sectionUp = "c-header-title--scrolling-up";
const sectionDown = "c-header-title--scrolling-down";
const thresholdFirst = 100;
const thresholdSecond = 300;

let headerNav = null;
let header = null;
let pinned = false;
let classNavBarStatus = 0;
let classSectionStatus = 0;
let distance = null;
let lastScrollTop = 0;
let panelIsOpen = false;
let scrollPosition = null;
let scrollPercentage = null;

/**
 * @method init
 * @description init method, adds event listener for scroll and resize
 * @return {undefined}
 */
export default function init() {
  headerNav = document.querySelector(headerNavSelector);
  header = document.querySelector(headerSelector);

  // sticky scrolling logic
  let originalScrollValue = window.pageYOffset;

  window.scrollTo(0, 0);
  headerNav && (distance = headerNav.offsetTop - window.pageYOffset);
  window.scrollTo(0, originalScrollValue);

  // run once on initialization
  onViewPortChange();

  ee.on(EVENT_NAMES.panel.opened, () => {
    panelIsOpen = true;
  });

  ee.on(EVENT_NAMES.panel.closed, () => {
    panelIsOpen = false;
  });
}

/**
 * @method isHeaderFixed
 * @description if header has the fixed class
 * @return {boolean}
 */
export function isHeaderFixed() {
  return headerNav && headerNav.classList.contains(headerNavFixedClass);
}

/**
 * @method onViewPortChange
 * @description method checks page scroll offset and applies toggles a class on/off
 * @return {undefined}
 */
export function onViewPortChange() {
  scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
  scrollPercentage = Math.round(((scrollPosition + window.innerHeight) / document.body.offsetHeight) * 100) / 100;

  if (headerNav && !panelIsOpen) {
    const isFixed = isHeaderFixed();

    if (scrollPosition >= distance && !isFixed && !pinned) {
      pinned = true;
      headerNav.classList.add(headerNavFixedClass);
      header.setAttribute("hidden", "hidden");
      ee.emit(EVENT_NAMES.stickyHeader.fixed);
    } else if (scrollPosition <= distance && pinned) {
      pinned = false;
      headerNav.classList.remove(headerNavFixedClass);
      header.removeAttribute("hidden");
      ee.emit(EVENT_NAMES.stickyHeader.notFixed);
    }
  }

  if (header) {
    const withinTopThreshold = scrollPosition < thresholdFirst;
    const withinSecondThreshold = scrollPosition < thresholdSecond;

    // if within top threshold swap classes to show title or button containers
    if (withinTopThreshold && classSectionStatus !== 0) {
      header.classList.remove(sectionShowTitleClass);
      classSectionStatus = 0;
    } else if (!withinTopThreshold && classSectionStatus !== 1) {
      header.classList.add(sectionShowTitleClass);
      classSectionStatus = 1;
    }

    if (!panelIsOpen) {
      // if within second threshold swap classes to show/hide header-na`
      if (withinSecondThreshold && classNavBarStatus !== 0) {
        resetNav();
      } else if (scrollPercentage === 1 && classNavBarStatus !== 4) {
        scrolledToBottom();
      } else if (!withinSecondThreshold && (scrollPosition > lastScrollTop) && classNavBarStatus !== 1) {
        // scrolling down
        scrollingDown();
      } else if (!withinSecondThreshold && (scrollPosition < lastScrollTop)) {
        if (classNavBarStatus === 1 || classNavBarStatus === 4) {
          classNavBarStatus = 2;
          ee.emit(EVENT_NAMES.stickyHeader.anchored);

        } else if (classNavBarStatus === 2) {
          // scrolling up and checking distance from anchor
          scrollingUp();
        }
      }
    }

    lastScrollTop = scrollPosition;
  }
}

/**
 * @method resetNav
 * @description resets navigation, sets status to 0 and classes and dispatches event
 * @return {undefined}
 */
export function resetNav() {
  header.classList.remove(sectionUp);
  header.classList.remove(sectionDown);
  classNavBarStatus = 0;

  ee.emit(EVENT_NAMES.stickyHeader.top);

  setTimeout(() => {
    ee.emit(EVENT_NAMES.stickyHeader.topAnimationFinished);
  }, animationTime);
}

/**
 * @method scrollingDown
 * @description called when scrolling down
 * @return {undefined}
 */
export function scrollingDown() {
  header.classList.remove(sectionUp);
  header.classList.add(sectionDown);
  classNavBarStatus = 1;

  ee.emit(EVENT_NAMES.stickyHeader.hide);

  setTimeout(() => {
    ee.emit(EVENT_NAMES.stickyHeader.hideAnimationFinished);
  }, animationTime);
}

/**
 * @method scrollingUp
 * @description called when scrolling up, sets status and dispatches event
 * @return {undefined}
 */
export function scrollingUp() {
  header.classList.add(sectionUp);
  header.classList.remove(sectionDown);
  classNavBarStatus = 3;

  ee.emit(EVENT_NAMES.stickyHeader.show);

  setTimeout(() => {
    ee.emit(EVENT_NAMES.stickyHeader.showAnimationFinished);
  }, animationTime);
}

/**
 * @method scrolledToBottom
 * @description sets status and dispatches event
 * @return {undefined}
 */
export function scrolledToBottom() {
  classNavBarStatus = 4;

  ee.emit(EVENT_NAMES.stickyHeader.bottom);

  setTimeout(() => {
    ee.emit(EVENT_NAMES.stickyHeader.bottomAnimationFinished);
  }, animationTime);
}
