RAI = function () {
	var moduleData={},
		eventData={},
		debug=false,
		ec=0,
		createInstance = function ( moduleId ) {
			var instance = moduleData[moduleId].creator( new Sandbox() ),
				name, method;
			if( debug === true ) {
				for( name in instance ) {
					method = instance[name];
					if( typeof method == 'function' ) {
						instance[name] = function ( method, name ) {
							return function () {
								try {
									return method.apply( this, arguments );
								}
								catch( err ) {
									RAI.log( moduleId + ' - ' + name + '(): ' + err.message );
								}
							};
						} ( method, name );
					}
				}
			}
			return instance;
		};

	return {
		register: function ( moduleId, creator ) {
			moduleData[moduleId] = {
				creator: creator,
				instance: null
			};
		},
		start: function ( moduleId ) {
			moduleData[moduleId].instance = createInstance( moduleId );
			moduleData[moduleId].instance.init();
		},
		stop: function ( moduleId ) {
			var data = moduleData[moduleId];
			if( data.instance ) {
				data.instance.destroy();
				data.instance = null;
			}
		},
		startAll: function () {
			var moduleId;
			for( moduleId in moduleData ) {
				if( moduleData.hasOwnProperty(moduleId) ) {
					this.start( moduleId );
				}
			}
		},
		stopAll: function () {
			var moduleId;
			for( moduleId in moduleData ) {
				if( moduleData.hasOwnProperty(moduleId) ) {
					this.stop( moduleId );
				}
			}
		},
		addListener: function ( events, handler, ctx, allowDupes ) {
			var l = events.length,
				i = 0;
			for( i; i < l; i++ ) {
				var j = 0,
					found=false,
					m;

				if( !eventData[events[i]] ) {
					eventData[events[i]] = [];
				}

				m = eventData[events[i]].length;

				for( j; j < m; j++ ) {
					if( handler == eventData[events[i]].handler && ctx == eventData[events[i]].ctx && !allowDupes ) {
						found = true;
					}
				}
				if( !found ) {
					eventData[events[i]].push({
						handler: handler,
						ctx: ctx
					});
				}
			}
		},
		dispatchEvent: function ( msgObj ) {
			var e = msgObj.e,
				data = [],
				i = 0,
				ev, l, prop;

			for( prop in msgObj.data ) {
				data.push( msgObj.data[prop] );
			}
			for( ev in eventData ) {
				if( ev == e ) {
					l = eventData[ev].length;
					for( i; i < l; i++ ) {
						var ce = eventData[ev][i];
						ce.handler.apply( ce.ctx, data );
					}
				}
			}
		},
		removeListener: function ( e, handler, ctx ) {
			var i = 0,
				l, ce;
			if( eventData[e] ) {
				l = eventData[e].length;
				for( i; i < l; i++ ) {
					ce = eventData[e][i];

					if( ce.handler == handler && ce.ctx == ctx ) {
						eventData[e].splice( i, 1 );
						break;
					}
				}
			}
		},
		clearEventType: function ( type ) {
			if( eventData[type] ) {
				eventData[type] = [];
			}
		},
		log: function ( msg ) {
			var ret, $c;
			ec++;
			ret = 'err' + ec + ': ' + msg;
			$c = $('#console');
			if( $c.length > 0 ) {
				var orig = $c.html();
				$c.html( orig + "\n" + ret );
			}
			else if( console ) {
				console.log( ret );
			}
			else {
				return ret;
			}
		}
	};
}();

Sandbox = function () {

	return {
		listen: function ( events, handler, ctx, allowDupes ) {
			if( typeof events == 'string' ) {
				events = [events];
			}
			RAI.addListener( events, handler, ctx, allowDupes );
		},
		notify: function ( msgObj ) {
			RAI.dispatchEvent( msgObj );
		},
		kill: function ( e, handler, ctx ) {
			RAI.removeListener( e, handler, ctx );
		},
		killType: function ( e ) {
			RAI.clearEventType( e );
		},
		refresh: function () {
			RAI.stopAll();
			RAI.startAll();
		}
	};
};

