/**
 * selector.js
 * script to toggle dropdown content by selector + set pointer position
 */

import ElementHelpers from '../helpers/element-helpers';

/**
 * Declare constants
 */
const attributeBase = 'data-rs-selector';

export class Selector {
  constructor(element) {
    this.element = element;
    this.dropdown = ElementHelpers.getElementByAttributeWithinElement(
      this.element,
      this.attributes.dropdown
    );
    this.content = ElementHelpers.getElementByAttributeWithinElement(
      this.element,
      this.attributes.content
    );
    this.pointer = ElementHelpers.getElementByAttributeWithinElement(
      this.element,
      this.attributes.pointer
    );
    this.overlay = ElementHelpers.getElementByAttribute(
      this.attributes.overlay
    );
    this.addEventHandlers();
  }

  /**
   * Declare attribute constants
   */
  get attributes() {
    return {
      content: `${attributeBase}-content`,
      dropdown: `${attributeBase}-dropdown`,
      overlay: `${attributeBase}-overlay`,
      pointer: `${attributeBase}-pointer`
    };
  }

  /**
   * Declare classes
   */
  get classes() {
    return {
      selectorDropDownActive: 'selector__dropdown--active',
      selectorContentActive: 'selector-box--active',
      modalOverlayActive: 'modal__overlay--active'
    };
  }

  /**
   * Add event handlers
   */
  addEventHandlers() {
    this.dropdown.addEventListener('click', (clickEvent) => {
      clickEvent.preventDefault();
      if (
        this.dropdown.classList.contains(this.classes.selectorDropDownActive)
      ) {
        this.closeContent();
      } else {
        this.openContent();
      }
    });
    // if page contains overlay, on click, close content
    if (this.overlay !== null) {
      this.overlay.addEventListener('click', () => {
        this.closeContent();
      });
    }

    window.addEventListener('resize', () => {
      if (
        this.dropdown.classList.contains(this.classes.selectorDropDownActive)
      ) {
        this.setPointer();
      }
    });
  }

  /**
   * Close content
   */
  closeContent() {
    this.dropdown.classList.remove(this.classes.selectorDropDownActive);
    this.content.classList.remove(this.classes.selectorContentActive);

    // set aria attributes
    this.dropdown.setAttribute('aria-expanded', 'false');
    this.content.setAttribute('aria-hidden', 'true');

    if (this.overlay !== null) {
      this.overlay.classList.remove(this.classes.modalOverlayActive);
    }
  }

  /**
   * Open content
   */
  openContent() {
    this.dropdown.classList.add(this.classes.selectorDropDownActive);
    this.content.classList.add(this.classes.selectorContentActive);
    this.setPointer();

    // set aria attributes
    this.dropdown.setAttribute('aria-expanded', 'true');
    this.content.setAttribute('aria-hidden', 'false');

    if (this.overlay !== null) {
      this.overlay.classList.add(this.classes.modalOverlayActive);
    }
  }

  /**
   * Set pointer - defines position of pointer attribute on dropdown content
   */
  setPointer() {
    const paddingRight = Math.round(
      window
        .getComputedStyle(this.dropdown, null)
        .getPropertyValue('padding-right')
        .replace('px', '')
    );

    const childNodes = this.dropdown.childNodes;
    let iconWidth;

    for (let i = 0; i < childNodes.length; i++) {
      if (
        childNodes[i].classList != null &&
        childNodes[i].classList.contains('icon')
      ) {
        const visibleIcon =
          getComputedStyle(childNodes[i]).getPropertyValue('display') !== 'none'
            ? childNodes[i]
            : null;

        if (visibleIcon) {
          iconWidth = getComputedStyle(childNodes[i])
            .getPropertyValue('width')
            .replace('px', '');
        }
      }
    }

    this.pointer.style.left = `${
      this.dropdown.offsetWidth -
      paddingRight -
      this.pointer.getBoundingClientRect().width / 2 +
      this.dropdown.offsetLeft -
      iconWidth / 3 +
      1
    }px`;
  }

  /**
   * Get selector
   */
  static getSelector() {
    return `[${attributeBase}]`;
  }
}
