/*
	---------------------------------------------
	-	JS Stuff
	-	/core.js
	-	Namespace, major scripts etc...
	---------------------------------------------
	-	Author:	James Haley
	-			workrequests@sevendigits.com
	-			2010
	---------------------------------------------
	
	Copyright (c)2010 James Haley - Unless otherwise stated

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/
	
	var seven={}; // SevenDigits
	
	/*-- Flour -------------------- */
		
		//	++ Initiation
		//----------------------------------------------
		//	First run settings/animations
		
			seven.init = function() {
				// Manage sizes
				seven.setup.manageSize();
				Event.observe(window,"resize",seven.resizeTasks);
				seven.external.twitter.pull();
				
				// Manage links and sections
				seven.nav.init();
				seven.setup.skillSet.init();
				($('oShowMoreResume'))?$('oShowMoreResume').observe('click',function(){$('oResumeExtra').slideDown();$('oShowMoreResume').fade({duration:0.3});}):null;
				($('oShowLessResume'))?$('oShowLessResume').observe('click',function(){Effect.ScrollTo('oResume');$('oResumeExtra').fade({duration:1});$('oShowMoreResume').appear({duration:0.3});}):null;
				($$('.to-top-link'))?$$('.to-top-link').each(function(o){o.observe('click',function(){Effect.ScrollTo('oTopBand');});}):null;
				
			};
			
			seven.resizeTasks = function() {
				seven.setup.manageSize();
			};
		
		
		//	++ Utilities
		//----------------------------------------------
		
			(seven.utils = function() {
				return {
					rnd:function(nMax){
						nMax=nMax||1000000000;
						return Math.floor(Math.random()*nMax);
					},
					SimpleDate:function(nD){
						var oDate=new Date(nD.toRoughDate()),oNow=new Date(),nDiff=0,vDate="";
						oDate=(Date.UTC(oDate.getFullYear(),oDate.getMonth(),oDate.getDate(),0,0,0))/86400000;
						oNow=(Date.UTC(oNow.getFullYear(),oNow.getMonth(),oNow.getDate(),0,0,0))/86400000;
						nDiff=(oNow-oDate);
						if(nDiff<1){vDate="Today"}
						else if(nDiff==1){vDate="Yesterday"}
						else if(nDiff<7){vDate=nDiff+" days ago"}
						else if(nDiff<14){vDate="1 week ago"}
						else if(nDiff<31){vDate=Math.floor(nDiff/7)+" weeks ago"}
						else if(nDiff<62){vDate="1 month ago"}
						else if(nDiff<365){vDate=Math.floor(nDiff/31)+" months ago"}
						else if(nDiff<730){vDate="1 year ago"}
						else{vDate=Math.floor(nDiff/365)+" years ago"};
						return vDate;
					}
				}
			}());
	
		
		//	++ Setup
		//----------------------------------------------
		
			(seven.setup = function() {
				return {
					bIsHijacked:false,
					manageSize:function(){
						/*
							Action: 	Check viewport size and re-jigs design based on data returned
							Version:	1.0
							Returns:	-
						*/
						if(!seven.setup.bIsHijacked){ // Check if top area being used for content
							var oViewPortSize = document.viewport.getDimensions(),oH=$('oPageHeader');
							// Resize header image
							if(oViewPortSize.height<700){
								oH.addClassName('short');
							}else{
								oH.removeClassName('short');
							}
							($('oWindowBody'))?Element.fire.delay(0.6,$('oWindowBody'),'custom:filled'):null;
						}
						
						// Apply transition class after firstrun, delay 1s
						(!oH.hasClassName('heightTrans'))?Element.addClassName.delay(1,oH,'heightTrans'):null;
					},
					skillSet:function(){
						return {
							init:function(){
								$('oBright').observe('mouseover',function(){seven.setup.skillSet.enact('perfect',true);});
								$('oBright').observe('mouseout',function(){seven.setup.skillSet.enact('perfect',false);});
								$('oFaded').observe('mouseover',function(){seven.setup.skillSet.enact('almost',true);});
								$('oFaded').observe('mouseout',function(){seven.setup.skillSet.enact('almost',false);});
								$('oReallyFaded').observe('mouseover',function(){seven.setup.skillSet.enact('maybe',true);});
								$('oReallyFaded').observe('mouseout',function(){seven.setup.skillSet.enact('maybe',false);});
							},
							enact:function(vLevel,bInit){
								(bInit)?$$('.'+vLevel).each(function(o){o.addClassName('on');}):$$('.'+vLevel).each(function(o){o.removeClassName('on');});
							}
						}
					}()
				}
			}());
		
		
		//	++ Navigation Setup and Actions
		//----------------------------------------------
		
			(seven.nav = function() {
				return {
					init:function(){
						/*
							Action: 	Look for action links and apply listener to them. Also handle HTML history/popstate
							Version:	1.0
							Returns:	-
						*/
						
						// Get all internal links and apply listener
						$$('a.int-link').each(
							function(o){
								o.observe('click',function(e){
									seven.nav.action.run(true,e.element());
								});
							}
						);
						
						// Listen for popstate incase back and forward used (HTML5)
						if(m.historymanagement){
							Event.observe(window,'popstate',function(){seven.nav.action.run(false);});
						}
						
						// First-run to catch direct links
						seven.nav.action.run(false);
					},
					action:function(bLink){
						return {
							_store:[
								{
									name:	'#about',
									isPage:	false,
									state:	[
										{'ident':'oAbout','custom':false,'action':'_aniscroll'}
									]
								},
								{
									name:	'#skills',
									isPage:	false,
									state:	[
										{'ident':'oSkills','custom':false,'action':'_aniscroll'}
									]
								},
								{
									name:	'#work',
									isPage:	false,
									state:	[
										{'ident':'oWork','custom':false,'action':'_aniscroll'}
									]
								},
								{
									name:	'#resume',
									isPage:	false,
									state:	[
										{'ident':'oResume','custom':false,'action':'_aniscroll'}
									]
								},
								{
									name:	'#contact',
									isPage:	false,
									state:	[
										{'ident':'oContact','custom':false,'action':'_aniscroll'}
									]
								}
							],
							run:function(bLink,oE){
								var vHash = (!bLink)?vHash=document.location.hash:'#'+oE.href.split('#')[1];
								// Set history item if HTML5
								(bLink)?(m.historymanagement)?window.history.pushState({page: vHash}):null:null;
								
								// Get and perform actions
								seven.nav.action._store.each(
									function(o){
										if(o.name===vHash){
											// Run required actions
											o.state.each(
												function(oA){
													if(oA.custom){
														$$('#'+oA.ident).invoke(oA.action);
													} else {
														if(oA.action=='_aniscroll'){
															Effect.ScrollTo(oA.ident,{duration:0.8,offset:-20});
														}
													}
												}
											);
											throw $break;
										}
									}
								);
							}
						}
					}()
				}	
			}());
			
			
			
		//	++ Third-party integration
		//----------------------------------------------
		
			(seven.external = function() {
				return {
					twitter:function(){
						var nFailureCount=0;
						return {
							_store:[],
							bUpdateSucess:false,
							pull:function(){
								var oTweetChannel=new Element('script',{src:'http://twitter.com/statuses/user_timeline/sparkyfied.json?callback=seven.external.twitter.save'});
								$(document.body).insert(oTweetChannel);
							},
							save:function(oData){
								// Save data for later use
								seven.external.twitter._store=oData;
								// Run single tweet
								seven.external.twitter.outputSingle()
							},
							outputSingle:function(oTweet){
								var o=oTweet||seven.external.twitter._store.first(),vTweet='',vLocation='',oContainer=$('oTweetBody')||new Element('h4',{className:'light',id:'oTweetBody'});
								$('oUpdate').hide();$('oUpdateLoading').hide();
								if(o!==undefined){
									vLocation=(!o.place)?'.':' near <a href="http://maps.google.co.uk/maps?q='+o.place.full_name+'" target="_blank">'+o.place.full_name+'</a>.</span>';
									vTweet=o.text.linkify().tweetify()+' &mdash; <span class="smaller"><a href="http://twitter.com/sparkyfied/status/'+o.id+'" target="_blank">'+seven.utils.SimpleDate(o.created_at)+'</a>'+vLocation;
									if(!$('oTweetBody')){
										$('oUpdate').insert(oContainer.update(vTweet)).appear();
									} else {
										$('oTweetBody').update(vTweet);
										$('oUpdate').show();
									}
									
									// Tell other functions
									seven.external.twitter.bUpdateSucess=true;
									
									if(!$('oWindowBody')){
										$('oUpdatesMore').appear();
										$('oUpdatesMoreLink').observe('click',seven.external.twitter.outputFull.init);
										// When open these link need to perform
										$('oUpdatesEvenMoreLink').observe('click',seven.external.twitter.outputFull.close);
										$('oUpdatesClose').observe('click',seven.external.twitter.outputFull.close);
									}
								} else {
									// Show failure message
									(nFailureCount==0)?$('oUpdate').insert(oContainer.update('No updates to show at the moment.')):null;
									// Warn other functions
									seven.external.twitter.bUpdateSucess=false;
									// Try again in 30s if no refresh and increase the failure count. 
									(nFailureCount<5)?seven.external.twitter.pull.delay(30):null;
									nFailureCount++;$('oUpdatesMore').hide();
								}
							},
							outputFull:function(){
								return {
									nCurrentTweet:0,
									init:function(){
										var nPosition=$('oUpdateSection').cumulativeOffset(),oWindow=$('oTweetWindow')||new Element('div',{className:'pop-out',id:'oTweetWindow'}),oWindowBody=new Element('div',{id:'oWindowBody',className:'pop-body'});
										$('oUpdatesMore').fade({duration:0.3,queue:{position:'end',scope:'updates'}});
										$('oUpdatesMoreOptions').appear({duration:0.3,queue:{position:'end',scope:'updates'}});
										
										
										if (!$('oWindowBody')) {
											// Set custom event to move the box based on the height of 10 items
											oWindowBody.observe('custom:filled',function(){
												var nPosition=$('oUpdateSection').cumulativeOffset(),nTop=((nPosition.top)),nLeft=((nPosition.left-330)/12)+'em';
												nNewTop=(nTop-(this.offsetHeight/2));
												(nNewTop<20)?nNewTop=20:null;
												oWindow.setStyle({left:nLeft,top:(nNewTop/12)+'em'});
											});
											
											oWindow.insert(oWindowBody);
																					
											// Build contents
											oWindowBody.insert(new Element('h3').update('Older Updates.'));
											seven.external.twitter._store.each(function(o,i){
												var oUpdate = new Element('a',{href:'javascript:;',id:'oTweet'+i}).update(new Element('div',{className:'item'}).update('<h5>'+o.text.short(45)+'</h5>'));
												oUpdate.observe('click',function(){seven.external.twitter.outputFull.updatePreviewPane(i);});
												(i==0)?oUpdate.addClassName('current'):null;
												oWindowBody.insert(oUpdate);
												
												if (i==15){throw $break;};
											});
										
											// Insert into body
											$(document.body).insert(oWindow);
										} else {
											// Reset and show
											$('oTweet'+seven.external.twitter.outputFull.nCurrentTweet).removeClassName('current');$('oTweet0').addClassName('current');
											seven.external.twitter.outputFull.nCurrentTweet=0;
										};
										
										// Fire resize event
										oWindow.show();
										$('oWindowBody').fire('custom:filled');
									},
									updatePreviewPane:function(i){
										$('oTweet'+seven.external.twitter.outputFull.nCurrentTweet).removeClassName('current');$('oTweet'+i).addClassName('current');
										seven.external.twitter.outputFull.nCurrentTweet=i;
										seven.external.twitter.outputSingle(seven.external.twitter._store[i]);
									},
									close:function(){
										$('oTweetWindow').hide();
										seven.external.twitter.outputSingle(seven.external.twitter._store[0]);
										$('oUpdatesMoreOptions').fade({duration:0.3,queue:{position:'end',scope:'updates'}});
										$('oUpdatesMore').appear({duration:0.3,queue:{position:'end',scope:'updates'}});
									}
								}
							}()
						}
					}()
				}
			}());
	
			
	/*-- Salt -------------------- */
	
		//	++ Prototype implementation of Linkify
		//	++ Hat tip to Ben Alman for making such a quality plugin
		//	++ http://benalman.com/projects/javascript-linkify-process-lin/
		//----------------------------------------------
		String.prototype.linkify = function() {
			return linkify(this);
		}
		
		//	++ Replace a Twitter username with a link to that user
		//	++ Regex lifted from http://tweet.seaofclouds.com/ - Under MIT
		//----------------------------------------------
		String.prototype.tweetify = function() {
			var oUserRX=/[\@]+([A-Za-z0-9-_]+)/gi,oHashRX=/(?:^| )[\#]+([A-Za-z0-9-_]+)/gi,vReturn='';
			vReturn = this.replace(oUserRX,'<a href="http://twitter.com/$1" target="_blank">@$1</a>');
			vReturn = vReturn.replace(oHashRX,' <a href="http://search.twitter.com/search?q=$1" target="_blank" class="hash">#$1</a>');
			return vReturn;
		}
		
		//	++ Rough and Ready Date creation
		//	++ Take the date given and make it valid (very rough)
		//	++ Needs to be replaced with a fancy regex later
		//----------------------------------------------
		String.prototype.toRoughDate=function(){
			return this.replace('+0000 ','');
		}
		
		//	++ Array Remove - By John Resig (MIT Licensed)
		//----------------------------------------------
		Array.prototype.remove = function(from, to) {
			var rest = this.slice((to || from) + 1 || this.length);
			this.length = from < 0 ? this.length + from : from;
			return this.push.apply(this, rest);
		};
		
		//	++ Trim spaces
		//----------------------------------------------
		String.prototype.trim = function() {
			return this.replace(/^\s+|\s+$/,"");
		}
		
		//	++ String Trim to length or first Stop(.)
		//----------------------------------------------
		String.prototype.short = function(nLen) {
				var nFSPos=this.indexOf('.');
				return (this.length>nLen)?((nFSPos>-1)&&(nFSPos<nLen+1)&&(nFSPos>3))?this.split('.')[0].trim()+'...':this.substring(0,nLen).trim()+'...':this;
			};
		
	
	/*-- Bake -------------------- */
	
		//	++ Run Site
		//----------------------------------------------
			document.observe("dom:loaded",seven.init);

		// ++ Tidy and code laziness
		//----------------------------------------------
		
			var m = Modernizr;
