/**********************************/
/* 	PORTFOLIO JAVASCRIPT
/*  v1
/*
/*	Author: Daniel Crisp
/* 	Date: 1st June 2011
/*
/**********************************/


// Canvas var definitions

var projectCanvas, projectContext;
var randomCanvas, randomContext;

var G_vmlCanvasManager;

var numOfRandomLines = 5;
var canvasRedrawTimeout = 20;
var colourFadeSteps = 10;
var currentColour = null;
var xOffset = -0.5;
var yOffset = -0.5;

var randomContextAlpha = projectContextAlpha = 0;

var projectLines = [];
var randomLines = [];

var randomLineColours = Array("#ff00ae", "#00ff00", "#e0e0e0", "#00ccff", "#ff0000");

var drawRandomLinesTimeout, drawProjectLinesTimeout, colourFadeTimeout;

var projectBoxX, projectBoxY, projectBoxWidth, projectBoxHeight, projectLineColour;

// jQuery element vars

var $canvas, $nav, $projects, $projectInfo, $thisProjectInfo, $logoSkills, $logoSummary;

// current page status
var pageStatus = "spread";
var currentHash = "";

/* 
 * 	Start DOC READY
 */
	
$(document).ready(function(){
	
	// Save elements in vars for quick access
	$canvas = $("#canvas");
	$projects = $("#projects");
	$projectInfo = $("#project-info");
	$nav = $("nav");
	$logoSkills = $("#logo ul");
	$logoSummary = $("#logo .summary");
	// Init Canvases
	initCanvas();
	
	if(!limitedVersion){
	
		// correct anchors for proxy
		$nav.find("a").each(function(){
			if($(this).attr("href") == "#"){
				$(this).attr("href","#goto-home");	
			} else {
				$(this).attr("href",$(this).attr("href").replace("#","#goto-"));	
			}
		});
		
		// draw random lines
		drawRandomLines();
		
		// a little  bit of jquery to handle some other bits
		$projects.find("li>a").hover(function(){ 
			// stop IE adding/removing class
			$(this).stop();
			
			if(pageStatus == "spread"){
				// make sure the current LI is always on top
				$projects.find("li").css("z-index", "0");
				$(this).parent("li").css("z-index", "1"); 
				
				if(!Modernizr.csstransitions){
					
					$(this).stop().animate({ "padding-right": "160px" }, "normal", function(){
						
						$(this).addClass("over");
						
						projectBoxWidth = $(this).outerWidth();
						projectBoxHeight = $(this).outerHeight();
						projectBoxX = $(this).offset().left;
						projectBoxY = $(this).offset().top;
						projectLineColour = $(this).css("background-color");
						
						// reset alpha
						projectContextAlpha = 0;
						
						drawProjectLines();														 
					});
				}
			}
		
		}, function(){ 
			
			// stop IE adding/removing class
			$(this).stop();
			
			if(pageStatus == "spread"){
			
				$(this).removeClass("over");
				
				if(!Modernizr.csstransitions){
					$(this).removeClass("over");
					$(this).css("padding-right", "10px");
				}
				// reset the canvas - double line for opera
				
				if(Modernizr.canvas){
					projectCanvas.width = projectCanvas.width-1; 
					projectCanvas.width = projectCanvas.width+1; 
				}
				
				// clear the canvas timeouts
				clearTimeout(drawProjectLinesTimeout); 
				// reset the zindex
				$(this).parent("li").css("z-index", "0"); 
			}
		});
		
		if(document.getElementById("projects") != null){
		
			var projectLinks = document.getElementById("projects").getElementsByTagName("a");
			var projectLinksLength = projectLinks.length;
			
			for(var i=0; i<projectLinksLength; i++){
				listen("transitionend", projectLinks[i], endProjectTransition);
				listen("oTransitionEnd", projectLinks[i], endProjectTransition);
				listen("webkitTransitionEnd", projectLinks[i], endProjectTransition);
			}
		
		}
		
		$projectInfo.find("a.close").click(function(){
										   
			location.href = "#goto-home";
			return false;								   
		});
		
		//$(window).hashchange(function() {
		$(window).bind('hashchange', function() {
	
			// simple solution to stop the browser scrolling
			var proxyHash = location.hash.replace("goto-","");
			
			$thisProjectInfo = $projectInfo.find("article"+proxyHash);
			$projectInfo.find("article").removeClass("on");
			$thisProjectInfo.addClass("on");
			
			// make sure there are no OVER links
			$projects.find("li>a").removeClass("over").removeAttr("style");
			
			if( (proxyHash != "" && proxyHash != "#home") && pageStatus == "spread"){
				// this bit fires if we are changing to a project from home
								
				// clear the canvas timeouts
				clearTimeout(drawProjectLinesTimeout);
				clearTimeout(colourFadeTimeout);
				
				// reset the project canvas
				
				if(Modernizr.canvas){
					projectCanvas.width = projectCanvas.width-1; 
					projectCanvas.width = projectCanvas.width+1; 
				}
				
				//hide projects
				$projects.fadeOut("fast", function(){
											
					$projects.removeClass("spread");
					$projects.addClass("line-up");
					//store page status in var
					pageStatus = "line-up";
					// show this project
					
					$projects.find("a").removeClass("active");
					$nav.find("a").removeClass("active");
					$projects.find("a[href='"+location.hash+"']").addClass("active");
					$nav.find("a[href='"+location.hash+"']").addClass("active");
					$projects.fadeIn("fast");
					
					var leftOffset = -($projectInfo.width() * ($thisProjectInfo.index()));
					$projectInfo.find("#project-holder").css("left",leftOffset+"px");
					
					$projectInfo.fadeIn("fast", function(){
						
						$projectInfo.find("article").removeClass("on");
						$thisProjectInfo.addClass("on");
						
						// draw project lines
						projectBoxWidth = $(this).outerWidth();
						projectBoxHeight = $(this).outerHeight();
						projectBoxX = $(this).offset().left;
						projectBoxY = $(this).offset().top;
						projectLineColour = $thisProjectInfo.css("background-color");
	
						// reset alpha
						projectContextAlpha = 0;
						
						highlightLogo($thisProjectInfo);
						
						drawProjectLines();
	
						changeLineColours(projectLineColour, true);
						
						// change logo summary colour
						$logoSummary.css("color", $thisProjectInfo.css("background-color"));
						
					});
				});
				
			} else if ( (proxyHash != "" && proxyHash != "#home") && pageStatus == "line-up"){
				// this bit fires if we are changing to another project from a project 
				
				// clear the canvas timeouts
				clearTimeout(drawRandomLinesTimeout); 
				clearTimeout(drawProjectLinesTimeout);
				clearTimeout(colourFadeTimeout);
				
				$projects.find("a").removeClass("active");
				$nav.find("a").removeClass("active");
				$projects.find("a[href='"+location.hash+"']").addClass("active");
				$nav.find("a[href='"+location.hash+"']").addClass("active");
				
				var leftOffset = -($projectInfo.width() * ($thisProjectInfo.index()));
				
				$projectInfo.find("#project-holder").stop().animate({ left: leftOffset+"px" }, "slow", "easeInOutCubic", function(){
																									   
					$projectInfo.find("article").removeClass("on");
					$thisProjectInfo.addClass("on");
					
					highlightLogo($thisProjectInfo);

					if (!Modernizr.canvas && G_vmlCanvasManager != undefined) {
						// change logo summary colour
						$logoSummary.css("color", $thisProjectInfo.css("background-color"));
					}
				});
	
				// get project colour
				changeLineColours($thisProjectInfo.css("background-color"));
			
			} else if( (proxyHash == "" || proxyHash == "#home") && pageStatus == "line-up"){
				
				// this bit fires if we are going to home from a project
				
				// clear the canvas timeouts
				clearTimeout(drawRandomLinesTimeout); 
				clearTimeout(drawProjectLinesTimeout);
				clearTimeout(colourFadeTimeout);
				// clear pLines
				
				if(Modernizr.canvas){
					projectCanvas.width = projectCanvas.width-1; 
					projectCanvas.width = projectCanvas.width+1; 
				}
				
				$projects.find("a").removeClass("active");
				$nav.find("a").removeClass("active");
				$nav.find("a[href='#']").addClass("active");
	
				$projects.fadeOut("fast", function(){
					$projects.removeClass("line-up");
					$projects.addClass("spread");
					
					pageStatus = "spread";
					
					changeLineColours(null, true);
					
					$projectInfo.fadeOut("fast", function(){
						
						$projectInfo.find("#project-holder").css("left","0px");
						$projectInfo.find("article").removeClass("on");
						
						$logoSkills.find("li").stop().animate({ opacity: 0.5 }, "slow");
						
						$projects.fadeIn("fast");							  
														  
					});
					
					// reset logo summary colour
					$logoSummary.css("color", "");

				});	
			}
			
			return false;
		})
		// trigger window resize
		$(window).trigger("resize");
		
		// trigger window hashchange
		$(window).trigger("hashchange");
		
		//now fade in the projects
		$projects.fadeIn("fast");
		
		$logoSkills.find("li").animate({ opacity: 0.5 }, "fast");
		
		if(!Modernizr.hashchange){
			setInterval(checkHash, 100);
		}
	}
}); // END DOC READY

