(function(window) {
  'use strict';

  var raf = window.requestAnimationFrame;

  var CLOSESNESS = 2;

  function startLoop(fn) {
    var running = false;
    var lastExit;

    (function animLoop() {
      // stop looping if lastExit was 1
      if (lastExit === 1) {
        return;
      }

      raf(animLoop);

      if (running) {
        return;
      }
      running = true;
      lastExit = fn();
      running = false;
    })();
  }

  /**
   * Absolute elements lose their 'real' offsetTop value.
   * This function calculate how far down the page an element really is.
   */
  function getTrueOffsetTop(element) {
    var offset = 0;
    var nextEl = element;

    do {
      offset += nextEl.offsetTop;
      nextEl = nextEl.offsetParent;
    } while (nextEl);

    return offset;
  }

  function calculateClosenesss(offsetTop, offsetHeight, viewportHeight, scrollY) {
    var offsetHalf = offsetTop + (offsetHeight / 2);
    var scrollYHalf = scrollY + (viewportHeight / 2);
    var distanceToElement;

    // defensively add one to prevent division by zero below
    offsetHeight += 1;

    if (offsetHalf > scrollYHalf) {
      distanceToElement = offsetHalf - scrollYHalf;
      return (distanceToElement / offsetHeight);
    } else if (offsetHeight < scrollYHalf) {
      distanceToElement = scrollYHalf - offsetHalf;
      return (distanceToElement / offsetHeight);
    } else {
      return 0;
    }
  }

  function watchElementLoop(watchElement, cb) {
    return function() {
      var offsetTop = getTrueOffsetTop(watchElement);
      var offsetHeight = watchElement.offsetHeight;
      var scrollY = window.scrollY;
      var viewportHeight = document.documentElement.clientHeight;

      var closeness = calculateClosenesss(offsetTop, offsetHeight, viewportHeight, scrollY);

      if (closeness <= CLOSESNESS) {
        cb();
        // one = stop looping now
        return 1;
      } else {
        // zero = keep looping
        return 0;
      }
    };
  }

  function lazyloadChildren(parent) {
    var childrenSelector = parent.getAttribute('data-lazyload-children');
    var children = parent.querySelectorAll(childrenSelector);

    // Bail out if we didn't find the children element to lazyload
    if (!children) {
      if (console && console.warn) {
        console.warn('Could not find children in %s using select: ', parent, childrenSelector);
      }

      return;
    }

    startLoop(watchElementLoop(parent, function() {
      for (var i = 0, l = children.length; i < l; i++) {
        lazySizes.loader.unveil(children[i]);
      }
    }));
  }

  var parentElements = document.querySelectorAll('[data-lazyload-children]');

  for (var i = 0, l = parentElements.length; i < l; i++) {
    lazyloadChildren(parentElements[i]);
  }

})(window);