const Sticky = {}

/**
 * Creates an instance of Sticky
 *
 * @param {HTMLElement}    element
 * @param {PositionSticky} positionSticky
 * @returns {Sticky}
 * @static
 * @public
 */
Sticky.create = function create(element, positionSticky) {
  return Object.create(Sticky).init(element, positionSticky)
}

/**
 * Constructor method
 *
 * @param {HTMLElement}    element
 * @param {PositionSticky} positionSticky
 * @returns {Sticky}
 * @instance
 * @private
 */
Sticky.init = function init(element, positionSticky) {
  this.constructor       = Sticky
  this.$element          = global.$(element)
  this.element           = this.$element[0]
  this.positionSticky    = positionSticky
  this.boundingBoxHeight = null

  this.setElementWidth()
  this.setBoundingBoxHeight()

  return this
}

/**
 * Applies element's computed width to its inline styling so that when the element
 * is positioned absolutely or fixed it doesn't lose its shape
 *
 * @instance
 * @private
 */
Sticky.setElementWidth = function setElementWidth(width) {
  this.$element.css('width', '') // remove inline styles
  this.$element.css('width', `${width || this.element.getBoundingClientRect().width}px`)
}

/**
 * Saves element's bounding box height to an instance property so that it is not
 * calculated on every PositionSticky#_update.
 *
 * @instance
 * @private
 */
Sticky.setBoundingBoxHeight = function setBoundingBoxHeight() {
  this.boundingBoxHeight = this.$element.outerHeight(true)
}

/**
 * Re-measures element's dimensions. It is called
 * from PositionSticky#refresh.
 *
 * @param
 * @instance
 */
Sticky.refresh = function refresh() {
  let stickyWidth

  if (!this.positionSticky.isStatic()) {
    stickyWidth = this.positionSticky.placeholder.element.getBoundingClientRect().width
  }

  this.setElementWidth(stickyWidth)
  this.setBoundingBoxHeight()
}

module.exports = Sticky
