/**
 * +-+-+-+-+-+-+-+-+-+-+
 * |m|i|n|i|-|m|o|d|a|l|
 * +-+-+-+-+-+-+-+-+-+-+
 *
 * Mini-modal is a lightweight and responsive light box plugin which supports images, YouTube, Vimeo, Google Maps,
 * Inline, Iframe, and AJAX content.
 *
 * Original minimodal.js script created by mdmoreau.
 * Version: 0.2.2
 * License: MIT
 * Homepage: https://github.com/mdmoreau/minimodal
 *
 * Updated version by Matt Zimmermann [https://github.com/influxweb]
 * Version: 1.0.0
 * License: MIT
 * Homepage: https://github.com/influxweb/minimodal
 *
 * The original script has been updated to allow for `inline` and `iframe` options. The CSS classes have been updated to
 * conform more with a name-spaced, BEM format.
 */

(function (root, factory) {
	'use strict';

	if (typeof define === 'function' && define.amd) {
		define([], factory);
	}
	else if (typeof module === 'object' && module.exports) {
		module.exports = factory();
	}
	else {
		root.minimodal = factory();
	}
}(this, function () {
	'use strict';

	var minimodal = function (target, options) {

		options = typeof options !== 'undefined' ? options : {};

		var _ = {};

		var option = function (property, value) {
			_.options[property] = typeof options[property] !== 'undefined' ? options[property] : value;
		};

		_.options = {};
		option('loadingHTML', 'Loading');
		option('previousButtonHTML', '‹');
		option('nextButtonHTML', '›');
		option('closeButtonHTML', '×');
		option('statusTimeout', 300);
		option('removeTimeout', 300);
		option('closeTimeout', 300);
		option('onLoaded', function () {});
		option('onClosed', function () {});
		option('googleMapsAPIKey', '');

		_.node = function (html) {
			var div = document.createElement('div');

			div.innerHTML = html;
			return div.firstChild;
		};

		_.setup = function (setTarget) {
			_.current = setTarget ? setTarget : target;
			_.minimodal = _.node('<div id="active-' + _.current.id + '" class="c-mini-modal" data-hook="active-' + _.current.id + '" tabindex="0" role="dialog">');
			_.overlay = _.node('<div class="c-mini-modal__overlay">');
			_.viewport = _.node('<div class="c-mini-modal__viewport">');
			_.closeButton = _.node('<button class="c-mini-modal__close">' + _.options.closeButtonHTML + '</button>');
		};

		_.build = function () {
			_.minimodal.appendChild(_.overlay);
			_.minimodal.appendChild(_.viewport);
			_.minimodal.appendChild(_.closeButton);
			document.body.appendChild(_.minimodal);
			_.minimodal.focus();
			_.minimodal.classList.add('c-mini-modal--active');
		};

		_.close = function () {
			var minimodal = _.minimodal;

			minimodal.classList.remove('c-mini-modal--active');
			setTimeout(function () {
				if (minimodal.parentNode) {
					minimodal.parentNode.removeChild(minimodal);
				}
			}, _.options.closeTimeout);
			document.documentElement.classList.remove('has-active-mini-modal');
			document.removeEventListener('keyup', _.keypress);
			if (target) {
				target.focus();
			}
			_.options.onClosed(_.type());
		};

		_.focusTrap = function (e) {
			if (e.shiftKey) {
				if (_.minimodal === document.activeElement) {
					e.preventDefault();
					_.closeButton.focus();
				}
			}
			else {
				if (_.closeButton === document.activeElement) {
					e.preventDefault();
					_.minimodal.focus();
				}
			}
		};

		_.keypress = function (event) {
			var key = event.key || event.keyCode;

			/* Tab Key */
			if (key === 'Tab' || key === 9) {
				_.focusTrap(event);
			}
			/* Esc Key */
			else if (key === 'Escape' || key === 27) {
				_.close();
			}
			/* Right Arrow */
			else if (key === 'ArrowRight' || key === 37) {
				if (_.index > -1) {
					_.previous();
				}
			}
			/* Left Arrow */
			else if (key === 'ArrowLeft' || key === 39) {
				if (_.index > -1) {
					_.next();
				}
			}
		};

		_.listen = function () {
			_.overlay.addEventListener('click', _.close);
			_.closeButton.addEventListener('click', _.close);
			document.addEventListener('keyup', _.keypress);
		};

		_.reflow = function () {
			var x = _.minimodal.clientWidth;
		};

		_.loading = function () {
			_.status = _.node('<div class="c-mini-modal__status">' + _.options.loadingHTML + '</div>');
			_.item.appendChild(_.status);
			_.reflow();
			_.item.classList.add('c-mini-modal__item--loading');
		};

		_.loaded = function () {
			var status = _.status;

			document.documentElement.classList.add('has-active-mini-modal');
			setTimeout(function () {
				if (status.parentNode) {
					status.parentNode.removeChild(status);
				}
			}, _.options.statusTimeout);
			_.item.appendChild(_.content);
			if (_.current.getAttribute('title')) {
				_.caption = _.node('<div class="c-mini-modal__caption">' + _.current.getAttribute('title'));
				_.item.appendChild(_.caption);
			}
			_.item.classList.remove('c-mini-modal__item--loading');
			_.reflow();
			_.item.classList.add('c-mini-modal__item--loaded');
			_.openCallback();
			_.options.onLoaded(_.type());
		};

		_.openCallback = function () {
			var openCallback = _.current.hasAttribute('data-mini-modal-openCallback') ? _.current.getAttribute('data-mini-modal-openCallback') : null;

			if (typeof mivaJS[openCallback] === 'function') {
				//console.log('this is a function');
				_.item.setAttribute('data-hook', openCallback);
				mivaJS[openCallback](_.item.getAttribute('data-hook'));
			}
		};

		_.error = function () {
			_.status.innerHTML = 'Error loading resource';
		};

		_.selectorExists = function (selector) {
			try {
				return document.querySelector(selector).length !== 0;
			} catch (e) {
				return false;
			}
		};

		_.ajax = function () {
			var url = _.url;
			var request = new XMLHttpRequest();

			request.open('GET', url, true);
			request.onload = function () {
				if (url === _.url) {
					if (request.status >= 200 && request.status < 400) {
						var response = request.responseText;

						_.content = _.node('<div class="c-mini-modal__content"><div class="c-mini-modal__element active-' + _.current.id + '">' + response);
						_.loaded();
					}
					else {
						_.error();
					}
				}
			};
			request.onerror = function () {
				if (url === _.url) {
					_.error();
				}
			};
			request.send();
		};

		_.googleMaps = function () {
			var src = 'https://www.google.com/maps/embed/v1/';
			var apiKey = _.options.googleMapsAPIKey;

			if (_.url.indexOf('/maps/place/') > -1) {
				var place = _.url.match('(?:/maps/place/)([^/]+)')[1];

				src += 'place?key=' + apiKey + '&q=' + place;
			}
			else {
				var coords = _.url.match('(?:/maps/@)([^z]+)')[1];

				coords = coords.split(',');

				var lat = coords[0];
				var long = coords[1];
				var zoom = coords[2];

				src += 'view?key=' + apiKey + '&center=' + lat + ',' + long + '&zoom=' + zoom + 'z';
			}
			_.content = _.node('<div class="c-mini-modal__content"><iframe class="c-mini-modal__element c-mini-modal__element--map active-' + _.current.id + '" src="' + src + '" frameborder="0">');
			_.loaded();
		};

		_.youtube = function () {
			var id = _.url.split('v=')[1];

			_.content = _.node('<div class="c-mini-modal__content"><div class="c-mini-modal__element c-mini-modal__element--video active-' + _.current.id + '"><iframe class="c-mini-modal__video" src="https://www.youtube.com/embed/' + id + '" frameborder="0" allowfullscreen>');
			_.loaded();
		};

		_.vimeo = function () {
			var id = _.url.split('vimeo.com/')[1];

			_.content = _.node('<div class="c-mini-modal__content"><div class="c-mini-modal__element c-mini-modal__element--video active-' + _.current.id + '"><iframe class="c-mini-modal__video" src="https://player.vimeo.com/video/' + id + '" frameborder="0" allowfullscreen>');
			_.loaded();
		};

		_.iframe = function () {
			var url = _.url;

			if (url === _.url) {
				_.content = _.node('<div class="c-mini-modal__content"><div class="c-mini-modal__element c-mini-modal__element--iframe active-' + _.current.id + '"><iframe class="c-mini-modal__iframe" src="' + url + '" frameborder="0" allowfullscreen>');
				_.loaded();
			}
		};

		_.inline = function () {
			var url = _.url;

			if (url === _.url) {
				if (_.selectorExists(url) || _.selectorExists('[' + _.current.getAttribute('data-mini-modal-content') + ']')) {
					var inlineContent;

					if (_.selectorExists(url)) {
						inlineContent = document.querySelector(url);
					}
					else {
						inlineContent = document.querySelector('[' + _.current.getAttribute('data-mini-modal-content') + ']');
					}

					if (inlineContent.nodeName.toLowerCase() === 'img') {
						var img = document.createElement('img');
						var imgSrc = inlineContent.getAttribute('src');
						var imgAlt = inlineContent.getAttribute('alt');

						img.onload = function () {
							if (url === _.url) {
								_.content = _.node('<div class="c-mini-modal__content"><img class="c-mini-modal__element active-' + _.current.id + '" src="' + imgSrc + '" alt="' + imgAlt + '">');
								_.loaded();
							}
						};
						img.onerror = function () {
							if (url === _.url) {
								_.error();
							}
						};
						img.src = imgSrc;
					}
					else {
						_.content = _.node('<div class="c-mini-modal__content"><div class="c-mini-modal__element active-' + _.current.id + '">' + inlineContent.innerHTML);
						_.loaded();
					}
				}
				else {
					_.iframe();
				}
			}
		};

		_.image = function () {
			var url = _.url;
			var img = document.createElement('img');

			img.onload = function () {
				if (url === _.url) {
					_.content = _.node('<div class="c-mini-modal__content"><img class="c-mini-modal__element active-' + _.current.id + '" src="' + _.url + '" alt="' + _.current.getAttribute('title') + '">');
					_.loaded();
				}
			};
			img.onerror = function () {
				if (url === _.url) {
					_.error();
				}
			};
			img.src = url;
		};

		_.type = function () {
			if (_.current.getAttribute('data-mini-modal-type')) {
				return _.current.getAttribute('data-mini-modal-type');
			}
			else if (_.url.indexOf('google.com/maps') > -1) {
				return 'googleMaps';
			}
			else if (_.url.indexOf('youtube.com') > -1) {
				return 'youtube';
			}
			else if (_.url.indexOf('vimeo.com') > -1) {
				return 'vimeo';
			}
			else {
				return 'image';
			}
		};

		_.load = function (change) {
			_.url = _.current.getAttribute('href');
			_.item = _.node('<div class="c-mini-modal__item">');
			_.viewport.appendChild(_.item);
			if (change) {
				_.item.classList.add('c-mini-modal__item--added');
				_.item.classList.add('c-mini-modal__item--added--' + change);
				_.reflow();
				_.item.classList.remove('c-mini-modal__item--added');
				_.item.classList.remove('c-mini-modal__item--added--' + change);
			}
			_.loading();
			_[_.type()]();
		};

		_.remove = function (change) {
			var item = _.item;

			item.classList.add('c-mini-modal__item--removed');
			item.classList.add('c-mini-modal__item--removed--' + change);
			setTimeout(function () {
				if (item.parentNode) {
					item.parentNode.removeChild(item);
				}
			}, _.options.removeTimeout);
		};

		_.update = function (change) {
			_.remove(change);
			_.current = _.groupItems[_.index];
			_.load(change);
		};

		_.previous = function () {
			if (_.index - 1 < 0) {
				_.index = _.indexMax;
			}
			else {
				_.index -= 1;
			}
			_.update('previous');
		};

		_.next = function () {
			if (_.index + 1 > _.indexMax) {
				_.index = 0;
			}
			else {
				_.index += 1;
			}
			_.update('next');
		};

		_.nav = function () {
			_.previousButton = _.node('<button class="c-mini-modal__nav c-mini-modal__nav--previous">' + _.options.previousButtonHTML + '</button>');
			_.nextButton = _.node('<button class="c-mini-modal__nav c-mini-modal__nav--next">' + _.options.nextButtonHTML + '</button>');
			_.minimodal.insertBefore(_.previousButton, _.closeButton);
			_.minimodal.insertBefore(_.nextButton, _.closeButton);
			_.previousButton.addEventListener('click', _.previous);
			_.nextButton.addEventListener('click', _.next);
		};

		_.group = function () {
			_.groupID = _.current.getAttribute('data-mini-modal');
			if (_.groupID) {
				_.groupItems = document.querySelectorAll('[data-mini-modal="' + _.groupID + '"]');
				if (_.groupItems.length > 1) {
					_.index = Array.prototype.indexOf.call(_.groupItems, _.current);
					_.indexMax = _.groupItems.length - 1;
					_.nav();
				}
			}
		};

		_.open = function (e) {
			e.preventDefault();
			_.setup();
			_.build();
			_.listen();
			_.load();
			_.group();
		};

		_.openModal = function (setTarget) {
			_.setup(setTarget);
			_.build();
			_.listen();
			_.load();
			_.group();
		};

		_.closeModal = function (activeModal) {
			activeModal.classList.remove('c-mini-modal--active');
			setTimeout(function () {
				if (activeModal.parentNode) {
					activeModal.parentNode.removeChild(activeModal);
				}
			}, _.options.closeTimeout);
			document.documentElement.classList.remove('has-active-mini-modal');
			document.removeEventListener('keyup', _.keypress);
			_.options.onClosed();
		};

		_.init = function () {
			target.addEventListener('click', _.open);
		};

		return _;

	};

	return minimodal;

}));