/*
 * jQuery UI Labs - Magnifier
 * - for experimental use only -
 *
 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Depends:
 *  ui.core.js
 *	effects.core.js
 */
(function($) {

var counter = 0;

$.widget("ui.magnifier", {
	_init: function() {

		var self = this,
			o = this.options;

		this.element
			.bind('click.magnifier', function(event) {
				!self.disabled && self._trigger('click', event, {
					current: self.current[0],
					offset: self.current[1]
				});
			});

		// the element must have relative or absolute positioning
		if (!(/^(r|a)/).test(this.element.css("position"))) {
			this.element.css("position", "relative");
		}

		this.items = [];
		$(o.items, this.element).each(function() {

			var $this = $(this);
			self.items.push({
				element: $(this),
				offset: $this.offset(),
				width: $this.width(),
				height: $this.height(),
				position: (o.overlap ? $this.position() : null)
			});

			(o.opacity && $this.css('opacity', o.opacity.min));

		});

		// absolutize
		(o.overlap && $.each(this.items, function() {
			this.element.css({
				position: "absolute",
				top: this.position.top,
				left: this.position.left
			});
		}));

		this.identifier = ++counter;
		$(document).bind("mousemove.magnifier"+this.identifier, function(event) {
			(self.disabled || self._magnify.call(self, event));
		});

		this.pp = this.element.offset();
	},

	destroy: function() {
		this.reset();
		$(document).unbind("mousemove.magnifier"+this.identifier);
		$.widget.prototype.destroy.apply(this, arguments);
	},

	disable: function() {
		this.reset();
		$.widget.prototype.disable.apply(this, arguments);
	},

	reset: function(event) {

		var o = this.options;
		$.each(this.items, function() {

			this.element.css({
				width: this.width,
				height: this.height,
				top: (this.position ? this.position.top : 0),
				left: (this.position ? this.position.left : 0)
			});

			(o.opacity && this.element.css('opacity', o.opacity.min));
			(o.zIndex && this.element.css("z-index", ""));

		});

	},

	_magnify: function(event) {

		this.current = this.items[0];
		var p = [event.pageX, event.pageY],
			o = this.options, c,
			distance = 1;

		// Compute the parent's distance
		// we don't need to fire anything if we are not near the parent
		var overlap = ((p[0] > this.pp.left - o.distance) &&
			(p[0] < this.pp.left + this.element[0].offsetWidth + o.distance) &&
			(p[1] > this.pp.top-o.distance) &&
			(p[1] < this.pp.top + this.element[0].offsetHeight + o.distance));
		if (!overlap) { return false; }

		for (var i = 0; i < this.items.length; i++) {

			c = this.items[i];

			var olddistance = distance;
			if (!o.axis) {
				distance = Math.sqrt(
					  Math.pow(p[0] - ((c.position ? this.pp.left : c.offset.left) + parseInt(c.element[0].style.left,10)) - (c.element[0].offsetWidth/2), 2)
					+ Math.pow(p[1] - ((c.position ? this.pp.top  : c.offset.top ) + parseInt(c.element[0].style.top,10)) - (c.element[0].offsetHeight/2), 2)
				);
			} else {
				if(o.axis == "y") distance = Math.abs(p[1] - ((c.position ? this.pp.top  : c.offset.top ) + parseInt(c.element[0].style.top,10)) - (c.element[0].offsetHeight/2));
				if(o.axis == "x") distance = Math.abs(p[0] - ((c.position ? this.pp.left : c.offset.left) + parseInt(c.element[0].style.left,10)) - (c.element[0].offsetWidth/2));
			}

			if (distance < o.distance) {

				this.current = distance < olddistance ? c : this.current;

				(!o.axis || o.axis != "y") && c.element.css({
					width: c.width + (c.width * (o.magnification - 1)) - (((distance / o.distance) * c.width) * (o.magnification - 1)),
					left: (c.position ? (c.position.left + o.verticalLine * ((c.height * (o.magnification - 1)) - (((distance / o.distance) * c.height) * (o.magnification - 1)))) : 0)
				});

				(!o.axis || o.axis != "x") && c.element.css({
					height: c.height + (c.height * (o.magnification - 1)) - (((distance/o.distance) * c.height) * (o.magnification - 1)),
					top: (c.position ? c.position.top : 0) + (o.baseline-0.5) * ((c.width * (o.magnification - 1)) - (((distance / o.distance) * c.width) * (o.magnification - 1)))
				});

				o.opacity && c.element.css('opacity', o.opacity.max - (distance / o.distance) < o.opacity.min ? o.opacity.min : o.opacity.max - (distance / o.distance));

			} else {

				c.element.css({
					width: c.width,
					height: c.height,
					top: (c.position ? c.position.top : 0),
					left: (c.position ? c.position.left : 0)
				});

				o.opacity && c.element.css('opacity', o.opacity.min);

			}

			o.zIndex && c.element.css("z-index", "");
		}

		o.zIndex && $(this.current[0]).css("z-index", o.zIndex);
	}
});

$.extend($.ui.magnifier, {
	version: "@VERSION",
	defaults: {
		distance: 150,
		magnification: 2,
		baseline: 0,
		verticalLine: -0.5,
		items: "> *"
	}
});

})(jQuery);