RAI.register( 'adjust', function( sandbox ) {
	var _,
		wrapper, grid,
		items, count,
		iw, ih,
		cx, cy,
		center, mobile;

	return {
		init: function () {
			_ = this;
			mobile = $('body').hasClass('mobile') && !$('body').hasClass('preview');
			if( !!mobile ) return false;
	
			center = [$(window).width()/2,($(window).height())/2];
			wrapper = $("#grid-wrapper");
			grid = $('#grid');
			$('*').disableSelection();
			items = $('.grid-item');

			count = items.length;
			$(window).bind('resize', this.resize ).trigger('resize');
			$(window).bind( 'orientationchange', this.resize).trigger('orientationchange');
			items.each(_.findCenter);
			sandbox.listen('features-found',_.refilter,_);
		},
		findCenter: function (key,obj) {
			var g = $(obj),
				p = {};
			p[0] = g.data('dy');
			p[3] = g.data('dx');
			p[1] = p[3] + g.innerWidth();
			p[2] = p[0] + g.innerHeight();
			if( p[0] <= center[1] && p[2] >= center[1] && p[3] <= center[0] && p[1] >= center[0] ) {
				if( g.hasClass('logo') ) {
					return false;
				}
				else {
					//_.swapForLogo(g);
				}
			}
		},
		swapForLogo: function ( item ) {
			var logo, i, li;
			logo = items.filter('.logo').eq(0);
			i = item.index();
			li = logo.index();

			items.eq(i).replaceWith(newLogo);
			items.eq(li).replaceWith(newItem);
		},
		refilter:function ( i ) {
			items = i;
		},
		resize: function ( e ) {
			var i, dx=0, dy=0,
				c=0,
				el, focus, w, h,
				r, of;
			
			w = $(window).width();
			h = $(window).height();
			

			_.findDimensions();

			cy = Math.ceil( h/ih )+5;
			cx = Math.ceil( count / cy );

			grid.css({
				width: 3057,
				height: 3160
			});

			overflow = cx*cy >= count;
			overflowIndex = (cx*cy)%count;
			overflowValue = cx-overflowIndex;
			maxIndex = count - overflowValue;
			if( !!overflow ) {
				cy -= 1;
			}

			for( i=0; i<count; i++ ) {
				el = items.eq(i);
				r = i % (cx);
				
				items.eq(i)[((r+1) >= cx || (r+1) >= count) ? 'addClass' : 'removeClass']('omega');
				items.eq(i)[i+cx >= count ? 'addClass' : 'removeClass']('bottom');

				el.data({
					dx: dx,
					dy: dy
				});

				dx += iw;
				c++;

				if( c >= cx ) {
					dy += ih;
					dx = 0;
					c=0;
				}

			}

			focus = $('.focus').eq(0);

			fx = focus.data('dx')+(iw/2);
			fy = focus.data('dy')+(ih/2);

			sandbox.notify({
				e: 'adjust',
				data: {
					width: w,
					height: h,
					focusx: fx,
					focusy: fy,
					cx: cx,
					cy: cy
				}
			});
		},
		findDimensions: function () {
			var el = items.not('.logo').eq(0),
				w = el.width(),
				h = el.height(),
				pd = parseInt( el.css('padding-top'),10 );

			w += (2*pd)+1;
			h += (2*pd)+1;

			iw = w;
			ih = h;
		},
		destroy: function () {
			$(window).unbind( 'resize', this.resize );
		}
	};
} );

