if(!dojo._hasResource["dojox.image.Lightbox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.image.Lightbox"] = true;
dojo.provide("dojox.image.Lightbox");
dojo.experimental("dojox.image.Lightbox");

dojo.require("dijit.Dialog"); 
dojo.require("dojox.fx");

dojo.declare("dojox.image.Lightbox",
	dijit._Widget,{
	// summary:
	//	a dojo-based Lightbox implementation. 
	//
	// description:
	//	an Elegant, keyboard accessible, markup and store capable Lightbox widget to show images
	//	in a modal dialog-esque format. Can show individual images as Modal dialog, or can group
	//	images with multiple entry points, all using a single "master" Dialog for visualization
	//
	// examples:
	//	
	//	<a href="image1.jpg" dojoType="dojox.image.Lightbox">show lightbox</a>
	//	<a href="image2.jpg" dojoType="dojox.image.Lightbox" group="one">show group lightbox</a>
	//	<a href="image3.jpg" dojoType="dojox.image.Lightbox" group="one">show group lightbox</a>
	//
	//	FIXME: not implemented fully yet, though works with basic datastore access. need to manually call
	//	widget._attachedDialog.addImage(item,"fromStore") for each item in a store result set.
	//	<div dojoType="dojox.image.Lightbox" group="fromStore" store="storeName"></div>

	// group: String
	//	grouping images in a page with similar tags will provide a 'slideshow' like grouping of images
	group: "",

	// title: String 
	//	A string of text to be shown in the Lightbox beneath the image (empty if using a store)
	title: "",

	// href; String
	//	link to image to use for this Lightbox node (empty if using a store).
	href: "",

	// duration: Integer
	//	generic time in MS to adjust the feel of widget. could possibly add various 
	//	durations for the various actions (dialog fadein, sizeing, img fadein ...) 
	duration: 500,

	// _allowPassthru: Boolean
	//	privately set this to disable/enable natural link of anchor tags
	_allowPassthru: false,
	_attachedDialog: null, // try to share a single underlay per page?

	startup: function(){
		this.inherited("startup", arguments);
		// setup an attachment to the masterDialog (or create the masterDialog)
		var tmp = dijit.byId('dojoxLightboxDialog');
		if(tmp){
			this._attachedDialog = tmp;
		}else{
			// this is the first instance to start, so we make the masterDialog
			this._attachedDialog = new dojox.image._LightboxDialog({ id: "dojoxLightboxDialog" });
			this._attachedDialog.startup();
		}
		if(!this.store){
			// FIXME: full store support lacking, have to manually call this._attachedDialog.addImage(imgage,group) as it stands
			this._addSelf();
			this.connect(this.domNode, "onclick", "_handleClick");
		}
	},

	_addSelf: function(){
		this._attachedDialog.addImage({
			href: this.href,
			title: this.title
		},this.group||null);
	},

	_handleClick: function(/* Event */e){
		// summary: handle the click on the link 
		if(!this._allowPassthru){ e.preventDefault(); }
		else{ return; }
		this.show();
	},

	show: function(){
		this._attachedDialog.show(this);
	},

	disable: function(){
		// summary, disables event clobbering and dialog, and follows natural link
		this._allowPassthru = true;
	},

	enable: function(){
		// summary: enables the dialog (prevents default link)
		this._allowPassthru = false; 
	}

});

dojo.declare("dojox.image._LightboxDialog",
	dijit.Dialog,{
	//
	// Description:
	//	
	//	a widget that intercepts anchor links (typically around images) 	
	//	and displays a modal Dialog. this is the actual Popup, and should 
	//	not be created directly. 
	//
	//	there will only be one of these on a page, so all dojox.image.Lightbox's will us it
	//	(the first instance of a Lightbox to be show()'n will create me If i do not exist)
	// 
	//	note: the could be the ImagePane i was talking about?

	// title: String
	// 	the current title 
	title: "",

	// FIXME: implement titleTemplate

	// inGroup: Array
	//	Array of objects. this is populated by from the JSON object _groups, and
	//	should not be populate manually. it is a placeholder for the currently 
	//	showing group of images in this master dialog
	inGroup: null,

	// imgUrl: String
	//	the src="" attrib of our imageNode (can be null at statup)
	imgUrl: "",

	// an array of objects, each object being a unique 'group'
	_groups: { XnoGroupX: [] },
	_imageReady: false,

	templateString:"<div class=\"dojoxLightbox\" dojoAttachPoint=\"containerNode\">\r\n\t<div style=\"position:relative\">\r\n\t\t<div dojoAttachPoint=\"imageContainer\" class=\"dojoxLightboxContainer\">\r\n\t\t\t<img dojoAttachPoint=\"imgNode\" src=\"${imgUrl}\" class=\"dojoxLightboxImage\" alt=\"${title}\">\r\n\t\t\t<div class=\"dojoxLightboxFooter\" dojoAttachPoint=\"titleNode\">\r\n\t\t\t\t<div class=\"dijitInline LightboxClose\" dojoAttachPoint=\"closeNode\"></div>\r\n\t\t\t\t<div class=\"dijitInline LightboxNext\" dojoAttachPoint=\"nextNode\"></div>\t\r\n\t\t\t\t<div class=\"dijitInline LightboxPrev\" dojoAttachPoint=\"prevNode\"></div>\r\n\r\n\t\t\t\t<div class=\"dojoxLightboxText\"><span dojoAttachPoint=\"textNode\">${title}</span><span dojoAttachPoint=\"groupCount\" class=\"dojoxLightboxGroupText\"></span></div>\r\n\t\t\t</div>\r\n\t\t</div>\t\r\n\t\t\r\n\t</div>\r\n</div>\r\n",

	startup: function(){
		// summary: add some extra event handlers, and startup our superclass.
		this.inherited("startup", arguments);

		// FIXME: these are supposed to be available in dijit.Dialog already,
		// but aren't making it over.
		dojo.connect(document.documentElement,"onkeypress",this,"_handleKey");
		this.connect(window,"onresize","_position"); 

		this.connect(this.nextNode, "onclick", "_nextImage");
		this.connect(this.prevNode, "onclick", "_prevImage");
		this.connect(this.closeNode, "onclick", "hide");
		
	},

	show: function(/* Object */groupData){
		// summary: starts the chain of events to show an image in the dialog, including showing the dialog 
		//	if it is not already visible

		dojo.style(this.imgNode,"opacity","0"); 
		dojo.style(this.titleNode,"opacity","0");

		// we only need to call dijit.Dialog.show() if we're not already open.
		if(!this.open){ this.inherited("show", arguments); }
	
		this._imageReady = false; 
		
		this.imgNode.src = groupData.href;
		if((groupData.group && !(groupData == "XnoGroupX")) || this.inGroup){ 
			if(!this.inGroup){ 
				this.inGroup = this._groups[(groupData.group)];
				var i = 0;
				// determine where we were or are in the show 
				dojo.forEach(this.inGroup,function(g){
					if (g.href == groupData.href){
						this._positionIndex = i;
					}
					i++; 
				},this);
			}
			if(!this._positionIndex){ this._positionIndex=0; this.imgNode.src = this.inGroup[this._positionIndex].href; }
			this.groupCount.innerHTML = " (" +(this._positionIndex+1) +" of "+this.inGroup.length+")";
			this.prevNode.style.visibility = "visible";
			this.nextNode.style.visibility = "visible";
		}else{
			this.groupCount.innerHTML = "";
			this.prevNode.style.visibility = "hidden";
			this.nextNode.style.visibility = "hidden";
		}
		this.textNode.innerHTML = groupData.title;
	
		if(!this._imageReady || this.imgNode.complete === true){ 
			this._imgConnect = dojo.connect(this.imgNode,"onload", this, function(){
				this._imageReady = true;
				this.resizeTo({ w: this.imgNode.width, h:this.imgNode.height, duration:this.duration });
				dojo.disconnect(this._imgConnect);
			});
			// onload doesn't fire in IE if you connect before you set the src. 
			// hack to re-set the src after onload connection made:
			if(dojo.isIE){ this.imgNode.src = this.imgNode.src; }
		}else{
			// do it quickly. kind of a hack, but image is ready now
			this.resizeTo({ w: this.imgNode.width, h:this.imgNode.height, duration:1 });
		}
	},

	_nextImage: function(){
		// summary: load next image in group
		if(this._positionIndex+1<this.inGroup.length){
			this._positionIndex++;
		}else{
			this._positionIndex = 0;
		}
		this._loadImage();
	},

	_prevImage: function(){
		// summary: load previous image in group
		if(this._positionIndex==0){
			this._positionIndex = this.inGroup.length-1;
		}else{
			this._positionIndex--;
		}
		this._loadImage();
	},

	_loadImage: function(){
		// summary: do the prep work before we can show another image 
		var _loading = dojo.fx.combine([
			dojo.fadeOut({ node:this.imgNode, duration:(this.duration/2) }),
			dojo.fadeOut({ node:this.titleNode, duration:(this.duration/2) })
		]);
		this.connect(_loading,"onEnd","_prepNodes");
		_loading.play(10);
	},

	_prepNodes: function(){
		// summary: a localized hook to accompany _loadImage
		this._imageReady = false; 
		this.show({
			href: this.inGroup[this._positionIndex].href,
			title: this.inGroup[this._positionIndex].title
		});
	},

	resizeTo: function(/* Object */size){
		// summary: resize our dialog container, and fire _showImage
		var _sizeAnim = dojox.fx.sizeTo({ 
			node: this.containerNode,
			duration:size.duration||this.duration,
			width: size.w, 
			height:size.h+30
		});
		this.connect(_sizeAnim,"onEnd","_showImage");
		_sizeAnim.play(this.duration);
	},

	_showImage: function(){
		// summary: fade in the image, and fire showNav
		dojo.fadeIn({ node: this.imgNode, duration:this.duration,
			onEnd: dojo.hitch(this,"_showNav")
		}).play(75);
	},

	_showNav: function(){
		// summary: fade in the footer, and setup our connections.
		dojo.fadeIn({ node: this.titleNode, duration:200 }).play(25);
	},

	hide: function(){
		// summary: close the Lightbox
		dojo.fadeOut({node:this.titleNode, duration:200 }).play(25); 
		this.inherited("hide", arguments);
		this.inGroup = null;
		this._positionIndex = null;
	},

	addImage: function(/* object */child,/* String? */group){
		// summary: add an image to this master dialog
		// 
		// child.href: String - link to image (required)
		// child.title: String - title to display
		//
		// group: String - attach to group of similar tag
		//	or null for individual image instance

		var g = group;
		if(!child.href){ return; }
		if(g){ 	
			if(this._groups[(g)]){
				this._groups[(g)].push(child); 
			}else{
				this._groups[(g)] = [(child)];
			}
		}else{ this._groups["XnoGroupX"].push(child); }
	},

	_handleKey: function(/* Event */e){
		// summary: handle keyboard navigation
		if(!this.open){ return; }
		var key = (e.charCode == dojo.keys.SPACE ? dojo.keys.SPACE : e.keyCode);
		switch(key){
			case dojo.keys.ESCAPE: this.hide(); break;

			case dojo.keys.DOWN_ARROW:
			case dojo.keys.RIGHT_ARROW:
			case 78: // key "n"
				this._nextImage(); break;

			case dojo.keys.UP_ARROW:
			case dojo.keys.LEFT_ARROW:
			case 80: // key "p" 
				this._prevImage(); break;
		}
	}
});

}
