/**
 * @module tgam-patterns-panel
 */

import EVENT_NAMES from "./event-names";
import ee from "./event-emitter";
import { ariaToggle, toArray } from "./dom-methods";
import { delayTime, animationTime } from "./animation-times";

const panelOpenedClass = "o-panel--opened";
const panelOpeningClass = "o-panel--opening";
const panelClosingClass = "o-panel--closing";
const panelCatsOpenClass = "o-panel-categories--opened";
const panelSearchOpenClass = "o-panel-search--opened";
const panelScrollContainerOpen = "o-panel-scrollable--opened";

let panel = null;
let panelCategories = null;
let panelSearch = null;
let closeControls = null;
let panelCategoriesScrollContainer = null;
let panelSearchScrollContainer = null;
let panelOpeningTimeout = null;
let panelOpenedTimeout = null;
let panelClosedTimeout = null;

/**
 * @method init
 * @description init method, adds event listener for scroll and resize
 * @return {undefined}
 */
export default function init() {
  panel = document.querySelector("#o-panel");
  panelCategories = document.querySelector(".o-panel-categories");
  panelCategoriesScrollContainer = document.querySelector(".o-panel-scrollable--categories");
  panelSearch = document.querySelector(".o-panel-search");
  panelSearchScrollContainer = document.querySelector(".o-panel-scrollable--search");
  closeControls = toArray(document.querySelectorAll(".c-control--close"));

  enableListeners(true);
}

/**
 * @method enableListeners
 * @description adds event listeners to panel buttons
 * @param {boolean} toggleOn - whether to turn click listeners on or off
 * @return {undefined}
 */
export function enableListeners(toggleOn) {
  if (toggleOn) {
    ee.on(EVENT_NAMES.panel.openCategories, toggleCategoriesPanel);
    ee.on(EVENT_NAMES.panel.openSearch, toggleSearchPanel);
    closeControls && closeControls.forEach((el) => el.addEventListener("click", panelClose));
  } else {
    ee.off(EVENT_NAMES.panel.openCategories, toggleCategoriesPanel);
    ee.off(EVENT_NAMES.panel.openSearch, toggleSearchPanel);
    closeControls && closeControls.forEach((el) => el.removeEventListener("click", panelClose));
  }
}

/**
 * @method toggleCategoriesPanel
 * @description on menu clicked
 * @return {undefined}
 */
export function toggleCategoriesPanel() {
  const isMenuOpen = panel.classList.contains(panelOpenedClass) || panel.classList.contains(panelOpeningClass);
  const isCatOpen = panelCategories.classList.contains(panelCatsOpenClass);

  isMenuOpen && isCatOpen ? panelClose() : categoriesOpen();
}

/**
 * @method toggleSearchPanel
 * @description adds open class
 * @return {undefined}
 */
export function toggleSearchPanel() {
  const isMenuOpen = panel.classList.contains(panelOpenedClass) || panel.classList.contains(panelOpeningClass);
  const isSearchOpen = panelSearch.classList.contains(panelSearchOpenClass);

  isMenuOpen && isSearchOpen ? panelClose() : searchOpen();
}

/**
 * @method categoriesOpen
 * @description adds open class specific to categories
 * @return {undefined}
 */
export function categoriesOpen() {
  panelOpen("categories");
}

/**
 * @method searchOpen
 * @description adds open class specific to search
 * @return {undefined}
 */
export function searchOpen() {
  panelOpen("search");
}

/**
 * @method panelOpen
 * @description opens the panel and dynamically emits the component name for analytics tracking purposes
 * @param {string} [componentName = categories] one of two string values for opening the panel: "categories" or "search"
 * @return {undefined}
 */
export function panelOpen(componentName = "categories") {
  // remove hidden should ALWAYS be called first without a timeout
  // if you don't separate this with a timeout, you won't see any animations
  panel.removeAttribute("hidden");

  clearTimeout(panelOpeningTimeout);
  panelOpeningTimeout = setTimeout(panelOpening.bind(this, componentName), delayTime);

  clearTimeout(panelOpenedTimeout);
  panelOpenedTimeout = setTimeout(panelOpened.bind(this, componentName), animationTime);
}

/**
 * @method panelOpening
 * @description starts the animation for fading in panel
 * @param {string} [componentName = categories] one of two string values for opening the panel: "categories" or "search"
 * @return {undefined}
 */
function panelOpening(componentName = "categories") {
  // the `emit` method is causing a considerable delay, so this should be called at the top of the method
  ee.emit(`panel:${componentName}-opening`);
  ee.emit(EVENT_NAMES.panel.opening);

  setPanelTransitionClass(panelOpeningClass);
  if (componentName === "categories") {
    panelCategories.classList.add(panelCatsOpenClass);
    panelCategoriesScrollContainer.classList.add(panelScrollContainerOpen);
    panelSearch.classList.remove(panelSearchOpenClass);
    panelSearchScrollContainer.classList.remove(panelScrollContainerOpen);
  } else {
    panelCategories.classList.remove(panelCatsOpenClass);
    panelCategoriesScrollContainer.classList.remove(panelScrollContainerOpen);
    panelSearch.classList.add(panelSearchOpenClass);
    panelSearchScrollContainer.classList.add(panelScrollContainerOpen);
  }

  ariaToggle(".c-control--menu-button .c-control__button", `close ${componentName}`, true);
}

/**
 * @method panelOpened
 * @description after the animation is finished the background becomes clickable and the scroll is locked through the scrollmanager
 * @param {string} [componentName = categories] one of two string values for opening the panel: "categories" or "search"
 * @return {undefined}
 */
function panelOpened(componentName = "categories") {
  ee.emit(`panel:${componentName}-opened`);
  ee.emit(EVENT_NAMES.panel.opened);

  setPanelTransitionClass(panelOpenedClass);
}

/**
 * @method panelClose
 * @description removes open classes
 * @return {undefined}
 */
export function panelClose() {
  ee.emit(EVENT_NAMES.panel.closing);
  ee.emit(EVENT_NAMES.panel.closingCategories);
  ee.emit(EVENT_NAMES.panel.closingSearch);

  setPanelTransitionClass(panelClosingClass);
  ariaToggle(".c-control--menu-button .c-control__button", "open navigation", false);
  ariaToggle(".c-control--search-button .c-control__button", "open search", false);

  clearTimeout(panelClosedTimeout);
  panelClosedTimeout = setTimeout(() => {
    setPanelTransitionClass(null);
    panelCategories.classList.remove(panelCatsOpenClass);
    panelCategoriesScrollContainer.classList.remove(panelCatsOpenClass);
    panelSearch.classList.remove(panelSearchOpenClass);
    panelSearchScrollContainer.classList.remove(panelCatsOpenClass);

    panel.setAttribute("hidden", "hidden");

    ee.emit(EVENT_NAMES.panel.closed);
    ee.emit(EVENT_NAMES.panel.closedSearch);
    ee.emit(EVENT_NAMES.panel.closedCategories);
  }, animationTime);
}

/**
 * @method setPanelTransitionClass
 * @description swaps out panel transition/state class and adds a new class
 * @param {string|null} [className = null] class name to swap in
 * @return {undefined}
 */
export function setPanelTransitionClass(className = null) {
  panel.classList.remove(panelOpeningClass, panelOpenedClass, panelClosingClass);
  className && panel.classList.add(className);
}