RAI.register( 'home-grid', function ( sandbox ) {
	var _,
		wrapper, grid,
		items, count,
		iw, ih,
		cx, cy,
		flyouts,
		currentIndex, c=0,
		dragged,
		exposed,
		top = [],
		bottom = [],
		topCheech,
		bottomCheech,
		featured,
		ipad,ww,wh,
		gridWidth=3057, gridHeight=3160,
		timer,
		clickTimer,
		totalHyp,
		mobile,
		dragTimer,
		timerInit,
		init = false;

	return {
		init: function () {
			_ = this;

			mobile = $('body').hasClass('mobile');

			dragged = false;
			exposed = false;
			
			wrapper = $("#grid-wrapper");
			topCheech = $('#top-cheech');
			bottomCheech = $('#bottom-cheech');
			grid = $('#grid');

			mobile = $('body').hasClass('mobile') ? true : false;

			flyouts = $('.fly-out').bind('mouseenter', _.forceClose);

			items = $('.grid-item').bind({
//				mouseenter: _.slideOut,
//				mouseleave: _.slideIn,
				click: _.loadPage,
				mousedown: _.preempt
//				click: gridClick
			});

			count = items.length;

			if( !mobile ) {
				$(window).load(function(){
					init = true;
				});

				items.not('.logo,.special').css('opacity',0.7).bind({
					mouseenter: _.fadeIn,
					mouseleave: _.fadeOut
				});

				_.findDimensions();	
				_.setCurrentIndex( $('.focus').index() );
				_.bindDrag( grid );
				_.stopDrag();

				sandbox.listen( 'adjust', _.adjust, _ );
				sandbox.listen( 'conceal', _.conceal, _ );
				sandbox.listen( 'page-ready', _.poke, _ );

				sandbox.listen('kill-drift', _.bounceKill, _);
				sandbox.listen('start-drift', _.bounceInit, _);

				$(window).bind('click',_.bounceKill);
				$(window).bind('mouseout',_.outOfBounds);
				setTimeout( _.bounceInit, 1750 );
				$(window).trigger('resize');
			}
		},
		preempt: function ( e ) {
			dragged = false;
			e.preventDefault();
		},
		fadeIn: function () {
			$(this).stop().animate({
				opacity: 1
			});
		},
		fadeOut: function () {
			$(this).stop().animate({
				opacity: 0.7
			});
		},
		bounceInit: function () {
			var targetX,targetY, hyp, frac, time;
			
			targetX = Math.ceil(Math.random()*(gridWidth-ww));
			targetY = Math.ceil(((gridHeight-wh))*Math.random());
			hyp = Math.sqrt((targetX*targetX)+(targetY*targetY));

			frac = hyp/totalHyp;
			time = 650000*frac;

			grid.animate({
				left: -targetX,
				top: -targetY
			}, time, function () {
				_.bounceInit();
			});
		},
		bounceKill: function (halt) {
			clearTimeout(timerInit);
			grid.stop();
			if( halt!==true ) timerInit = setTimeout(_.bounceInit, 10000);
			
		},
		findFeatured: function () {
			var focus = $('.focus');
			featured = $('.featured');

			focus.after(featured);
			items = $('.grid-item');
			sandbox.notify({e:'features-found',data:{items:items}});
		},
		poke: function ( page, from, to ) {
			_.expose();
		},
		expose: function () {
			exposed = true;

			var rr = Math.floor(cy/2),
				gr = cx*rr,
				gridItem = items.eq(gr),
				index = gridItem.index(),
				r = index % cx,
				row = (index-r)/cx,
				div = row * cx,
				br = gridItem.offset().top+ih,
				i, sp = $(window).height()*2,
				half = $(window).height()/2;
			
			items.each(function(key,obj){
				var g = $(obj),
					dy = g.offset().top;
				g.stop(true,true).fadeOut();
			});

			topCheech.delay(350).animate({
				height: 0
			}, function () {
				sandbox.notify({
					e: 'cheech-gone'
				});
			} );

			bottomCheech.delay(500).animate({
				top: '100%'
			}, function () {
				bottomCheech.css('display','none');
			});

		},
		conceal: function () {
			for( var i=0; i<bottom.length; i++ ) {
				$(bottom[i]).appendTo('#grid');
			}
			
			exposed = false;
			top = [];
			bottom = [];
			
			topCheech.animate({
				top: 0,
				height: '50%'
			});
			bottomCheech.css({
				display: 'block'
			}).animate({
				top: '50%',
				height: '50%'
			}, function() {
				items.each(function(){
					$(this).stop(true,true).delay(150).fadeIn(1400);
				});
			});
			$(window).trigger('resize');
		},
		slideOut: function ( e ) {},
		slideIn: function ( e, obj ) {},
		forceClose: function ( e ) {},
		loadPage: function ( e ) {
			if( !mobile && !$(this).hasClass('special') ) {
				e.preventDefault();
				var re, href, link, base;
				if( dragged === true ) {
					dragged = false;
					return false;
				}

				link = String( $(this).children('a').attr('href') );
				re = new RegExp(site_url);
				href = '#!/'+link.replace(re,'');
				window.location.hash = href;
			}
		},
		clearAll: function () {},
		focusCenter: function () {
			var x = $(window).width()/2,
				y = $(window).height()/2,
				i, el, l, r, t, b,
				featured, f;

			for( i=0; i<count; i++ ) {

				el = items.eq(i);
				l = el.data('dx')+grid.offset().left;
				r = l+iw;
				t = el.data('dy')+grid.offset().top;
				b = t+ih;
				if( l <= x && r >= x && t <= y && b >= y ) {
					el.addClass('focus').siblings().removeClass('focus');
				}
			}

			init = false;
		},
		prefocus: function ( e, cell ) {
			var el = e !== undefined ? $(this) : cell;
			el.addClass('focus').siblings().removeClass('focus');
			currentIndex = el.index();
		},
		bindDrag: function ( object ) {
			object.draggable({
				start: _.startDrag,
				drag: _.isDrag,
				refreshPositions: true,
				stop: _.stopDrag,
				handle: '.grid-item'
			});

			object.bind({
				touchstart: _.startDrag,
				touchmove: _.isDrag,
				touchstop: _.stopDrag
			});
		},
		startDrag: function ( e, ui ) {
			var focus = $(e.target);
			_.bounceKill();
		}, 
		isDrag: function ( e, ui ) {
			clearTimeout(clickTimer);
			var otop, oleft, oright, obottom, 
			object = $(this);
			dragged = true;
			cancel = false;
			force = {};
			gridHeight = 3160;
			gridWidth = 3057;
			otop = grid.offset().top;
			obottom = top + gridHeight;
			oleft = grid.offset().left;
			oright = grid.offset().left + gridWidth;

			if( otop >= 1 ) {
				force.top=0;
				cancel=true;
			}
			if( oleft >= 1 ) {
				force.left=0;
				cancel=true;
			}
			if( otop <= (wh-gridHeight) ) {
				force.top=wh-gridHeight-1;
				cancel=true;
			}
			if( oleft <= ww-gridWidth ) {
				force.left=ww-gridWidth+22;
				cancel=true;
			}
			clearTimeout(timer);
			if(!!cancel) {
				timer = setTimeout(function(){
					grid.stop().animate(force);
					e.preventDefault();
				}, 75);
			}
		},
		outOfBounds: function (e) {
			dragged = true;
			return false;
		},
		stopDrag: function ( e, ui ) {
			clearTimeout(dragTimer);
			_.focusCenter();
			//items.each( _.setSide );
			dragTimer = setTimeout(function(){
			},50);
			$(window).trigger('resize');
		},
		setSide: function( key, object ) {
			var cell = $(this),
				cellPosition = cell.data('dx') + grid.data('dx');
				cellEndPoint = cellPosition + (iw*1.5);
			
			if( cellEndPoint > ww ) {
				cell.addClass('left');
			}
			else {
				cell.removeClass('left');
			}
		},
		findDimensions: function () {
			var el = items.not('.logo').eq(0),
				w = el.innerWidth(),
				h = el.innerHeight();
			ww = $(window).width();
			wh=$(window).height();
			iw = w;
			ih = h;
		},
		setCurrentIndex: function ( index ) {
			c++;

			var buffer;
			
			buffer = _.controlCurrentIndex( index );
			if( buffer ) {
				currentIndex = index;
				_.updateData();
			}
		},
		controlCurrentIndex: function ( index ) {
			if( index >= count ) {
				return false;
			}
			else if( index < 0 ) {
				return false;
			}
			else {
				return true;
			}
		},
		updateData: function () {
			var f, l, r, t, b;

			items.eq(currentIndex).addClass('focus').siblings().removeClass('focus');
			
			f = $('.focus').eq(0);
			l = f.offset().left;
			r = l+f.width()+50;
			t = f.offset().top;
			b = t+f.height()+50;

			if( l < 0 || t < 0 || b > $(window).height() || r > $(window).width() ) {
				$(window).trigger('resize');
			}
		},
		adjust: function ( w, h, fx, fy, _cx, _cy ) {
			if( exposed === true ) {
				return false;
			}
			var sx = fx - (w/2),
				sy = fy - (h/2),
				gh;
			
			sx = sx < 0 ? 0 : sx;
			sy = sy < 0 ? 0 : sy;
			gw = 3057;
			gh = 3160;
			cx = _cx;
			cy = _cy;

			if( cy !== undefined ) {
				sy = -sy < (h-gh) ? (gh-h)+106 : sy;
			}

			if( cx !== undefined ) {
				sx = -sx < (w-gw) ? (gw-w) : sx;
			}

			totalHyp = Math.sqrt((gw*gw)+(gh*gh));
			ww = w;
			wh = h;

			sandbox.notify({
				e: 'grid-shift',
				data: {
					dx: -sx,
					dy: -sy,
					gw: gw,
					gh: gh
				}
			});
			
			items.each( _.move );

			grid.data({
				dx: -sx,
				dy: -sy
			});
		},
		refocus: function ( dir ) {
			var shift=0,
				buffer,
				mv=0,
				r=0,
				delta=0;
			
			_.clearAll();
			switch( dir ) {
				case 'up':
					shift -= (cx);
					break;
				case 'down':
					shift += (cx);
					break;
				case 'left':
					shift -= 1;
					delta = currentIndex % cx;
					if( delta + shift < 0 ) return false;
					break;
				case 'right':
					delta = currentIndex % cx;
					if( delta + shift >= cx-1 ) return false;
					shift += 1;
					break;
			}

			$('.focus').eq(0);
			
			mv = currentIndex+shift;

			buffer = _.controlShift( mv );

			if( buffer ) {
				_.setCurrentIndex( mv );
			}
		},
		controlShift: function ( mv ) {
			var delta = (mv % cx)+1;

			return  delta <= cx ? true : false;
		},
		move: function ( key, object ) {},
		destroy: function () {
			sandbox.kill( 'adjust', _.adjust, _ );
		}
	};
} );

