(function(window) {

	'use strict';

	var toggleEvent = function(el, name, fn, unbind) {
			var methodName = (unbind ? 'remove' : 'add') + 'EventListener';
			el[methodName](name, fn, false);
		};


	window.MicroMasonryGrid = function(gallery, newOpts) {
		var self = this,
			thumbElements = gallery.childNodes,
			figureEl,
			columnHeights,
			columnItems,
			gridWidth,
			columnWidth,
			i,
			windowHeight,
			galleryRect,
			galleryInitialYOffset,
			numColumns,
			localPageYOffset;


		var opts = self.opts = {
			cols: function(){return 3},
			gap: 10,
			src: 'data-m-src',
			getHeight: function(el, columnWidth) {
				return Math.round( columnWidth / Number(el.getAttribute('data-ratio')) );
			},
			addImage: function(el) {
				var img = new Image();
				// "this" is options object
				
				var srcSet = el.getAttribute('data-m-srcset');
				if(srcSet) {
					img.setAttribute('srcset',srcSet);
				}
				img.src = el.getAttribute(this.src);

				el.children[0].insertBefore(img, el.children[0].firstChild);

				//el.children[0].appendChild(img);
			}
		};

		for (var n in newOpts) { 
			opts[n] = newOpts[n]; 
		}
		
		var itemsToPaint = {},
			totalHeight;

		var calc = function() {
			localPageYOffset = window.pageYOffset;

			// create empty arrays for columns
			columnHeights = [];
			columnItems = [];
			

			galleryRect = gallery.getBoundingClientRect();
			galleryInitialYOffset = galleryRect.top + localPageYOffset;
			windowHeight =  window.innerHeight;

			gridWidth = galleryRect.right - galleryRect.left;

			i = numColumns = opts.cols(gridWidth);
			while(i--) {
				columnHeights.push(0);
				columnItems.push([]);
			}

			columnWidth = ( gridWidth - opts.gap * (numColumns-1) ) / numColumns;
			columnWidth = Math.round(columnWidth * 100) / 100; // leave two decimal points

			for(i = 0; i < thumbElements.length; i++) {
						
			    figureEl = thumbElements[i];

			    if(figureEl.nodeType !== 1) {
			        continue;
			    }

				// Find the key of the smallest column.
				var smallestColumnIndex = 0,
					tempVal = columnHeights[0];
				for(var q = 1; q < numColumns; q++) {
					if(columnHeights[q] < tempVal) {
						smallestColumnIndex = q;
						tempVal = columnHeights[q];
					}
				}
				
				var itemHeight = opts.getHeight(figureEl, columnWidth);
				var itemYPosition = columnHeights[smallestColumnIndex];
				var itemData;

				
				itemsToPaint[i] = {
					width: columnWidth + 'px',
					height: itemHeight + 'px',
					top: itemYPosition + 'px',
					left: columnWidth * smallestColumnIndex + (smallestColumnIndex * opts.gap) + 'px'
				};
				
				
				if(opts.src && figureEl.getAttribute(opts.src)) {
					itemData = {
						el:figureEl,
						h:itemHeight + opts.gap,
						tH: itemYPosition
					};
				}
			
				columnItems[smallestColumnIndex].push(itemData);

				columnHeights[smallestColumnIndex] += itemHeight + opts.gap;
			}
			
		};

		var paint = function() {
			for(i = 0; i < thumbElements.length; i++) {
				
				if(itemsToPaint[i]) {
				    var elStyle = thumbElements[i].style;
				   
				    elStyle.width = itemsToPaint[i].width;
				    elStyle.height = itemsToPaint[i].height;
				    elStyle.top = itemsToPaint[i].top;
				    elStyle.left = itemsToPaint[i].left;
				}
			}
			
			gallery.style.height = Math.max.apply(0, columnHeights) + 'px';
			//self.lazyLoad();
		};
		
		self.lazyLoad = function() {
			if(!opts.src) {
				return;
			}
			var pageOffset = localPageYOffset - galleryInitialYOffset,
				col,
				item;

			for(var c = 0; c < numColumns; c++) {
				col = columnItems[c];
				for(i = 0; i < col.length; i++) {
					item = col[i];
					if(!item) {
						continue;
					}
					var extraGap = 50;
					var tempGap = 0; // TEMP
					if(
						pageOffset+windowHeight+extraGap-tempGap >= item.tH && 
						pageOffset-extraGap+tempGap                    <= (item.tH + item.h) 
					) {
						opts.addImage(item.el);
						item.el.removeAttribute(opts.src);
						col[i] = null;
					}
				}
			}

		};

		// Throttle scroll (fire once per 100ms)
		var throttleTimer,
			onPageScroll = function() {
				if(!throttleTimer) {
					localPageYOffset = window.pageYOffset;
					self.lazyLoad();
					throttleTimer = setTimeout(function() { 
						localPageYOffset = window.pageYOffset;
						self.lazyLoad(); 
						throttleTimer = 0; 
					}, 100);
				}
			};

		/**
		 * Adds/removes scroll event, resize event, and their debouce/throttle timers.
		 * @param  {boolean} remove    Set to true to remove.
		 */
		self.toggleEvents = function(remove) {
			
			toggleEvent(window, 'scroll', onPageScroll, remove);

			toggleEvent(window, 'magnificCalc', calc, remove);
			toggleEvent(window, 'magnificPaint', paint, remove);

			//toggleEvent(window, 'resize', onPageResize, remove);
			if(remove) {
				clearTimeout(debounceTimer);
				clearTimeout(throttleTimer);
			}
		};

		//self.build();
		self.toggleEvents();
	};

})(window);


var init = function() {
	// loop through all gallery elements and bind events
	var galleryElements = document.querySelectorAll('.micro-masonry-grid');
	for(var i = 0, l = galleryElements.length; i < l; i++) {
		window.masonryTest = new MicroMasonryGrid(galleryElements[i], {
			cols:function(w) {
				return Math.round(w/210);
			}
		});
	}
};

init();