jQuery(function($){
	// create the demo controller
	var demo = window.demo = {
		// some handy refs
		$win: $( window ),
		$doc: $( document ),
		// the demo links
		$links: $('#content a.demo').bind("click",function(){
			demo.load( this );
			// prevent default
			return false;
		}),
		// the whole demo markup
		markup: [
			'<div class="demo-overlay">',
				'<div class="demo-mask"></div>',
				'<div class="demo-loader">Loading</div>',
				'<div class="demo-box">',
					'<div class="demo-ctrl">',
						'<a href="#edit" class="demo-edit">Edit Source</a>',
						'<a href="#execute" class="demo-commit">Execute Source</a>',
						'<a href="#close" class="demo-close">Close &times;</a>',
					'</div>',
					'<div class="demo-editor"></div>',
					'<iframe src="../demo/blank/" frameborder="0" class="demo-frame" />',
					'<div class="demo-nav">',
						'<a href="#" class="demo-open" title="Open demo in a new window.">New Window</a>',
						'<a href="#prev" class="demo-prev">&laquo; Prev</a>',
						' &middot; <span class="demo-num">1/10</span> &middot; ',
						'<a href="#next" class="demo-next">Next &raquo;</a>',
					'</div>',
				'</div>',
			'</div>'
		],
		// initialize the components
		init: function(){
			// the container that holds everything
			demo.$overlay = $( demo.markup.join('') )
				.appendTo( document.body );
			// the semi-transparent mask
			demo.$mask = demo.$overlay.find('.demo-mask')
				.bind("mousedown", demo.close );
			// displays a loading message, or error
			demo.$loader = demo.$overlay.find('.demo-loader');
			// the centered content container
			demo.$box = demo.$overlay.find('.demo-box');
			// the edit source link
			demo.$editlink = demo.$overlay.find('.demo-edit')
				.bind("click", demo.edit );
			// the commit source code link
			demo.$commitlink = demo.$overlay.find('.demo-commit')
				.bind("click", demo.commit );
			// show the demo URL / open in new window
			demo.$openurl = demo.$overlay.find('.demo-open')
				.bind("click",function(){
					window.open( this.href );
					return false;					   
				});
			// the "close" link
			demo.$overlay.find('.demo-close').bind("click",function(){
				demo.close();
				return false;
			});
			// the "prev" link
			demo.$overlay.find('.demo-prev').bind("click",function(){
				demo.load( demo.$links[ demo.prev_index ] );
				return false;
			});
			// the "next" link
			demo.$overlay.find('.demo-next').bind("click",function(){
				demo.load( demo.$links[ demo.next_index ] );
				return false;
			});
			// the number display
			demo.$num = demo.$overlay.find('.demo-num');
			// the index of the last link
			demo.last = demo.$links.length - 1;
			// the source editor
			demo.$editor = demo.$overlay.find('.demo-editor');
			// the entire background
			demo.$bg = demo.$overlay.add( demo.$mask );
			// instantiate the codemirror editor
			demo.codemirror = new CodeMirror( 
				demo.$editor[0], {
				content: '&nbsp;',
				width: "100%",
				height: "100%",
				indentUnit: 3,
				tabMode: "shift",
				textWrapping: false,
				//lineNumbers: true,
				path: "../../inc/codemirror/",
				parserfile: [
					"parsexml.js", 
					"parsecss.js", 
					"tokenizejavascript.js", 
					"parsejavascript.js", 
					"parsehtmlmixed.js"
					],
				stylesheet: [
					"../../inc/codemirror/xmlcolors.css", 
					"../../inc/codemirror/jscolors.css", 
					"../../inc/codemirror/csscolors.css"
					],
				initCallback: function(){
					demo.codeMirrorReady = true;
				}
			});
			// the demo page
			demo.$iframe = demo.$overlay.find('.demo-frame');
			// add resize events
			demo.$win.bind("scroll resize", demo.update );
			// set a timeout to fail if iframe page doesn't load
			demo.timer = setTimeout( demo.error, 10e3 ); // 10 seconds
			// remember state
			demo.ready = true;
		},
		// update the overlay position
		update: function(){
			if ( !demo.isopen ) return;
			// which element is being aligned...
			var $elem = demo.isloaded ? demo.$box : demo.$loader;
			// force opacity on the background mask
			demo.$mask.css('opacity', 0.8 );
			// force 100% coverage
			demo.$bg.height( demo.$doc.height() ).width( demo.$doc.width() ).show();
			// center height in the viewport
			$elem.css({
				top: demo.$doc.scrollTop() + ( demo.$win.height() - $elem.height() ) / 2,
				left: demo.$doc.scrollLeft() + ( demo.$win.width() - $elem.width() ) / 2 
			});
			return false;
		},
		// load a new demo for presentation
		load: function( a ){
			// make sure it is initialized
			if ( !demo.ready )
				demo.init();
			
			// make sure the states are correct
			demo.reset();	
			// reload the iframe
			if ( demo.frame )
				demo.frame.location.reload();
			// load the page content with ajax
			$.ajax({
				type: 'post',
				dataType: "text",
				url: a.href+'/source',
				success: demo.success,
				error: demo.error
			});
			// update new window link
			//demo.$openurl.text( a.href );
			demo.$openurl.attr('href', a.href );
			// update the number display...
			demo.index = demo.$links.index( a );
			demo.$num.text( ( demo.index + 1 )+'/'+( demo.last + 1 ) );
			// update the previous index and link
			demo.prev_index = demo.index - 1;
			// modify circular navigation
			if ( demo.prev_index < 0 )
				demo.prev_index = demo.last;
			// update the previous index and link
			demo.next_index = demo.index + 1;
			// modify circular navigation
			if ( demo.next_index > demo.last )
				demo.next_index = 0;
			// re-position the overlay
			demo.isopen = true;
			demo.update();
		},
		// edit the source code of whatever is in the iframe
		edit: function(){
			// wait until the codemirror is ready
			if ( demo.codeMirrorReady ){
				// throw new code against the mirror
				demo.codemirror.setCode( demo.source );
				// toggle displays
				demo.$editor.show();
				demo.$commitlink.show();
				demo.$editlink.hide();
				demo.$iframe.hide();
			}
			return false;
		},
		// execute the edited source in the demo iframe
		commit: function(){
			// wait until the codemirror is ready
			if ( demo.codeMirrorReady ){
				// reset the code mirror history
				demo.codemirror.clearHistory();
				// extract the demo source code
				demo.source = demo.codemirror.getCode();
				// throw new code into the demo frame
				demo.$body.html( demo.source );
				// toggle displays
				demo.$editor.hide();
				demo.$commitlink.hide();
				demo.$editlink.show();
				demo.$iframe.show();
			}
			return false;
		},
		// notify when the demo frame has completely loaded
		loaded: function( win, $$ ){
			clearTimeout( demo.timer );
			// store the iframe's jQuery body instance
			demo.$body = $$('body');
			// store the iframe's window object
			demo.frame = win;
			demo.isloaded = true;
			if ( demo.source ) 
				demo.complete();
			
		},
		// execute the loaded code...
		complete: function(){
			if ( !demo.source || !demo.isloaded ) 
				return demo.error();
			// execute the source
			demo.$body.html( demo.source );
			// set the correct displays
			demo.$iframe.show();
			demo.$editor.hide();
			demo.$commitlink.hide();
			demo.$editlink.show();
			// reveal the demo contents
			demo.$box.show();
			demo.$loader.hide();	
			demo.update();
		},
		// handle ajax success calls
		success: function( txt ){
			demo.source = $.trim( txt );
			if ( demo.isloaded ) 
				demo.complete();
		},
		// handle load errors
		error: function(){
			demo.$loader.text('Load Error. Please try again.').show();
			// remove the demo contents
			demo.$box.hide();
			demo.update();
		},
		// reset things to the correct state
		reset: function(){
			demo.$box.hide();
			demo.$loader.text('Loading').show();
			demo.isopen = demo.isloaded = demo.source = false;	
		},
		// close the overlay
		close: function(){
			/*
			// restore the page scrollbars
			$('#everything')
				.css({ height:'', overflow:'' })
				.scrollTop( 0 ).scrollLeft( 0 );
			// restore the scroll position	
			demo.$doc	
				.scrollTop( demo.scroll.top )
				.scrollLeft( demo.scroll.left );
				*/
			demo.$overlay.hide();
			demo.reset();
		}
	};
});