/*
 *	Window Resize listener
 */
 
$(window).resize(function() {
	if(!limitedVersion){
		// reset project canvas on window resize
		
		if(Modernizr.canvas){
			projectCanvas.width = $canvas.width();
			projectCanvas.height = $canvas.height();
		
			if(pageStatus == "line-up"){
				
				// we need to redraw project lines if a project info box is open
				// draw project lines
				projectBoxWidth = $projectInfo.outerWidth();
				projectBoxHeight = $projectInfo.outerHeight();
				projectBoxX = $projectInfo.offset().left;
				projectBoxY = $projectInfo.offset().top;
				projectLineColour = $projectInfo.find("article.on").css("background-color");		
				
				drawProjectLines();			
					
			}
		}

	
	}
}); // END WINDOW RESIZE


function endProjectTransition(){
	
	if(Modernizr.canvas){
		if(parseInt($(this).css("padding-right")) > 10){
		
			projectBoxWidth = $(this).outerWidth();
			projectBoxHeight = $(this).outerHeight();
			projectBoxX = $(this).offset().left;
			projectBoxY = $(this).offset().top;
			projectLineColour = $(this).css("background-color");
			
			//reset alpha
			projectContextAlpha = 0;
			
			drawProjectLines();
			
			$(this).addClass("over");
			
			
		} else {
			
			// reset the canvas
			// double line because opera is being weird
			projectCanvas.width = projectCanvas.width-1; 
			projectCanvas.width = projectCanvas.width+1; 
		}
	}
	
}


