(function() {
	var root = (typeof exports == 'undefined' ? window : exports);

	var config = {
		// Ensure Content-Type is an image before trying to load @2x image
		// https://github.com/imulus/retinajs/pull/45)
		check_mime_type: true,

		// Resize high-resolution images to original image's pixel dimensions
		// https://github.com/imulus/retinajs/issues/8
		force_original_dimensions: true
	};

	root.Retina = Retina;

	function Retina() {}

	Retina.configure = function(options) {
		if (options == null) options = {};
		for (var prop in options) config[prop] = options[prop];
	};

	Retina.init = function(context) {
		if (context == null) context = root;

		var existing_onload = context.onload || new Function;

		context.onload = function() {
			var images = document.getElementsByTagName("img"), retinaImages = [], i, image;
			for (i = 0; i < images.length; i++) {
				image = images[i];
				retinaImages.push(new RetinaImage(image));
			}
			existing_onload();
		}
	};

	Retina.isRetina = function(){
		var mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),\
                      (min--moz-device-pixel-ratio: 1.5),\
                      (-o-min-device-pixel-ratio: 3/2),\
                      (min-resolution: 1.5dppx)";

		if (root.devicePixelRatio > 1)
			return true;

		if (root.matchMedia && root.matchMedia(mediaQuery).matches)
			return true;

		return false;
	};


	root.RetinaImagePath = RetinaImagePath;

	function RetinaImagePath(path, at_2x_path) {
		this.path = path;
		if (typeof at_2x_path !== "undefined" && at_2x_path !== null) {
			this.at_2x_path = at_2x_path;
			this.perform_check = false;
		} else {
			this.at_2x_path = path.replace(/\.\w+$/, function(match) { return "@2x" + match; });
			this.perform_check = true;
		}
	}

	RetinaImagePath.confirmed_paths = [];

	RetinaImagePath.prototype.is_external = function() {
		return !!(this.path.match(/^https?\:/i) && !this.path.match('//' + document.domain) )
	}

	RetinaImagePath.prototype.check_2x_variant = function(callback) {
		var http, that = this;
		if (this.is_external()) {
			return callback(false);
		} else if (!this.perform_check && typeof this.at_2x_path !== "undefined" && this.at_2x_path !== null) {
			return callback(true);
		} else if (this.at_2x_path in RetinaImagePath.confirmed_paths) {
			return callback(true);
		} else {
			http = new XMLHttpRequest;
			http.open('HEAD', this.at_2x_path);
			http.onreadystatechange = function() {
				if (http.readyState != 4) {
					return callback(false);
				}

				if (http.status >= 200 && http.status <= 399) {
					if (config.check_mime_type) {
						var type = http.getResponseHeader('Content-Type');
						if (type == null || !type.match(/^image/i)) {
							return callback(false);
						}
					}

					RetinaImagePath.confirmed_paths.push(that.at_2x_path);
					return callback(true);
				} else {
					return callback(false);
				}
			}
			http.send();
		}
	}



	function RetinaImage(el) {
		this.el = el;
		this.path = new RetinaImagePath(this.el.getAttribute('src'), this.el.getAttribute('data-at2x'));
		var that = this;
		this.path.check_2x_variant(function(hasVariant) {
			if (hasVariant) that.swap();
		});
	}

	root.RetinaImage = RetinaImage;

	RetinaImage.prototype.swap = function(path) {
		if (typeof path == 'undefined') path = this.path.at_2x_path;

		var that = this;
		function load() {
			if (! that.el.complete) {
				setTimeout(load, 5);
			} else {
				if (config.force_original_dimensions) {
					that.el.setAttribute('width', that.el.offsetWidth);
					that.el.setAttribute('height', that.el.offsetHeight);
				}

				that.el.setAttribute('src', path);
			}
		}
		load();
	}




	if (Retina.isRetina()) {
		Retina.init(root);
	}

})();
