/**
 * Sticky.js
 * Script to make a component sticky
 */

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

export class Sticky {
  constructor(element) {
    this.element = element;
    this.addEventHandlers();
    this.makeElementSticky();

    this.stickyHeight = this.element.offsetHeight;
  }

  /**
   * Declare attribute constants
   */
  get attributes() {
    return {};
  }

  /**
   * Declare classes
   */
  get classes() {
    return {
      sticky: this.element.dataset.rsSticky
        ? this.element.dataset.rsSticky
        : 'is-sticky'
    };
  }

  /**
   * Add event handlers
   */
  addEventHandlers() {
    window.addEventListener('resize', () => {
      this.makeElementSticky();
    });
  }

  makeElementSticky() {
    const elementIsVisible =
      getComputedStyle(this.element).getPropertyValue('display') !== 'none';

    if (elementIsVisible) {
      const elementPos = this.element.offsetTop;

      const windowScrollStartPos = window.scrollY;

      if (windowScrollStartPos > elementPos) {
        this.element.classList.add(this.classes.sticky);
        this.addExtraSpacingToNextElement();
      }

      window.addEventListener('scroll', () => {
        const windowScrollPos = window.scrollY;

        if (windowScrollPos > elementPos) {
          this.element.classList.add(this.classes.sticky);
          this.addExtraSpacingToNextElement();
        } else {
          this.element.classList.remove(this.classes.sticky);
          this.removeExtraSpacingNextElement();
        }
      });
    }
  }

  addExtraSpacingToNextElement() {
    const nextElement = this.next(this.element);
    nextElement.setAttribute(
      'style',
      `top: ${this.stickyHeight}px; position: relative;`
    );
  }

  removeExtraSpacingNextElement() {
    const nextElement = this.next(this.element);
    nextElement.removeAttribute('style');
  }

  /*
   * Function to get the next elements node instead of text node
   */
  next(elem) {
    do {
      elem = elem.nextSibling;
    } while (elem && elem.nodeType !== 1);
    return elem;
  }

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