function highlightLogo($project){
	
	$project.find("li").each(function(){
		
		var opacity = ($(this).hasClass("yes")) ? 1 : 0.5;
		
		var classes = $(this).attr("class").split(" ");	
		var classesLen = classes.length;
		
		for(i=0; i<classesLen; i++){
			if(classes[i] != "yes" && classes[i] != "no"){
				$logoSkills.find("li."+classes[i]).stop().animate({ "opacity": opacity }, "slow");
			}
		}
	
	});
}

function initCanvas(){
	
	if(Modernizr.canvas || G_vmlCanvasManager != undefined){
		// get canvas elements
		projectCanvas = document.getElementById('project');
		randomCanvas = document.getElementById('random');
		
		if (G_vmlCanvasManager != undefined) { 
			G_vmlCanvasManager.initElement(randomCanvas);
			// we don't use the project canvas in IE so don't init
		}
		
		// set canvas contexts
		if(Modernizr.canvas){
			projectContext = projectCanvas.getContext('2d');
		}
		randomContext = randomCanvas.getContext('2d');
			
		
		// set full screen dimensions of project canvas
		projectCanvas.width = $canvas.width();
		projectCanvas.height = $canvas.height();
	} 
}

function drawRandomLines(){
	
	/*
	 * 	This function draws random lines on the canvas
	 */	
	if(Modernizr.canvas || G_vmlCanvasManager != undefined){
	 
		// clear canvas
		randomCanvas.width = randomCanvas.width-1;
		randomCanvas.width = randomCanvas.width+1;
	
		// set alpha
		randomContext.globalAlpha = randomContextAlpha;
	
		for(var i=0; i<numOfRandomLines; i++){
			
			// check if positions have already been saved
			if(randomLines[i] == undefined){
				
				// RANDOM LINE POSITION, within reason
				randomLines[i] = Array();
				randomLines[i]['x'] = Math.floor(Math.random()*300)+xOffset;
				randomLines[i]['y'] = Math.floor(Math.random()*300)+yOffset+100;
				randomLines[i]['colour'] = randomLineColours[i];
				// settings saved in variable
			}
			
			// DRAW LINE
			randomContext.beginPath();
			randomContext.lineCap = "square";
			randomContext.moveTo(randomLines[i]['x'],yOffset);
			randomContext.lineTo(randomCanvas.width,randomLines[i]['y']);
			randomContext.strokeStyle = randomLines[i]['colour'];
			randomContext.stroke();
		}
					
		if(randomContextAlpha < 1){
			// if we're not at full opacity yet then loop
			randomContextAlpha += 0.1;
			drawRandomLinesTimeout = setTimeout(drawRandomLines, canvasRedrawTimeout);
		}
	}
}