RAI.register( 'SWFAddress', function ( sandbox ) {
	var _,
		mobile;
	return {
		init: function () {
			_ = this;
			mobile = $('body').hasClass('mobile');
			if( !!mobile ) return false;
			SWFAddress.addEventListener( SWFAddressEvent.CHANGE, _.hashChange );
		},
		hashChange: function ( e ) {
			var alias = e.path.replace(/!\//, ''),
				target = site_url+'_resources/ajax_interface/alias_lookup/'+alias,
				xhr = {};
			if( !e.pathNames[0] ) {
				sandbox.notify({e: 'conceal'});
			}
			else {
				xhr.type = 'GET';
				xhr.url = target;
				xhr.success = _.recieveData;
				xhr.error = _.error;

				$.ajax(xhr);
			}
		},
		recieveData: function ( data ) {
			sandbox.notify({
				e: 'load-page',
				data: {
					page: data
				}
			});
		},
		error: function ( xhr, error ) {
			sandbox.notify({e:'conceal'});
		},
		destroy: function () {
			SWFAddress.removeEventListener( SWFAddressEvent.CHANGE, _.hashChange );
		}
	};
} );

RAI.register( 'breadcrumbs', function ( sandbox ) {
	var _,
		wrapper,
		breadcrumbs,
		crumb,
		re,
		next,
		mobile;

	return {
		init: function () {
			_ = this;
			mobile = $('body').hasClass('mobile');
			if( !!mobile ) return false;
			re = new RegExp(site_url);
			wrapper = $("#breadcrumbs-wrapper");
			breadcrumbs = $('#crumbs');
			crumb = $('.crumb').detach();
			next = $("#next-crumbs").bind('click',_.crumbAdvance).hide();
			sandbox.listen( 'load-page', _.addCrumb, _ );
		},
		crumbAdvance: function ( e ) {
			var crumbs = $('.crumb'),
				first = crumbs.first(),
				w = first.width();

			first.animate({width:0,opacity:0},function(){
				first.appendTo(breadcrumbs);
				crumbs.last().css('width','auto');
				first.animate({width:w,opacity:1});
			});

			e.preventDefault();
		},
		hashbangify: function ( e ) {
			var link = $(this),
				href = link.attr('href').replace(re,'!/');
			window.location.hash = href;
			e.preventDefault();
		},
		addCrumb: function ( page ) {
			var name = page.name.replace(/&amp;/gi, '&'),
				url = page.url,
				cr = crumb.clone(),
				w = 0,
				cw=0;
			
			$('.crumb').each(function(){
				var obj = $(this);
				_.wipe( obj, name );
				cw += obj.innerWidth();
			});
			
			if( cw >= 780 )
				next.fadeIn();
			else
				next.fadeOut();

			cr.attr('href', url);
			cr.text( name );

			breadcrumbs.prepend( cr );
			w = cr.width();
	
			cr.css({
				opacity: 0,
				width: 0
			});

			cr.bind('click', _.hashbangify);

			cr.animate({
				width: w
			}, 750, function () {
				cr.css({
					width: 'auto'
				}).animate({
					opacity: 1
				});
			} );
		},
		wipe: function ( obj, name ) {
			if( obj.text() == name ) {
				obj.animate({
					opacity: 0,
					width: 0
				}, function () {
					obj.remove();
				} );
			}
		},
		destroy: function () {
			sandbox.kill( 'load-page', _.addCrumb, _ );
		}
	};
} );

RAI.register( 'map', function ( sandbox ) {
	var _,
		mapIcon,
		osd,
		close,
		animating = false;
	return {
		init: function () {
			_ = this;
			osd = $('.map-osd');
			close = osd.find('.close').bind('click',_.conceal);
			map = $('.map').bind('click',_.toggleMap);	
		},
		toggleMap: function ( e ) {
			osd = $(this).prev('div');
			map = $(this);
			if( !!animating ) return false;
			if( !osd.is(':visible') )
				_.expose();
			else
				_.conceal();
			animating = true;
			e.preventDefault();
		},
		expose: function () {
			osd.css({
				display: 'block',
				opacity: 0
			}).animate({
				opacity: 1
			}, function () {
				animating = false;
			} );
			
			map.addClass('active');
		},
		conceal: function (e) {
			if( e ) {
				animating =true;
				e.preventDefault();
			}
			osd.animate({
				opacity: 0
			}, function () {
				osd.css('display','none');
				animating = false;
			});
			
			map.removeClass('active');
		},
		destroy: function () {
			
		}
	};
} );

RAI.register( 'keyboard', function ( sandbox ) {
	var _, mobile;
	return {
		init: function () {
			_ = this;
			mobile = $('body').hasClass('mobile');
			if( !!mobile ) return false;
			$(window).bind('keydown', _.evaluate);
		},
		evaluate: function ( e ) {
			switch( e.keyCode ) {
				case 38:
					sandbox.notify({e: 'shift',data:{dir:'up'}});
					break;
				case 37:
					sandbox.notify({e: 'shift',data:{dir:'left'}});
					break;
				case 39:
					sandbox.notify({e: 'shift',data:{dir:'right'}});
					break;
				case 40:
					sandbox.notify({e: 'shift',data:{dir:'down'}});
					break;
				case 27:
					sandbox.notify({e:'escape'});
					break;
				case 13:
					sandbox.notify({
						e: 'select',
						data: {
							item: $('.focus').eq(0)
						}
					});
					break;
			}
		},
		destroy: function () {
			$(window).unbind('keydown', _.evaluate);
		}
	};
} );

RAI.register( 'page-manager', function ( sandbox ) {
	var _,
		images = [],
		imageContent, imageBody, textBody,
		pageCell, grid,fb,tw, mobile, mapIcon, map,
		oldPageType='',
		currentPageType='';

	return {
		init: function () {
			_ = this;
			mobile = $('body').hasClass('mobile');
			grid = $("#grid-wrapper");
			pageCell = $('#page-cell');
			fb = $('.facebook');
			tw = $('.twitter');
			pageCell = $('#page-cell');
			mapIcon = $('.map');
			map = $('.map-osd');

			if( !mobile ) {
				imageBody = $('#project-item-image-content').detach();
				textBody = $('#project-item-text-content').detach();
				aboutBody = $('#about-content').detach();

				imageBody.find('.logo').live('click',_.goHome);
				textBody.find('.logo').live('click',_.goHome);
				aboutBody.find('.logo').live('click',_.goHome);

				pageCell.css('z-index',-10);
				sandbox.listen( 'go-home', _.goHome, _ );
				sandbox.listen( 'load-page', _.loadPage, _ );
				sandbox.listen( 'cheech-gone', _.resortZ, _ );
				sandbox.listen( 'conceal', _.reseat, _ );
			}
			
			sandbox.listen( 'adjust', _.adjustImageBody, _ );
			sandbox.listen( 'select', _.select, _ );
		},
		select: function ( item ) {
			item.trigger('click');	
		},
		adjustImageBody: function ( w, h ) {},
		reseat: function () {
			$('#project-item-image-content').css('z-index',0);
			$('#project-text-image-content').css('z-index',0);
			pageCell.css('z-index',0);
			grid.css('z-index',10);
			_.wipeBoard();
		},
		resortZ: function () {
			grid.css('z-index',-10);
			$('#project-item-image-content').css('z-index',9999999);
			$('#project-item-text-content').css('z-index',9999999);
		},
		goHome: function (e) {
			history.go(-1);
			mapIcon.css('background-position','center top');
			map.css('display','none');
			if(!!e) e.preventDefault();		
		},
		fixType: function ( str, p1, offset, s ) {
			return p1.toUpperCase();
		},
		loadPage: function ( page ) {
			var type = page.type.replace( /_(\w)/gi, _.fixType ),
				fbShare = 'http://www.facebook.com/sharer.php?u='+page.url+'&t='+page.name,
				twShare = 'http://twitter.com/home?status=Currently reading '+page.url;
			pageCell.css('height','auto');
			fb.not('.footer').attr('href',fbShare);
			tw.not('.footer').attr('href',twShare);
			oldPageType = currentPageType;
			currentPageType = page.type;

			pageCell.css('z-index',2);
			_.wipeBoard();

			sandbox.listen('escape', _.escape, _);
			_[type](page);
		},
		wipeBoard: function () {
			pageCell.css('height','auto');

			if( oldPageType == 'project_item_text' && currentPageType == 'project_item_image' ) {
				pageCell.children().fadeOut(750);
			}
			else {
				pageCell.children().remove();
				$('#carousel').children().fadeOut(function(){
					$(this).remove();
				});
			}
			sandbox.kill('escape', _.escape, _);
			sandbox.kill('shift', _.watchShift, _);
		},
		escape: function () {
			sandbox.notify({e:'conceal'});
		},
		projectItemImage: function ( page ) {
			var target = site_url+'_resources/ajax_interface/children/'+page.id+'/media/',
				xhr = {};

			xhr.type = 'GET';
			xhr.url = target;
			xhr.success = function ( data ) {
				_.recieveImages( page, data );
			};
			xhr.error = _.error;

			sandbox.listen('shift', _.watchShift, _);

			$.ajax(xhr);
		},
		watchShift: function ( shift ) {
			switch( shift ) {
				case 'left':
					sandbox.notify({
						e: 'image-shift',
						data: {
							dir: -1
						}
					});
					break;
				case 'right':
					sandbox.notify({
						e: 'image-shift',
						data: {
							dir: 1
						}
					});
					break;
			}
		},
		recieveImages: function ( page, data ) {
			var bx, by, body, container, imageContent;

			container = imageBody.clone().appendTo(pageCell);
			imageContent = container.children('#project-content');
			if( oldPageType=='project_item_text' ) {
				$('#carousel').hide().fadeIn(750);
			}
			page.images = data;

			$('#project-left,#project-right')[page.images.length>1?'show':'hide']();

			container.css({
				zIndex: 0,
				display: 'block'
			});

			body = _.returnImageContent( page );

			imageContent[0].innerHTML = body;
			pageCell.css('height',imageContent.outerHeight(true)+imageContent.offset().top+120);
			sandbox.notify({
				e: 'page-ready',
				data: {
					page: page,
					from: oldPageType,
					to: currentPageType
				}
			});
			
		},
		returnImageContent: function ( obj ) {
			var str = '';

			str += '<h1 class="project-image-title din">'+obj.name+'</h1>\r\n';
			if( obj.text ) {
				str += obj.text.replace(/&amp;/gi, '&');
			}

			return str;
		},
		error: function ( jqXHR, e, settings ) {},
		aboutPage: function ( page ) {
			page.isAbout = true;
			_.projectItemText( page );
		},
		projectItemText: function ( page ) {
			var container = !!page.isAbout ? aboutBody.clone().appendTo(pageCell) : textBody.clone().appendTo(pageCell),
				title = container.children(!!page.isAbout ? '#about-title' : '#project-text-title'),
				info = container.children('#project-text-info'),
				by = info.children('#article-by'),
				source = info.children('#article-source'),
				content = container.children('#article-content'),
				image = page.image ? public_dir+'images/'+page.id+'/rai_'+page.id+'_image'+page.image : null;
			title[image !== null ? 'hide' : 'show']();
			title.text( page.name );

			if( image !== null ) {
				var img = new Image();
				img.className='header-image';
				img.width = 445;
				img.src = image;
				content.html(img);
			}
			
			content.html( content.html()+page.text2 );

			_.getTextMedia( content, page.id );

			if( page.rai_by || page.source ) {
				by.show();
				source.show();
				if( page.rai_by ) {
					by.text( page.rai_by );
				}

				if( page.source ) {
					source.text( page.source );
				}
			}
			else {
				by.hide();
				source.hide();
			}
			
			sandbox.notify({
				e: 'page-ready',
				data: {
					page: page
				}
			});
		},
		getTextMedia: function ( target, parent ) {
			var call = {};

			call.url=site_url+'_resources/text_associations/'+parent+'/';
			call.dataType='json';
			call.type='get';
			call.timeout=5000;
			call.success=function(data){
				_.imagesLoaded( target, data );
			};
			call.error=_.imageError;
			
			$.ajax(call);
		},
		imagesLoaded: function ( target, images ) {
			if( !images[0] ) return false;
			var ul = document.createElement('ul'),
				len = images.length,
				i, li, img, a;
			ul.id = 'text-page-gallery';
			target[0].appendChild(ul);
			for( i=0; i<len; i++ ) {
				li = document.createElement('li');
				li.className='text-page-gallery-item';
				if( i%3===0 ) li.className += ' alpha';
				img = new Image();
				img.src = public_dir+images[i].path;
				ul.appendChild(li);
				if( !!images[i].assoc ) {
					a = document.createElement('a');
					a.href = '#'+images[i].assoc.alias;
					li.appendChild(a);
					a.appendChild(img);
				}
				else {
					li.appendChild(img);
				}
			}

		},
		imageError: function ( e, xhr, data ) {},
		destroy: function () {
			sandbox.kill( 'load-page', _.loadPage, _ );
		}
	};
} );

RAI.register( 'carousel', function ( sandbox ) {
	var _,
		carousel,
		carouselItem,
		left, right,
		close,
		images,
		count,
		currentIndex = 0,
		animating,
		mobile,
		len,
		preview;

	return {
		init: function () {
			_ = this;
			preview = $('body').hasClass('preview');
			mobile = $('body').hasClass('mobile') && !preview;
			animating = false;
			carousel = $('#carousel');
			carouselItem = $('.img-backer');

			if( !mobile && !$('body').hasClass('preview') ) {
				carouselItem.detach();
				sandbox.listen( 'page-ready', _.loadCarousel, _ );
				sandbox.listen( 'page-ready', _.bindItems, _ );
				sandbox.listen( 'adjust', _.adjust, _ );
			}
			else {
				count = carouselItem.length;
				$(window).bind('orientationchange',_.adjust);
				_.bindItems();
				_.adjust();
			}
			if( $('body').hasClass('preview') ) sandbox.listen( 'adjust', _.adjust, _ );
			sandbox.listen( 'image-shift', _.imageShift, _ );
		},
		bindItems: function () {
			if(!mobile) close = $("#project-image-logo,#project-text-logo,#close-project").bind('click',_.goHome);
			left = $('#project-left').bind('click',_.prevItem);
			right = $('#project-right').bind('click',_.nextItem);
		},
		goHome: function ( e ) {
			sandbox.notify({
				e: 'go-home'
			});

			e.preventDefault();
		},
		prevItem: function ( e ) {
			_.setCurrentIndex(currentIndex-1);
			if(e) e.preventDefault();
		},
		nextItem: function ( e ) {
			_.setCurrentIndex(currentIndex+1);
			if(e) e.preventDefault();
		},
		imageShift: function ( dir ) {
			switch( dir ) {
				case 1:
					_.nextItem();
					break;
				case -1:
					_.prevItem();
					break;
			}
		},
		setCurrentIndex: function ( index ) {
			if( animating === true ) {
				return false;
			}

			currentIndex = index;
			_.controlCurrentIndex();
			_.updateData();
		},
		controlCurrentIndex: function () {
			if( currentIndex < 0 ) {
				currentIndex = count - 1;
			}
			else if( currentIndex >= count ) {
				currentIndex = 0;
			}
		},
		updateData: function () {
			if( !mobile && !preview ) {
				var img = new Image(),
					cell = carouselItem.clone();
				$(img).addClass('cell');
				
				cell.append(img);
				
				cell.css('opacity',0).appendTo(carousel);

				img.src = public_dir+images[currentIndex].path;

				$(img).data({
					width: images[currentIndex].width,
					height: images[currentIndex].height
				});

				$(window).trigger('resize');

				cell.animate({
					opacity: 1
				}, function () {
					cell.prevAll().remove();
					animating = false;
				});
			}
			else {
				_.mobileUpdate();
			}
		},
		mobileUpdate: function () {
			var vis = carouselItem.filter(':visible'),
				current = carouselItem.eq(currentIndex);
			vis.css('z-index',0).fadeOut();
			current.css('z-index',999).fadeIn();
			if($('body').hasClass('preview')) $(window).trigger('resize');
		},
		loadCarousel: function ( page ) {
			carousel.children().remove();
			images = [];
			
			var img;
			if( page.type == 'project_item_image' ) {
				currentIndex = 0;
				images = page.images;
				count = images.length;
				img = _.appendCarouselItem( images[0] );
				setTimeout( function () {
					$(window).trigger('resize');
				}, 15 );
				
			}
		},
		appendCarouselItem: function ( object ) {
			var cell = carouselItem.clone(),
				img = new Image();
		
			img.src = public_dir+object.path;

			$(img).data({
				width: object.width,
				height: object.height
			});

			$(img).addClass('cell');
			cell.append(img);
			
			carousel.append(cell);

			return $(img);

		},
		adjust: function ( w, h ) {
			var cells = $('.cell');
			if( !!mobile && !$('body').hasClass('preview') ) {
				switch( window.orientation ) {
					case -90:
					case 90:
						w = 1440;
						h = 1024;
						break;
					case -90:
					case 90:
					case 180:
					case 0:
						w = 600;
						h = 1280;
						break;
				}
			}

			cells.each( function ( key, object ) {
				_.stretchCell( w, h, key, object );
			} );
		},
		stretchCell: function ( w, h, key, object ) {
			var cell = $(object),
				iw = cell.data('width'),
				ih = cell.data('height'),
				a = w/h,
				ia = iw/ih,
				s = a > ia ? w/iw : h/ih,
				t=0,
				l=0;
			iw = iw*s;
			ih = ih*s;
			l = (w-iw)/2;
			t = (h-ih)/2;


			cell.css({
				width: iw,
				height: ih,
				left: l,
				top: t
			});
		},
		destroy: function () {
			sandbox.kill( 'page-ready', _.loadCarousel, _ );
			sandbox.kill( 'adjust', _.adjust, _ );
			sandbox.kill( 'image-shift', _.imageShift, _ );
		}
	};
} );

RAI.register( 'logo-manipulation', function ( sandbox ) {
	var _, logo, cx, cy, logoPlacer = {}, grid, gridItems, count,
		point = {}, dims = {}, locked, pageType, left, lower, featured,ipad;
	return {
		init: function () {
			_ = this;

			logo = $('.logo');
			
			logo.filter('.grid-item').bind({
				mouseenter: _.showFeatures,
				mouseleave: _.hideFeatures
			});
		},
		showFeatures: function ( e ) {
			$(this).find('.logo-black').stop().animate({opacity:0});
			$(this).find('.logo-white').stop().animate({opacity:1});
		},
		hideFeatures: function ( e ) {
			$(this).find('.logo-black').stop().animate({opacity:1});
			$(this).find('.logo-white').stop().animate({opacity:0});
		},
		goHome: function ( e ) {
			window.location.hash = '';
			e.preventDefault();
		},
		destroy: function () {
		}
	};
} );

RAI.register('email-box', function (sandbox) {
	var _, box, ew, eh, link, cheech, close, submit, method, action, email, msg;
	var EMAIL_REGEXP = /([A-Za-z0-9-_]+)@([A-Za-z0-9-_]+)\.(\w{2,4})(\.\w{0,4})?/;
	return {
		init: function () {
			_ = this;
			if( $('body').hasClass('mobile') ) return false;
			box = $('#email-box');
			link = $('.connect-title');
			cheech = $('#email-cheech');
			close = $('#email-close');
			submit = $('input[type="submit"]');
			email = $('input[type="email"]');
			msg = $('textarea');
			ew = box.innerWidth();
			eh = box.innerHeight();
			method = box[0].method;
			action = box[0].action;
			sandbox.listen('adjust', _.adjust, _);
			link.bind('click', _.expose);
		},
		adjust: function (w,h) {
			box.css({
				top: (h-eh)/2,
				left: (w-ew)/2
			});
		},
		expose: function (e) {
			box.fadeIn();
			cheech.css({
				opacity: 0,
				display: 'block'
			}).animate({
				opacity: '.85'
			});
			close.bind('click',_.conceal);
			cheech.bind('click',_.conceal);
			submit.bind('click',_.submit);
			sandbox.notify({e:'kill-drift',data:{halt:'true'}});
			$(window).bind('keydown',_.keypress);
			e.preventDefault();
		},
		keypress: function(e) {
			if( e.keyCode==27 ) {
				_.conceal({preventDefault:function(){return false;}})
			}
		},
		conceal: function (e) {
			box.fadeOut();
			cheech.fadeOut();
			email[0].value = '';
			msg[0].value = '';
			close.unbind('click',_.conceal);
			cheech.unbind('click',_.conceal);
			submit.unbind('click',_.submit);
			sandbox.notify({e:'start-drift'});
			e.preventDefault();
		},
		validate: function () {
			var emailAddress = email[0].value,
				validMsg = msg[0].value !== '',
				validEmail = EMAIL_REGEXP.exec(emailAddress);
			
			if( !validMsg ) {
				msg.addClass('invalid');
				msg.bind('focus',_.makeValid);
			}
			if( !validEmail ) {
				email.addClass('invalid');
				email.bind('focus',_.makeValid);
			}

			return validMsg && validEmail;
		},
		makeValid: function (e) {
			$(this).removeClass('invalid');
		},
		submit: function (e) {
			var call = {};
			
			if( !_.validate() ) return false;

			call.type = method;
			call.data = box.serialize();
			call.url = action;
			call.timeout = 5000;
			call.success = _.conceal;
			call.error = function(){};
			$.ajax(call);
		
			e.preventDefault();
		},
		destroy: function () {
			
		}
	};
});

RAI.register('ajax-analytics', function ( sandbox ) {
	var _,
		ajaxInterface = /.+\/ajax\_interface\//,
		alias_lookup = /.+\/ajax\_interface\/alias\_lookup\/(.+)$/;

	return {
		init: function () {
			_ = this;
			$(document).bind('ajaxSend', _.googleLog);
		},
		googleLog: function ( e, xhr, settings ) {
			if( typeof _gaq !== 'undefined' && _gaq !== null ) {
				if( !!ajaxInterface.exec(settings.url) ) {
					if( !!alias_lookup.exec(settings.url) ) {
						url = alias_lookup.exec(settings.url)[1];
						_gaq.push(['_trackPageview', '/'+url]);
					}
				}
				else {
					_gaq.push(['_trackPageview', settings.url]);
				}
			}
		},
		destroy: function () {
			$(document).unbind('ajaxSend', _.googleLog);
		}
	}
} );

$(function() {
	RAI.startAll();
	$(window).load(function(){
		setTimeout(function(){
			$('body').removeClass('init-hide');
			$('#grid-wrapper').css('display','block');
			}, 50 );
		$('.mobile #init-cheech').remove();
		$('#init-cheech').fadeOut(1250);
		$('.mobile #grid-wrapper').css('opacity',1);
	});

	$(window).trigger('resize');
});
