/**
 * 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();
  }

  /**
   * 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() {
    this.makeElementSticky();
  }

  makeElementSticky() {
    const elementPos = this.element.offsetTop;
    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 stickyHeight = this.element.offsetHeight;
    const nextElement = this.next(this.element);
    nextElement.setAttribute(
      'style',
      `top: ${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}]`;
  }
}
