(function($){
	EYE.extend({
		
		trgallery: {
			libs: {},
			types: /\.jpg|\.jpeg|\.png|\.gif|\.bmp/g,
			current: null,
			moved: false,
			pointer: {x:0,y:0},
			diff: {x:0, y:0},
			trackKey: false,
			

			defaults: {
				opacity: 0.3,
				border: 0,
				shadow: 6,
				duration: 300,
				prevent: 14,
				controls: true,
				caption: true,
				hideSource: false,
				centered: false,
				className: false,
				onLoad: function(){return false},
				beforeZoomIn: function(){return false},
				onZoomIn: function(){return false},
				beforeZoomOut: function(){return false},
				onZoomOut: function(){return false},
				onFocus: function(){return false},
				controlsTrigger: 'focus',
				easing: 'linear',
				preload: 'click'
			},
			
			template: [
				'<div class="trgallery">',
					'<div class="trgallery_s">',
						'<div class="trgallery_st">',
							'<div class="trgallery_stl"></div>',
							'<div class="trgallery_stc"></div>',
							'<div class="trgallery_str"></div>',
						'</div>',
						'<div class="trgallery_sc">',
							'<div class="trgallery_scl"></div>',
							'<div class="trgallery_scc"></div>',
							'<div class="trgallery_scr"></div>',
						'</div>',
						'<div class="trgallery_sb">',
							'<div class="trgallery_sbl"></div>',
							'<div class="trgallery_sbc"></div>',
							'<div class="trgallery_sbr"></div>',
						'</div>',
					'</div>',
					'<img src="" />',
					'<div class="trgallery_controls">',
						'<a href="#" class="trgallery_prev"></a>',
						'<a href="#" class="trgallery_next"></a>',
					'</div>',
					'<div class="trgallery_caption"></div>',
					'<div class="trgallery_loading"></div>',
				'</div>'
			],
			

			click: function(e) {
				var el = this;
				el.blur();

				if (el.trgalleryCfg.loading === true) {
					return false;
				}

				if (el.trgalleryCfg.zoomed == false) {
					EYE.trgallery.zoomIn(el);

				} else {
					EYE.trgallery.zoomOut(el, false);
				}
				return false;
			},
			

			zoomIn: function(el) {

				if (el.trgalleryCfg.loaded === false) {

					if (el.trgalleryCfg.loading != true) {
						el.trgalleryCfg.loading = true;
						EYE.trgallery.preload(el);
					}
					return;
				}

				if (el.trgalleryCfg.zoomed == true) {
					EYE.trgallery.focus(el);
					return;
				}
				el.trgalleryCfg.beforeZoomIn.apply(el,[el.trgalleryCfg.box]);
				
				var elPos = EYE.getPosition(el, true);
				var elHeight = el.offsetHeight;
				var elWidth = el.offsetWidth;
				var pos = EYE.getScroll();
				var borderAndShadow = el.trgalleryCfg.border + el.trgalleryCfg.shadow;
				var width = el.trgalleryCfg.width + borderAndShadow * 2; 
				var height = el.trgalleryCfg.height + borderAndShadow * 2;
				var screenRatio = pos.iw/pos.ih;
				var imageRatio = el.trgalleryCfg.width/el.trgalleryCfg.height;
				

				if (screenRatio > imageRatio) {
					if (height > pos.ih) {
						height = pos.ih;
						width = parseInt(height * imageRatio,10);
					}
				} else if (width > pos.iw) {
					width = pos.iw;
					height = parseInt(width / imageRatio, 10);
				}

				var top = el.trgalleryCfg.centered ? 
							pos.t + parseInt((pos.ih - height)/2, 10)
							: 
							Math.min(
								Math.max(
									pos.t, 
									elPos.y + (elHeight - height)/2 - borderAndShadow
								), 
								pos.t + pos.ih - height
							);
				var left = el.trgalleryCfg.centered ? 
							pos.l + parseInt((pos.iw - width)/2, 10)
							:
							Math.min(
								Math.max(
									pos.l, 
									elPos.x + (elWidth - width)/2 - borderAndShadow 
								), 
								pos.l + pos.iw - width
							);
				var imgWidth = width - borderAndShadow * 2;
				var imgHeight = height - borderAndShadow * 2;
				
				if(el.trgalleryCfg.hideSource === true) {
					el.style.visibility = 'hidden';
				}
				

				$('#' + el.trgalleryCfg.box)
					.css({
						top: elPos.y + 'px',
						left: elPos.x + 'px',
						width: elWidth + 'px',
						height: elHeight + 'px'
					})
					.find('>div')
						.hide()
						.end()
					.find('img')
						.attr('src', el.trgalleryCfg.src)
						.css({
							top: 0,
							left: 0,
							width: '100%',
							height: '100%',
							display: 'block',
							borderWidth: '0px'
						})
						.end()
					.animate({
							width: imgWidth,
							height: imgHeight,
							top: top + borderAndShadow,
							left: left + borderAndShadow
						}, 
						el.trgalleryCfg.duration,
						el.trgalleryCfg.easing, 
						function(){
							$(this)
								.css({
									top: top + 'px',
									left: left + 'px',
									width: width + 'px',
									height: height + 'px'
								})
								.find('img')
									.css({
										top: el.trgalleryCfg.shadow + 'px',
										left: el.trgalleryCfg.shadow + 'px',
										width: imgWidth + 'px',
										height: imgHeight + 'px',
										borderWidth: el.trgalleryCfg.border + 'px'
									})
									.end()
								.find('>div:first')
									.find('div.trgallery_sc')
										.css('height', height - el.trgalleryCfg.shadow*2 + 'px')
										.end()
									.show();
								el.trgalleryCfg.zoomed = true;
								EYE.trgallery.focus(el);
								el.trgalleryCfg.onZoomIn.apply(el,[el.trgalleryCfg.box]);
						});
			},
			

			showControls: function(el) {
				if(el == undefined)
					return;
				if (el.trgalleryCfg == undefined) {
					el = $('#' + $(el).attr('trgallery')).get(0);
				}
				var height,
					imgWidth,
					borderAndShadow = el.trgalleryCfg.border + el.trgalleryCfg.shadow;
				$('#' + el.trgalleryCfg.box)
					.find('img')
						.each(function(){
							imgWidth = parseInt($.curCSS(this, 'width'),10);
						})
						.end()
					.get(0).trgalleryControls = true;

				if(el.trgalleryCfg.caption) {
					$('#' + el.trgalleryCfg.box)
					.find('>div:eq(2)')
						.stop()
						.css({
							bottom: borderAndShadow + 'px',
							left: borderAndShadow + 'px',
							width: imgWidth + 'px'
						})
						.show()
						.each(function() {
							this.style.height = 'auto';
							height = this.offsetHeight;
							this.style.height = '0';
						})
						.animate({height: height}, el.trgalleryCfg.duration);
				}

				if(el.trgalleryCfg.controls) {

					if (EYE.trgallery.libs[el.trgalleryCfg.lib] > 1) {
						$('#' + el.trgalleryCfg.box)
							.find('>div:eq(1)')
								.show()
								.each(function(){
									if (!el.trgalleryCfg.controlsHeight) {
										el.trgalleryCfg.controlsHeight = this.offsetHeight;
									}
									this.style.height = '0';
								})
								.css({
									top: borderAndShadow + 'px',
									left: borderAndShadow + 'px',
									width: imgWidth + 'px'
								})
								.animate({height: el.trgalleryCfg.controlsHeight}, el.trgalleryCfg.duration);
					}
				}
			},
			

			zoomOut: function(el, goToNext) {
				var boxEl, elPos, borderAndShadow, elSize;

				if (el.trgalleryCfg) {
					if (el.trgalleryCfg.zoomed === false) {
						return;
					}
					el.trgalleryCfg.beforeZoomOut.apply(el,[el.trgalleryCfg.box]);
					boxEl = document.getElementById(el.trgalleryCfg.box);
					

				} else {
					boxEl = el;
					el = $('a[href=' + $('img',boxEl).attr('src') + ']').get(0);
				}

				if (el) {
					elPos = EYE.getPosition(el, true);
					el.trgalleryCfg.zoomed = false;
					borderAndShadow = el.trgalleryCfg.border + el.trgalleryCfg.shadow;
					elSize = {
						width: el.offsetWidth,
						height: el.offsetHeight
					};

				} else {
					borderAndShadow = EYE.trgallery.defaults.border + EYE.trgallery.defaults.shadow;
					elSize = {
						width: 0,
						height: 0
					};
					elPos = EYE.getPosition(boxEl, true);
					elPos.y += parseInt(boxEl.offsetHeight/2, 10);
					elPos.x += parseInt(boxEl.offsetWidth/2, 10);
				}
				$(boxEl)
					.css({
						top: boxEl.offsetTop + borderAndShadow + 'px',
						left: boxEl.offsetLeft + borderAndShadow + 'px',
						width: boxEl.offsetWidth - borderAndShadow*2 + 'px',
						height: boxEl.offsetHeight - borderAndShadow*2 + 'px'
					})
					.find('>div')
						.stop()
						.hide()
						.end()
					.find('img')
						.css({
							top: 0,
							left: 0,
							width: '100%',
							height: '100%',
							borderWidth: '0px'
						})
						.end()
					.animate(
						{
							top: elPos.y + 'px',
							left: elPos.x + 'px',
							width: elSize.width + 'px',
							height: elSize.height + 'px'
						}, 

						el ? el.trgalleryCfg.duration : EYE.trgallery.defaults.duration,
						el.trgalleryCfg.easing,
						function() {

							EYE.trgallery.blur();
							$(this).hide();

							if (el) {
								if(el.trgalleryCfg.hideSource === true) {
									el.style.visibility = 'visible';
								}
								el.trgalleryCfg.onZoomOut.apply(el,[el.trgalleryCfg.box]);
								if (!goToNext) {
									EYE.trgallery.focus($('div.trgallery:visible:last').not(':animated').get(0));
								}

							} else {
								$(boxEl).stop().remove();
							}
						}
					);
			},
			
			mouseOver: function(e) {
				var triggerEl = document.getElementById($(this).attr('trgallery'));
				if (triggerEl.trgalleryCfg.zoomed === true && this.trgalleryControls == false) {
					EYE.trgallery.showControls(triggerEl);
				}
				return false;
			},
			
			mouseOut: function(e) {
				if ( !EYE.isChildOf(this, e.relatedTarget, this) ) {
					$(this)
						.find('>div:not(:first)')
							.stop()
							.hide();
					this.trgalleryControls  = false;
				}
				return false;
			},
			

			mouseDown: function(e) {

				var triggerEl = document.getElementById($(this).attr('trgallery'));

				if (triggerEl) {
					$.extend(EYE.trgallery,{
						current: this,
						prevent: triggerEl.trgalleryCfg.prevent,
						moved: false,
						diff: {
							x: e.pageX - this.offsetLeft,
							y: e.pageY - this.offsetTop
						},
						pointer: {
							x: e.pageX ,
							y: e.pageY
						}
					});
					$(document)
						.bind('mousemove', EYE.trgallery.mouseMove)
						.bind('mouseup', EYE.trgallery.mouseUp);

				} else {
					$(this).trgalleryClear();
				}
				return false;
			},
			

			mouseMove: function(e) {
				var diffX = Math.abs(EYE.trgallery.pointer.x - e.pageX);
				var diffY = Math.abs(EYE.trgallery.pointer.y - e.pageY);

				if (EYE.trgallery.moved === false) {
					if ( diffX > EYE.trgallery.prevent|| diffY > EYE.trgallery.prevent) {
						EYE.trgallery.moved = true;
						$(EYE.trgallery.current).addClass('trgallery_move');
						if (!$(EYE.trgallery.current).is('.trgallery_focused')) {
							EYE.trgallery.focus(EYE.trgallery.current);
						}
					}

				} else {
					EYE.trgallery.current.style.top = e.pageY - EYE.trgallery.diff.y + 'px';
					EYE.trgallery.current.style.left = e.pageX - EYE.trgallery.diff.x + 'px';
				}
				return false;
			},
			

			mouseUp: function (e) {
				$(EYE.trgallery.current).removeClass('trgallery_move');
				EYE.trgallery.current = null;
				$(document)
					.unbind('mousemove', EYE.trgallery.mouseMove)
					.unbind('mouseup', EYE.trgallery.mouseUp);
				return false;
			},
			

			imageClick: function(e) {
				$(document)
					.unbind('mousemove', EYE.trgallery.mouseMove)
					.unbind('mouseup', EYE.trgallery.mouseUp);
				var el = document.getElementById($(this).attr('trgallery'));

				if (el) {

					if (EYE.trgallery.moved === false && $(this).is('.trgallery_focused')) {

						if ($(e.target).is('a')) {
							EYE.trgallery.zoomNext(el, e.target.className == 'trgallery_next' ? 1 : -1);
							var goToNext = true;

						} else {
							EYE.trgallery.zoomOut(el, goToNext||false);
						}

					} else if(!$(this).is('.trgallery_focused')) {
						EYE.trgallery.focus(this);
					}

				} else {
					$(this).trgalleryClear();
				}
				return false;
			},
			

			clear: function() {
				var subject = this;
				if (subject.size() == 0) {
					subject = $('div.trgallery');
				}
				return subject.each(function(){
					var triggerEl = document.getElementById($(this).attr('trgallery'));
					if (triggerEl) {
						EYE.trgallery.zoomOut(triggerEl, false);
					} else {
						EYE.trgallery.zoomOut(this, false);
					}
				});
			},
			

			zoomNext: function(el, dir) {
				if(el.trgalleryCfg.zoomed === false) {
					return;
				}
				EYE.trgallery.zoomOut(el, true);
				var nextImg = el.trgalleryCfg.iteration + dir;
				var lib = $(el).attr('trgallery');
				var maxImg = EYE.trgallery.libs[lib];
				if (nextImg < 0) {
					nextImg = maxImg - 1;
				} else if (nextImg >= maxImg) {
					nextImg = 0;
				}
				EYE.trgallery.zoomIn($('a[trgallery="' + lib + '"]').get(nextImg));
			},
			

			keyPressed: function(e) {
				var el = $('div.trgallery_focused');
				if (el.size() == 1) {
					var pressedKey = e.charCode || e.keyCode || -1;
					el = $('#' + $(el).attr('trgallery')).get(0);
					var lib = $(el).attr('trgallery');
					switch (pressedKey)
					{

						case 35:

							if (EYE.trgallery.libs[lib] > 1 &&  EYE.trgallery.libs[lib] - 1 != el.trgalleryCfg.iteration) {
								EYE.trgallery.zoomNext(el, EYE.trgallery.libs[lib] - el.trgalleryCfg.iteration - 1);
								return false;
							}
						break;

						case 36:

							if (EYE.trgallery.libs[lib] > 1 && el.trgalleryCfg.iteration != 0) {
								EYE.trgallery.zoomNext(el, - el.trgalleryCfg.iteration);
								return false;
							}
						break;

						case 40:

						case 37:

						case 8:

						case 33:

						case 80:
						case 112:

							if (EYE.trgallery.libs[lib] > 1) {
								EYE.trgallery.zoomNext(el, -1);
								return false;
							}
						break;

						case 38:

						case 39:

						case 34:

						case 32:

						case 110:
						case 78:

							if (EYE.trgallery.libs[lib] > 1) {
								EYE.trgallery.zoomNext(el, 1);
								return false;
							}
						break;

						case 27:

							EYE.trgallery.zoomOut(el, false);
							return false;
						break;
					}
				}
			},
			
			

			focus: function(el) {
				if(el == undefined)
					return;
				if (el.trgalleryCfg == undefined) {
					el = $('#' + $(el).attr('trgallery')).get(0);
				} else {
					var showControls = true;
				}

				EYE.trgallery.blur(el);
						
				$('#' + el.trgalleryCfg.box)
					.not('.trgallery_focused')
					.addClass('trgallery_focused');
				el.trgalleryCfg.onFocus.apply(el,[el.trgalleryCfg.box]);
				if (el.trgalleryCfg.controlsTrigger == 'focus' || showControls) {
					EYE.trgallery.showControls(el);
				}
			},
			

			blur: function(el) {
				$('div.trgallery_focused')
					.not('#' + (el == undefined ? 'faketrgallery' : el.trgalleryCfg.box))
					.removeClass('trgallery_focused')
					.each(function(){
						this.trgalleryControls = false;
					})
					.find('>div:not(:first)')
						.stop()
						.hide();
			},
			
			preload: function(el) {

				var boxEl = $('#' + el.trgalleryCfg.box).show();
				boxEl.find('>div, img').hide();
				var elPos = EYE.getPosition(el, true);
				boxEl
					.find('>div:last')
						.show()
						.end()
					.css({
						top: elPos.y + 'px',
						left: elPos.x + 'px',
						width: el.offsetWidth + 'px',
						height: el.offsetHeight + 'px'
					});

				var preld= new Image();
				preld.src = el.href;

				if (preld.complete) {
					EYE.trgallery.markPreloaded(preld, el);

				} else {
					preld.onload = function() {
						EYE.trgallery.markPreloaded(preld, el);
					};
				}
			},
			
			markPreloaded: function(preld, el) {

				$.extend(el.trgalleryCfg,{
					loaded: true,
					width: preld.width,
					height: preld.height,
					src: preld.src
				});

				$('#' + el.trgalleryCfg.box)
					.find('div.trgallery_loading')
					.hide();

				if (el.trgalleryCfg.loading) {
					el.trgalleryCfg.loading = false;
					EYE.trgallery.zoomIn(el);
				}
				el.trgalleryCfg.onLoad.apply(el,[el.trgalleryCfg.box]);
			},
			

			init: function(opt) {

				var libKey = parseInt(Math.random()*2000,10);

				EYE.trgallery.libs[libKey] = 0;
				opt = $.extend({lib:libKey}, EYE.trgallery.defaults, opt||{});
				return this.each(function(){
					var jQEl = $(this);
					var el = this;

					if (el.href && el.href.toLowerCase().match(EYE.trgallery.types) != null) {

						el.trgalleryCfg = $.extend({}, opt, {
							zoomed: false,
							loading: false,
							loaded: false,
							animated: false,
							src: el.href,
							iteration: EYE.trgallery.libs[libKey],
							box: 'trgallery_' + parseInt(Math.random() * 2000, 10) + ''
						});

						EYE.trgallery.libs[libKey]++;
						jQEl
							.bind('click', EYE.trgallery.click)
							.attr('trgallery', libKey)
							.attr('trgalleryBox', el.trgalleryCfg.box);
						var currId = jQEl.attr('id');
						if (!currId) {
							currId = el.trgalleryCfg.box + '_trigger';
							jQEl.attr('id', currId);
						}
						var titleAttr = $(el).attr('title');
						if (titleAttr == '' || titleAttr == false) {
							el.trgalleryCfg.caption = false;
						}

						$(EYE.trgallery.template.join(''))
							.attr('id', el.trgalleryCfg.box)
							.attr('trgallery', currId)
							.addClass(el.trgalleryCfg.className)
							.appendTo(document.body)
							.bind('mousedown', EYE.trgallery.mouseDown)
							.bind('click', EYE.trgallery.imageClick)
							.each(function(){
								this.trgalleryControls = false;
								if (el.trgalleryCfg.controlsTrigger != 'focus') {
									$(this)
										.bind('mouseover', EYE.trgallery.mouseOver)
										.bind('mouseout', EYE.trgallery.mouseOut);
								}
							})
							.find('>div')
								.not(':first')
									.css('opacity', el.trgalleryCfg.opacity)
									.end()
								.filter('div:eq(2)')
									.html('<p>' + titleAttr + '</p>');
						if (el.trgalleryCfg.preload == 'load') {
							EYE.trgallery.preload(el);
						}
						if (EYE.trgallery.trackKey === false) {
							EYE.trgallery.trackKey = true;
							$(document).bind('keydown', EYE.trgallery.keyPressed);
						}
					}
				});
			}
		}
	});
	
	$.fn.extend({

		trgallery: EYE.trgallery.init,

		trgalleryClear: EYE.trgallery.clear
	});
})(jQuery);