function drawProjectLines(){
	
	if(Modernizr.canvas){
		
		// reset canvas
		projectCanvas.width = projectCanvas.width-1;
		projectCanvas.width = projectCanvas.width+1;
		
		// set alpha
		projectContext.globalAlpha = projectContextAlpha;
		
		
		// draw line from top left of box to top left of screen
		projectContext.beginPath();
		projectContext.moveTo(xOffset,yOffset);
		projectContext.lineTo(projectBoxX-xOffset,projectBoxY-yOffset);
		projectContext.lineCap = "square";
		projectContext.strokeStyle = projectLineColour;
		projectContext.stroke();
		
		// draw line from bottom right of box to bottom right of screen
		projectContext.beginPath();
		projectContext.moveTo(projectBoxX+projectBoxWidth+xOffset-1,projectBoxY+projectBoxHeight+yOffset-1);
		projectContext.lineTo(projectCanvas.width-xOffset,projectCanvas.height-yOffset);
		projectContext.lineCap = "square";
		projectContext.strokeStyle = projectLineColour;
		projectContext.stroke();
		
		if(projectContextAlpha < 1){
			
			projectContextAlpha += 0.1;
			
			drawProjectLinesTimeout = setTimeout(drawProjectLines, canvasRedrawTimeout);
		}
	}
}



