
// ------------------------------------------
// Rellax.js - v0.1
// Buttery smooth parallax library
// Copyright (c) 2016 Moe Amaya (@moeamaya)
// MIT license
//
// Thanks to Paraxify.js and Jaime Cabllero
// for parallax concepts 
// ------------------------------------------


var Rellax = function(el, options){
  "use strict";

  var self = Object.create(Rellax.prototype);

  // Rellax stays lightweight by limiting usage to desktops/laptops
  if (typeof window.orientation !== 'undefined') { return; }

  var posY = 0;
  var screenY = 0;
  var blocks = [];

  // Default Settings
  self.options = {
    speed: -4
  };

  // User defined options (might have more in the future)
  if (options){
    Object.keys(options).forEach(function(key){
      self.options[key] = options[key];
    });
  }

  // If some clown tries to crank speed, limit them to +-10
  if (self.options.speed < -10) {
    self.options.speed = -10;
  } else if (self.options.speed > 10) {
    self.options.speed = 10;
  }

  // By default, rellax class
  if (!el) {
    el = '.rellax';
  }

  // Classes
  if (document.getElementsByClassName(el.replace('.',''))){
    self.elems = document.getElementsByClassName(el.replace('.',''));
  }

  // Now query selector
  else if (document.querySelector(el) !== false) {
    self.elems = querySelector(el);
  }

  // The elements don't exist
  else {
    throw new Error("The elements you're trying to select don't exist.");
  }


  // Let's kick this script off
  // Build array for cached element values
  // Bind scroll and resize to animate method
  var init = function() {
    screenY = window.innerHeight;
    setPosition();

    // Get and cache initial position of all elements
    for (var i = 0; i < self.elems.length; i++){
      var block = createBlock(self.elems[i]);
      blocks.push(block);
    }

    window.addEventListener('scroll',function(){
      animate();
      if (DEBUG) { debounce(); }
      else { animate(); }
    });
    window.addEventListener('resize',function(){
      animate();
    });

    animate();
  };


  // We want to cache the parallax blocks'
  // values: base, top, height, speed
  // el: is dom object, return: el cache values
  var createBlock = function(el) {

    // initializing at scrollY = 0 (top of browser)
    // ensures elements are positioned based on HTML layout
    var posY = 0;

    var blockTop = posY + el.getBoundingClientRect().top;
    var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;

    // apparently parallax equation everyone uses
    var percentage = (posY - blockTop + screenY) / (blockHeight + screenY);

    // Optional individual block speed as data attr, otherwise global speed
    var speed = el.dataset.rellaxSpeed ? el.dataset.rellaxSpeed : self.options.speed;
    var base = updatePosition(percentage, speed);

    // Store non-translate3d transforms
    var cssTransform = el.style.cssText.slice(11);

    return {
      base: base,
      top: blockTop,
      height: blockHeight,
      speed: speed,
      style: cssTransform
    };
  };


  // set scroll position (posY)
  // side effect method is not ideal, but okay for now
  var setPosition = function() {
    if (window.pageYOffset !== undefined) {
      posY = window.pageYOffset;
    } else {
      posY = (document.documentElement || document.body.parentNode || document.body).scrollTop;
    }
  };


  // Ahh a pure function, gets new transform value
  // based on scrollPostion and speed
  var updatePosition = function(percentage, speed) {
    var value = (speed * (100 * (1 - percentage)));
    return Math.round(value);
  };


  // Not using. Debating it's value for this script
  // check if element is in viewport (ignores transform3d tho)
  var visible = function(i) {
    if ( (posY + screenY) > self.elems[i].offsetTop && (posY) < self.elems[i].offsetTop + self.elems[i].offsetHeight ) {
      return true;
    }
    return false;
  };


  // Transform3d on parallax element
  var animate = function() {
    setPosition();

    for (var i = 0; i < self.elems.length; i++){
      var percentage = ((posY - blocks[i].top + screenY) / (blocks[i].height + screenY));

      // Subtracting initialize value, so element stays in same spot as HTML
      var position = updatePosition(percentage, blocks[i].speed) - blocks[i].base;

      // Move that element
      var translate = 'translate3d(0,' + position + 'px' + ',0)' + blocks[i].style;
      self.elems[i].style.cssText = '-webkit-transform:'+translate+';-moz-transform:'+translate+';transform:'+translate+';';
    }
  };


  // ------------------------------------
  //  For Testing
  // ------------------------------------
  var debounceValue = 0;
  var debounce = function() {
    if (debounceValue < 10) {
      debounceValue++;
    } else {
      animate();
      debounceValue = 0;
    }
  };


  init();
  Object.freeze();
  return self;
};