function changeLineColours(newColour, randomOnly){
	
	/*
	 * 	This function crossfades the colours of ALL canvas lines
	 */	
	if(Modernizr.canvas){
		
		var targetRGB;
		

		
		// first off we need to convert the new colour to the correct value
		
		if(newColour == null){
			
			// requested new colour is NULL
			// therefore we need to reset the lines back to their default colours
			// so we also set the targetRGB value as null
			targetRGB = null;
			
		} else {
			
			targetRGB = convertColour(newColour);
		}
		
		var fadeStep = 0;
		// create arrays
		var colourFadeColoursRandom = [];
		var colourFadeColoursProject = [];
		
		// now lets loop through the random lines stored in our array
		// and we'll calculate the colour steps for each line
		
		var numOfLines = randomLines.length;
		
		
		for(var i=0; i<numOfLines; i++){
		
			// for each line we need to calculate the colour steps of the fade
		
			var startRGB = convertColour(randomLines[i]['colour']);
			var sR = startRGB[0];
			var sG = startRGB[1];
			var sB = startRGB[2];
			
			var endRGB;
			
			if(targetRGB == null){
				// we must be reseting the colour to the original
				// so we need to set the targetRGB using the original array
				endRGB = convertColour(randomLineColours[i]);
			} else {
				
				// pass the targetRGB through to our endRGB value
				endRGB = targetRGB;
			}
			
			var eR = endRGB[0];
			var eG = endRGB[1];
			var eB = endRGB[2];
			
			// now we have our colours we need to calculate the difference
			// between and split the difference into steps
			
			var rDiff = (eR-sR)/(colourFadeSteps-1);
			var gDiff = (eG-sG)/(colourFadeSteps-1);
			var bDiff = (eB-sB)/(colourFadeSteps-1);
			
			colourFadeColoursRandom[i] = [];
			
			for(var n=0; n<colourFadeSteps; n++){
				
				// calculate the values for each step
				var rInt = Math.round(sR + (rDiff * n));
				var gInt = Math.round(sG + (gDiff * n));
				var bInt = Math.round(sB + (bDiff * n));
				
				// put these values into our fade array
				
				colourFadeColoursRandom[i][n] = Array(rInt, gInt, bInt);
			}
		
		}
		
		//console.log(colourFadeColoursRandom);
		
		
		if(targetRGB != null && !randomOnly){
			// we only need to colour the project lines if a new colour has been provided
			// otherwise they just disappear
				
				//alert(currentColour);
				
			var startRGB = convertColour(projectLineColour);
			var sR = startRGB[0];
			var sG = startRGB[1];
			var sB = startRGB[2];
			
			var endRGB = targetRGB;		
			var eR = endRGB[0];
			var eG = endRGB[1];
			var eB = endRGB[2];
			
			// now we have our colours we need to calculate the difference
			// between and split the difference into steps
			
			var rDiff = (eR-sR)/(colourFadeSteps-1);
			var gDiff = (eG-sG)/(colourFadeSteps-1);
			var bDiff = (eB-sB)/(colourFadeSteps-1);
			
			// make sure we're starting with an empty object
			colourFadeColoursProject = [];
			
			for(var n=0; n<colourFadeSteps; n++){
				
				// calculate the values for each step
				var rInt = Math.round(sR + (rDiff * n));
				var gInt = Math.round(sG + (gDiff * n));
				var bInt = Math.round(sB + (bDiff * n));
				
				// put these values into our fade array
				
				colourFadeColoursProject[n] = Array(rInt, gInt, bInt);
				
			}
			
			//console.log(colourFadeColoursProject);
			
		}
		
		// now we've worked out the colours we can go about applying them to all the lines
		// for this we need a recursive function which we will define inside this function
		
		
		function applyLineColours(){
			
			// clear random canvas
			randomCanvas.width = randomCanvas.width-1;
			randomCanvas.width = randomCanvas.width+1;
				
			// random lines
			for(var i=0; i<numOfRandomLines; i++){
				
				// Redraw line on canvas
				randomContext.beginPath();
				randomContext.lineCap = "square";
				randomContext.moveTo(randomLines[i]['x'],yOffset);
				randomContext.lineTo(randomCanvas.width, randomLines[i]['y']);
				
				randomLines[i]['colour'] = "rgb(" + colourFadeColoursRandom[i][fadeStep][0] + ", " + colourFadeColoursRandom[i][fadeStep][1] + ", " + colourFadeColoursRandom[i][fadeStep][2] + ")";
				
				
				randomContext.strokeStyle = randomLines[i]['colour'];
				randomContext.stroke();
				
			}
			
			
			
			if(!randomOnly){
				
				// clear project canvas
				projectCanvas.width = projectCanvas.width;
			
				// project lines
				var newProjectLineColour = "rgb(" + colourFadeColoursProject[fadeStep][0] + ", " + colourFadeColoursProject[fadeStep][1] + ", " + colourFadeColoursProject[fadeStep][2] + ")";
				
				//console.log(newProjectLineColour);
				
				// draw line from top left of box to top left of screen
				projectContext.beginPath();
				projectContext.moveTo(xOffset,yOffset);
				projectContext.lineTo(projectBoxX-xOffset,projectBoxY-yOffset);
				projectContext.lineCap = "square";
				projectContext.strokeStyle = newProjectLineColour;
				projectContext.stroke();
				
				// draw line from bottom right of box to bottom right of screen
				projectContext.beginPath();
				projectContext.moveTo(projectBoxX+projectBoxWidth+xOffset-1,projectBoxY+projectBoxHeight+yOffset-1);
				projectContext.lineTo(projectCanvas.width-xOffset,projectCanvas.height-yOffset);
				projectContext.lineCap = "square";
				projectContext.strokeStyle = newProjectLineColour;
				projectContext.stroke();
				
				// change logo summary colour
				$logoSummary.css("color", newProjectLineColour);
				
			}
			
			if(fadeStep < colourFadeSteps-1){
			
				fadeStep++;
		
				colourFadeTimeout = setTimeout(applyLineColours, canvasRedrawTimeout);
			}
		}

		// call recursive apply function
		applyLineColours();
	
	}
		
} // end changeLineColours


// convert the color to rgb from hex //
function convertColour(code) {
	//default to white
	var rgb = [255,255,255];
	if(code.substr(0, 3) == "rgb"){
		// this is an RGB colour definition
		
		code = code.replace(/rgb\(/i, "").replace(/\)/i, "");
		codeArr = code.split(",");
		
		rgb = [parseInt(codeArr[0]), 
		parseInt(codeArr[1]), 
		parseInt(codeArr[2])];
					
	} else {
		code = code.replace(/#/i, "");
		rgb = [parseInt(code.substring(0,2),16), 
		parseInt(code.substring(2,4),16), 
		parseInt(code.substring(4,6),16)];
		
	}
	return rgb;
}

function listen(evnt, elem, func) {
	if (elem.addEventListener) // W3C DOM
		elem.addEventListener(evnt,func,false);
	else if (elem.attachEvent) { // IE DOM
		var r = elem.attachEvent("on"+evnt, func);
		return r;
	}
	else window.alert('Oops');
}		

function checkHash() {
    var hash = location.hash;
    if (hash != currentHash) {
        currentHash = hash;
		$(window).trigger("hashchange");
    }
}


// hide mobile address bar
/mobile/i.test(navigator.userAgent) && !location.hash && setTimeout(function () {
  window.scrollTo(0, 1);
}, 1000);
		

