/*
 *	dn v1.2
 *
 *	changelog:
	04.11.2010 - integrated blog with google feedreader api
	17.11.2010 - added paneHeader previews
	18.11.2010 - added left and right image navigation
	08.06.2011 - added bestiary and draw link handling
	
	TODO: 

 *
 *	@author donny nguyen
 *	jQuery for donnynguyen.com
 *  all i'd like is a shout out if you're gonna use this in any way. enjoy. thanks.
 */

(function($) {

	// 04.11.2010 - blog integration 
	if (!google.feeds) google.load("feeds", "1");
	
    var firstTileInfo = "";
    var currTileInfo = "";
    var lastTile;
    var lastPane;
    var lastPaneIsOpen = false;
    var minf = 35;
	var minWidth = 842; 
    var defaultCaption = "&nbsp;";
    var defaultColour = "#ffffff";
    var defaultBackgroundColour = "#a6a6a6";
    var defaultBookmarkedBackgroundColour = "#a6a6a6";
    var firstColour = 89;
    var secondColour = 144;
    var colourThreshold = 16777215;
    var colourModes = new Array("high", "low", "off");
	var previewModes = new Array("on", "off");
    var colourModeIndex = 0;
    var clickCount = 0;
    var hoverCount = 0;
	var newsViewed = false;
	var previewWindow;
	var showPreview = false; 
	var previewIsVisible = false;
	var currentPaneImages;

    $.fn.dnBasketweave = function( options ) {
        var defaults = {
            colourModeIndex: 0, 
			duration: 400,
            minimumWidth: 30,
            minimumHeight: 35,
			maximumWidth: 548,            
            maximumHeight: 595,
            paneHeaderHeight: 35,
			fadeOutOpacity: 0.382,
			fadeTime: 618 , 
			showPreview: true ,
			previewOpacity: 0.618 ,
			numBlogEntries: 6 ,
			showRandomImage: true
        },

		// initialisations
		options = $.extend(defaults, options);
		
		$( '#left' ).css( { height: options.minimumHeight, width: options.minimumHeight, opacity:0 } );
		$( '#left' ).css('position','absolute');
		$( '#left' ).css('top','0px' );
		$( '#right' ).css( { height: options.minimumHeight, width: options.minimumHeight, opacity:0 } );
		$( '#right' ).css('position','absolute');
		$( '#right' ).css('top','0px' );
		$( '#home' ).css( { height: options.minimumHeight, opacity:0 } );
		$( "#home" ).css( 'position', 'absolute' );
		$( "#home" ).css( "top", "0px" );
		
		switch( colourModeIndex ){
			case 0:
				$("#home").css("color","#ffffff");
				break;
			case 1:
				$("#home").css("color","#a6a6a6");
				break;
			case 2:
				$("#home").css("color","#a6a6a6");
				break;
		}
		
		// set the widths according the browser size at load time
		var w = Math.max( minWidth , $(window).width() ); 
		
		$( '#header' ).css({ marginLeft : "16.1%", marginRight:"16.1%" });		
		//$( '#nav' ).css({ width : '79.9%' , marginLeft : "19.1%" });		
		$( '#content' ).css({ width : '100%' });		
		$( '#info' ).css({ width: '100%' });		
		$( '#infoPane' ).css({ paddingLeft : "19.1%" , paddingRight : "19.1%" });		
		$( '#footer' ).css({ width : '100%' });		
		$( '.legalese' ).css({ paddingRight: '19.1%' });
		$( '.pane' ).css({ height: options.paneHeaderHeight	});		
		$( '.paneHeader' ).css({ paddingLeft: '19.1%' , paddingRight: '19.1%' });
		$( '#news' ).css('border-bottom' , '1px solid ' + defaultBackgroundColour );
		
		$(window).scroll( function() {
			$('#left').css('top',$(this).scrollTop() );
			$('#right').css('top',$(this).scrollTop() );
			$('#home').css('top',$(this).scrollTop() );
		});
		
		// 04.11.2010 - nav fadeout
		$('#nav').animate( { opacity:options.fadeOutOpacity }, options.fadeTime );
			
		$('#nav').hover(
			function() {
				$('#nav').stop().animate( { opacity:1.0 }, options.fadeTime  );
			},
			function() {
				$('#nav').stop().animate( { opacity:options.fadeOutOpacity }, options.fadeTime );
			}
		)		
		
		$("#left").hover(
			function() {
				$("#left").stop().animate( { opacity:1.0 }, options.fadeTime  );
			},
			function() {
				$('#left').stop().animate( { opacity:options.fadeOutOpacity }, options.fadeTime );
			}
		)
		$("#right").hover(
			function() {
				$("#right").stop().animate( { opacity:1.0 }, options.fadeTime  );
			},
			function() {
				$('#right').stop().animate( { opacity:options.fadeOutOpacity }, options.fadeTime );
			}
		)
		$("#home").hover(
			function() {
				$("#home").stop().animate( { opacity:1.0 }, options.fadeTime  );
			},
			function() {
				$('#home').stop().animate( { opacity:options.fadeOutOpacity }, options.fadeTime );
			}
		)
		
		
		// set the colour mode based on the page's configuration
        colourModeIndex = options.colourModeIndex;
		$("#colourMode").attr("innerHTML", colourModes[colourModeIndex]);
		
		// 16.11.2010 - set the prevew mode
		showPreview = options.showPreview;
		$("#previewToggle").attr("innerHTML", options.showPreview ? previewModes[0] : previewModes[1] );
				
        /*
         *	helpPane click event
         */
        $(".helpPane").click(function() {

            HandlePaneEvents(this, false);
			ToggleControls( false );
			
            //ChooseNextColours();
        }); // end helpPane click

        /*
         *	infoPane click event
         */
        $(".infoPane").click(function() {
			/*if( this.id == 'bestiary' ){
				window.location = $( '#bestiary > div > a' ).attr('href');
			}
			else if( this.id == 'draw' ){
				window.location = $( '#draw > div > a' ).attr('href');
			}
			else {*/
				HandlePaneEvents(this, true);
				//ChooseNextColours();
				ToggleControls( false );
			//}
        }); // end infoPane click

        /*
         *	pane click event
         */
        $(".pane").click(function() {
			
			if( this.id == 'bestiary' ){
				window.location = $( '#bestiary > div > a' ).attr('href');
				return false;
			}
			else if( this.id == 'draw' ){
				window.location = $( '#draw > div > a' ).attr('href');
				return false;
			}

            clickCount += 1;
            ShowActionCount();
			if( showPreview ){
				if( previewIsVisible ){
					HandlePaneEvents(this, true, $(preview).attr("src"));
				}
				else{
					HandlePaneEvents(this, true);
				}
			}
			else{
				HandlePaneEvents(this, true);
			}
            //ChooseNextColours();
        }); // end pane click

		$('#news').click( function() {
			$( this ).css( 'border-bottom' , 'none' );
			ToggleControls( false );
		});

        /*
        *	tile click event
        */
        // $("a").bind( "dblclick", function() { 
        // if( this.id != "colourMode" && this.id != "ext" ) {
        // alert("piece was double-clicked!");
        // }
        // return false;
        // })

        /*
        *	tile click event
        */
        $("a").click(function() {
            clickCount += 1;
            ShowActionCount();

            if (this.id == "colourMode") { // change the colour mode
                colourModeIndex = (colourModeIndex + 1) % 3;
                $("#colourMode").attr("innerHTML", colourModes[colourModeIndex]);
                return false;
            }
			else if (this.id == "previewToggle") { // 16.11.2010 toggle previews
				if( $("#previewToggle").attr("innerHTML") == ( previewModes[0] ) ) {
					$("#previewToggle").attr("innerHTML" , previewModes[1] );				}
				else{
					$("#previewToggle").attr("innerHTML" , previewModes[0] );				
				}
				showPreview = !showPreview
				return false;
			}
            else if (this.id == "permalink") {
                ShowMessage(window.location);
				ChooseNextColours();
                return false;
            }
            else if (this.id == "bookmark") {
             
                var paneRef = "#" + $("." + $(this).attr("title")).parent().parent().parent().attr("id");
				
				// 11.04.2010 - adjust pane height
				var pHeight = GetPaneHeight( paneRef );				
                var tileRef = paneRef + " ul > li > ." + $(this).attr("title")
                var tileWidth = $(tileRef + " > img").width();
                var currentCaption = $(tileRef).attr("title");

                if (currentCaption == undefined || currentCaption.length < 1) {
                    currentCaption = defaultCaption;
                }

				// close the news pane
                ClosePane("#newsPane", false);
				
				// open the bookmarked pane
				OpenPane( paneRef, true, pHeight );
				
				//sent the background colour
				//$(paneRef).css("background-color", ColourValue(firstColour, secondColour));
				SetCaption(paneRef + " > .caption", currentCaption, (colourModeIndex < 2));
				
				// $(paneRef + ' > .paneHeader').css("background-color", ColourValue(firstColour, secondColour));
				// $(paneRef + ' > .paneHeader').css("color", '#ffffff');
				// $(paneRef + ' > .paneHeader').css("color", ColourComplement( ColourValue(firstColour, secondColour) ) );
				
                OpenTile(tileRef, false, tileWidth);

                lastTile = $(tileRef).get(0);
                lastPane = $(paneRef).get(0);
                lastPaneIsOpen = true;
                SetHash($(this).attr("title"));

                if( colourModeIndex < 2 ) {
					// set the pane's colour to the next colour
					ChooseNextColours();					
					$(paneRef).css("background-color", ColourValue(firstColour, secondColour));
					// set the pane header's colour to the pane's colour complement
					$(paneRef + ' > .paneHeader').css("background-color", ColourComplement(ColourValue(firstColour, secondColour)));
					
				}
				else {
					// no background color for the pane header so reverse the background and fore colours
					$(paneRef + " > .paneHeader ").css("background-color", defaultColour);
					$(paneRef + " > .paneHeader ").css("color", defaultBackgroundColour);

                }				
				
				$('html, body').animate( {scrollTop: $(paneRef).position().top }, {queue:false, duration:options.duration} );	
				if( lastPaneIsOpen ){
					ToggleControls( true );
				}
                return false;
            }
            else if (this.id != "ext" ) { // panel and tile events
			
                currTileInfo = this.innerHTML;
                var currentCaption = $(this).attr("title");
                var captionRef = "#" + $(this).parent().parent().parent().get(0).id + " > .caption";
                var tileWidth = $("." + $(this).attr("class") + " > img").width();

                if (tileWidth == undefined || tileWidth < 1) {
                    tileWidth = options.maximumWidth;
                }

                if (currentCaption.length < 1) {
                    currentCaption = defaultCaption;
                }

                if (lastTile == undefined) {
                    // all tiles are closed
                    OpenTile(this, false, tileWidth);
                    SetCaption(captionRef, currentCaption, true);
                    lastTile = this;
                    SetHash($(this).attr("class"));
                }
                else { 
                    CloseTile(lastTile, false);
					
                    if (lastTile != this) {
                        OpenTile(this, false, tileWidth);
                        SetCaption(captionRef, currentCaption, true);
                        SetHash($(this).attr("class"));
                        lastTile = this;
                    }
                    else {
                        SetCaption(captionRef, defaultCaption, true);
                        RemoveHash();
                        lastTile = undefined;
                    }
                }

                if (colourModeIndex < 1) {
                    ChooseNextColours();
                }

                // stop any pane animation
                return false;
            } // otherwise the link is external so redirect 
        });

		/*
		 *	18.11.2010 - close the current tile and open the next one
		 */
		$("#left").click( function() {
			
			if( lastPaneIsOpen ){

				// get the image of the currently displayed image
				var currentImageIndex = 0;
				
				// get the list of images in the currently open pane
				currentPaneImages = new Array( $( '#' + lastPane.id + ' > ul > li > a > img ' ).size() );

				// note the class names and the index of the image whose class name matches the currently displayed image
				$('#' + lastPane.id + ' > ul > li > a ').each( function( index ) {
					currentPaneImages[index] = $(this).attr("class");						
					if( currentPaneImages[index] == window.location.hash.substr(1) ){
						currentImageIndex = index;
					}				
				});
				
				CloseTile( '.' + currentPaneImages[currentImageIndex], false );

				if( currentImageIndex - 1 >= 0 ){

					var tWidth = $( '.' + currentPaneImages[currentImageIndex-1] + ' > img ' ).width();
					OpenTile( '.' + currentPaneImages[currentImageIndex-1], false , tWidth );

					SetCaption( '#' + lastPane.id + " > .caption ", $( '.' + currentPaneImages[currentImageIndex-1] ).attr("title") );
					window.location.hash = currentPaneImages[ currentImageIndex-1 ] == undefined ? "" : currentPaneImages[ currentImageIndex-1 ];								
					lastTile = $( tileRef ).get(0);
				
				}
				else{

					/*
					SetCaption( '#' + lastPane.id + " > .caption ", "" );
					window.location.hash = "";
					var previousPane = lastPane;
					ClosePane( "#" + lastPane.id , false );
					*/
					var previousPane = lastPane;
					var currentPaneIndex = 0;
					var paneList = new Array( $( "#content > div" ).size() );
					
					$( "#content > div" ).each( function( index ) {
						paneList[index] = "#" + $(this).attr("id");
						if( $(this).attr("id") == previousPane.id ){
							currentPaneIndex = index;							
						}
					});

					var newPaneIndex = ( currentPaneIndex - 1 + paneList.length ) % ( paneList.length );

					// 08.06.2011 - don't navigate to the bestiary
					if( paneList[newPaneIndex] == '#bestiary' ){
						newPaneIndex = paneList.length-2;
					}
					/*var pHeight = GetPaneHeight( paneList[newPaneIndex] );	

					OpenPane( paneList[ newPaneIndex ], true, pHeight );
					scrollToPane( previousPane, paneList[newPaneIndex] );*/
					ChooseNextColours();

					var tileSrc = $( paneList[newPaneIndex] + " ul > li > a > img:last " ).attr("src");
					
					HandlePaneEvents( $(paneList[newPaneIndex]).get(0) , true, tileSrc ); 

					switch( colourModeIndex ){
						case 2:
							break;
						case 1:
							
							$( $(previousPane).id + " > .paneHeader " ).css( 'background-color' , ColourValue(firstColour, secondColour) );
							$( $(previousPane).id + " > .paneHeader" ).css( 'color' , '#ffffff' );
							$( previousPane ).css( 'background-color' , defaultBackgroundColour );
							$( previousPane ).css( 'color', defaultColour );
							
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'background-color' , '#ffffff' );
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'color' , defaultBackgroundColour  );
							break;
						case 0: 
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'background-color' , ColourValue(firstColour, secondColour) );
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'color' , '#ffffff' );

							break;						
					}					
				}
				
			}
			else{
				//open the first pane and the first image
				var paneRef = $( "#content > div:last" );
				var tileSrc = $( "#" + $(paneRef).attr("id") + " > ul > li > a > img:last" ).attr("src");
				HandlePaneEvents( paneRef.get(0), true , tileSrc);

					switch( colourModeIndex ){
						case 2:
							break;
						case 1:
							
							$( $(previousPane).id + " > .paneHeader " ).css( 'background-color' , ColourValue(firstColour, secondColour) );
							$( $(previousPane).id + " > .paneHeader" ).css( 'color' , '#ffffff' );
							$( previousPane ).css( 'background-color' , defaultBackgroundColour );
							$( previousPane ).css( 'color', defaultColour );
							
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'background-color' , '#ffffff' );
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'color' , defaultBackgroundColour  );
							break;
						case 0: 
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'background-color' , ColourValue(firstColour, secondColour) );
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'color' , '#ffffff' );

							break;						
					}					
			}
			ChooseNextColours();
		});
		
		$("#right").click( function() {
			
			if( lastPaneIsOpen ){

				// get the image of the currently displayed image
				var currentImageIndex = 0;
				
				// get the list of images in the currently open pane
				currentPaneImages = new Array( $( '#' + lastPane.id + ' > ul > li > a > img ' ).size() );

				// note the class names and the index of the image whose class name matches the currently displayed image
				$('#' + lastPane.id + ' > ul > li > a ').each( function( index ) {
					currentPaneImages[index] = $(this).attr("class");						
					if( currentPaneImages[index] == window.location.hash.substr(1) ){
						currentImageIndex = index;
					}				
				});
				
				CloseTile( '.' + currentPaneImages[currentImageIndex], false );

				// last image in the current pane?
				if( currentImageIndex < currentPaneImages.length - 1){

					var tWidth = $( '.' + currentPaneImages[currentImageIndex+1] + ' > img ' ).width();
					OpenTile( '.' + currentPaneImages[currentImageIndex+1], false , tWidth );
					SetCaption( '#' + lastPane.id + " > .caption ", $( '.' + currentPaneImages[currentImageIndex+1] ).attr("title"), true );
					window.location.hash = currentPaneImages[ currentImageIndex+1 ] == undefined ? "" : currentPaneImages[ currentImageIndex+1 ];			
					lastTile = $( tileRef ).get(0);
				
				}
				else{

					/*
					SetCaption( '#' + lastPane.id + " > .caption ", "" );
					window.location.hash = "";
					var previousPane = lastPane;
					ClosePane( "#" + lastPane.id , false );
					*/
					var previousPane = lastPane;
					var currentPaneIndex = 0;
					var paneList = new Array( $( "#content > div" ).size() );
					
					$( "#content > div" ).each( function( index ) {
						paneList[index] = "#" + $(this).attr("id");
						if( $(this).attr("id") == previousPane.id ){
							currentPaneIndex = index;							
						}
					});

					var newPaneIndex = ( currentPaneIndex + 1 /*+ paneList.length*/ ) % ( paneList.length );

					// 08.06.2011 - don't navigate to the bestiary
					if( paneList[newPaneIndex] == '#draw' ){
						newPaneIndex = 1;
					}

					/*var pHeight = GetPaneHeight( paneList[newPaneIndex] );	

					OpenPane( paneList[ newPaneIndex ], true, pHeight );
					scrollToPane( previousPane, paneList[newPaneIndex] );*/
					ChooseNextColours();


					var tileSrc = $( paneList[newPaneIndex] + " ul > li > a > img:first " ).attr("src");
	
					HandlePaneEvents( $(paneList[newPaneIndex]).get(0) , true, tileSrc ); 

					switch( colourModeIndex ){
						case 2:
							break;
						case 1:
							
							$( $(previousPane).id + " > .paneHeader " ).css( 'background-color' , ColourValue(firstColour, secondColour) );
							$( $(previousPane).id + " > .paneHeader" ).css( 'color' , '#ffffff' );
							$( previousPane ).css( 'background-color' , defaultBackgroundColour );
							$( previousPane ).css( 'color', defaultColour );
							
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'background-color' , '#ffffff' );
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'color' , defaultBackgroundColour  );
							break;
						case 0: 
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'background-color' , ColourValue(firstColour, secondColour) );
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'color' , '#ffffff' );

							break;
						
					}					
					
				}
			}
			else{
				//open the first pane and the first image
				var paneRef = $( "#content > div:first" );
				var tileSrc = $( "#" + $(paneRef).attr("id") + " > ul > li > a > img:first" ).attr("src");
				HandlePaneEvents( paneRef.get(0), true , tileSrc);

					switch( colourModeIndex ){
						case 2:
							break;
						case 1:
							
							$( $(previousPane).id + " > .paneHeader " ).css( 'background-color' , ColourValue(firstColour, secondColour) );
							$( $(previousPane).id + " > .paneHeader" ).css( 'color' , '#ffffff' );
							$( previousPane ).css( 'background-color' , defaultBackgroundColour );
							$( previousPane ).css( 'color', defaultColour );
							
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'background-color' , '#ffffff' );
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'color' , defaultBackgroundColour  );
							break;
						case 0: 
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'background-color' , ColourValue(firstColour, secondColour) );
							$( paneList[newPaneIndex] + " > .paneHeader" ).css( 'color' , '#ffffff' );

							break;						
					}					
				
			}
			ChooseNextColours();
		});

		$( "#home" ).click( function() {
			$('html, body').animate( { scrollTop: 0 } );			
			$(this).animate( {opacity:0}, {duration:options.fadeTime} );
		});
		
        /*
         *	hover actions
         */
        $(".paneHeader").hover(
			function() {
			    hoverCount += 1;
			    ShowActionCount();
			    //$(this).addClass(this.id).fadeIn();		
			    if (colourModeIndex < 2) {
					ChooseNextColours();
			        $(this).css("background-color", ColourValue(firstColour, secondColour));
			        //ChooseNextColours();
			        // $(this).css("color", ColourValue(firstColour, secondColour));
					// $(this).css("color", ColourComplement(ColourValue(firstColour, secondColour)));
					$(this).css("color", defaultColour);			        
			    }
				else {
					$(this).css("background-color", defaultBackgroundColour);
					$(this).css("color", defaultColour);
				}
			},
			function() {
			    //$(this).removeClass(this.id);
			    if (colourModeIndex > 0) {
			        //if( !lastPaneIsOpen ) {
			        $(this).css( 'background-color', defaultColour);
			        $(this).css( 'color', defaultBackgroundColour);
			        //}
			    }
				hide();
			}
		);
		
		// 15.11.2010 - added for image previews
		$('.paneHeader').mouseenter( function(e) {

			//if( options.showPreview ) {
			if( showPreview ) {
			
				if( !lastPaneIsOpen || (lastPaneIsOpen && lastPane.id != $(this).parent().attr("id") ) ) {
			
				if( $(this).parent().attr('class') == "pane" ){			
					previewWindow = ( previewWindow || ( previewWindow = $('<div id="preview"></div>')
						.css({
							width: 1 ,
							height: 1 ,
							position: 'absolute' ,
							overflow: 'hidden' ,
							opacity: options.previewOpacity
						})
						.append( preview = $('<img id="previewImage" src="" style="height:100%"/>')
							.css({
								position: 'absolute' ,
								cursor: 'none'
							}))
						.mousemove( move )
						.appendTo( 'body' )
					)).show();
					previewIsVisible = true;

					
					move( e , $( this ).parent().attr('id') );
				}
				}
			}
		});
		
		$(".paneHeader").mouseout( function() {
			//if( options.showPreview ){	
			if( showPreview ){	
				hidePreview();
			}
		});
		
		$('.paneHeader').mousemove( function(e) {
			//if( options.showPreview ){	
			if( showPreview ){	
				move( e , $(this).parent().attr('id') );
			}
		});

        $("a").hover( function() {
			    hoverCount += 1;
			    ShowActionCount();
			    //$(this).addClass(this.id).fadeIn();		
			    if (colourModeIndex < 2) {
			        //$(this).css( "background-color" , ColourValue( firstColour , secondColour ) );
			        ChooseNextColours();
			        // $(this).css( "color" , ColourValue( firstColour , secondColour ) );
			        // ChooseNextColours();
			    }
			} /*,
			function() {
				//$(this).removeClass(this.id);
				if( colourModeIndex > 0 ) {
					//if( !lastPaneIsOpen ) {
						$(this).css( "background-color" , defaultColour );
						$(this).css( "color", "#a6a6a6" );
					//}
				}
			}*/
		);

        /*
         *	calculate a colour value
         */
        ColourValue = function(colour1, colour2) {
            var s = "000000" + ((colour1 + colour2) % colourThreshold).toString(16);
            var len = s.length;
            s = s.substr(len - 6, 6);
            //if( colour1 + colour2 > 255 )

            return "#" + s;
        }

        /*
         *	return a hex colours colours complement
         */
        ColourComplement = function(hexColourValue) {
            
            hexColourValue = hexColourValue.toString().replace('#', '');

            var hexR, hexG, hexB;
            var r, g, b;
            var compR, compG, compB;
            var min, max, delta;
            var hue, saturation, luminosity;
            var compHue;
            var deltaR, deltaG, deltaB;
            var v1, v2, vh;

            hexR = hexColourValue.toString().substr(0, 2);
            hexG = hexColourValue.toString().substr(2, 2);
            hexB = hexColourValue.toString().substr(4, 2);

            r = parseInt(hexR, 16) / 255;
            g = parseInt(hexG, 16) / 255;
            b = parseInt(hexB, 16) / 255;

            min = Math.min(r, g, b);
            max = Math.max(r, g, b);
            delta = max - min;

            // determine the luminosity value
            luminosity = (max + min) / 2;

            if (delta == 0) {
                hue = 0;
                saturation = 0;
            }
            else {
                // determine the saturation value
                if (luminosity < 0.5) {
                    saturation = delta / (max + min);
                }
                else {
                    saturation = delta / (2 - max - min);
                }

                deltaR = (((max - r) / 6) + (delta / 2)) / delta;
                deltaG = (((max - g) / 6) + (delta / 2)) / delta;
                deltaB = (((max - b) / 6) + (delta / 2)) / delta;

                // determine the hue value
                if (r == max) {
                    hue = deltaB - deltaG;
                }
                else if (g == max) {
                    hue = (1 / 3) + deltaR - deltaB;
                }
                else if (b == max) {
                    hue = (2 / 3) + deltaG - deltaR;
                }

                if (hue < 0) {
                    hue += 1;
                }

                if (hue > 1) {
                    hue -= 1;
                }

                
            }
            //alert( 'hue: ' + hue + ' | saturation: ' + saturation + ' | luminosity: ' + luminosity );
            compHue = hue + 0.5;

            if (compHue > 1) {
                compHue -= 1;
            }

            // start converting back...
            if (saturation == 0) {
                compR = luminosity * 255;
                compG = luminosity * 255;
                compB = luminosity * 255;
            }
            else {
                if (luminosity < 0.5) {
                    v2 = luminosity * (1 + saturation);
                }
                else {
                    v2 = (luminosity + saturation) - (saturation * luminosity);
                }
            }
            v1 = 2 * luminosity - v2;
            compR = 255 * HueToRGB(v1, v2, compHue + (1 / 3));
            compG = 255 * HueToRGB(v1, v2, compHue);
            compB = 255 * HueToRGB(v1, v2, compHue - (1 / 3));
			
			var len;
			hexR = '0' + Math.round(compR).toString(16);
			len = hexR.length;
			hexR = hexR.substr( len - 2 , 2 );
			
			hexG = '0' + Math.round(compG).toString(16);
			len = hexG.length;
			hexG = hexG.substr( len - 2 , 2 );
			
			hexB = '0' + Math.round(compB).toString(16);
			len = hexB.length;
			hexB = hexB.substr( len - 2 , 2 );
			
            //alert( 'r: ' + hexR + ' | g: ' + hexG + ' | b: ' + hexB );
            return '#' + hexR + hexG + hexB;
        }

        /*
         *	convert hue to rgb
         */
        HueToRGB = function(v1, v2, vh) {
            if (vh < 0) {
                vh += 1;
            }
            if (vh > 1) {
                vh -= 1;
            }
            if ((6 * vh) < 1) {
                return (v1 + (v2 - v1) * 6 * vh);
            }
            if ((2 * vh) < 1) {
                return v2;
            }
            if ((3 * vh) < 2) {
                return (v1 + (v2 - v1) * ((2 / 3 - vh) * 6));
            }
            return v1;
        }

        /*
         *	close a tile
         */
        ChooseForeColour = function(colour) {
            if (colour > (colourThreshold / 2)) {
                return "#FFFFFF";
            }
            else {
                return "#000000";
            }
        }

        /*
         *	close a tile
         */
        ChooseNextColours = function() {

            var tempColour = secondColour;
            secondColour += firstColour;
            firstColour = tempColour;
			
            if (!isFinite(firstColour) || !isFinite(secondColour) || !isFinite(firstColour + secondColour)) {
			
                firstColour = 89;
                secondColour = 144;
            }
        }

        /*
         *	close a tile
         */
        CloseTile = function(tile, queueAnimation) {
            $(tile).animate({ width: options.minimumWidth }, { queue: queueAnimation, duration: options.duration });
            HideMessage();
        }

        /*
         *	close a pane
         */
        ClosePane = function(pane, queueAnimation) {
            $(pane).animate({ height: options.minimumHeight }, { queue: queueAnimation, duration: options.duration });
			lastPane = undefined; 
			lastPaneIsOpen = false; 
            HideMessage();
        }

        /*
         *	get the next colour value
         */
        GetNextColourValue = function(colour1, colour2) {
            var tempColour = colour2;
            colour2 += colour1;
            colour1 = tempColour;
            return ColourValue(colour1, colour2);
        }

        /*
         *	handle pane events
		 *
		 *	@parameter base:			the pane to handle
		 *	@parameter changeColours:	pass true to allow for colour change
		 *	@parameter base:			optional tile to open
         */
        HandlePaneEvents = function(base, changeColours, tileSrc) {

            //clickCount += 1;

            // the open pane is to be closed
            if (lastPane == base && lastPaneIsOpen == true) {
                // close all tiles in the currently opened pane before closing the pane
                CloseTile("#" + base.id + " > ul > li > a", false);                
                SetCaption("#" + base.id + " .caption", defaultCaption);
                RemoveHash();
                lastTile = undefined;

                ClosePane(lastPane, false);

                if (colourModeIndex < 2) {
                    ChooseNextColours();
                }
				
				// 22.11.2010 - left/right navigation added
				$("#ctrl").animate( { opacity:0 } , { duration: options.fadeTime } );
            }
            else { // a pane different from the previous one was clicked

                // 11.17.2010 - determine the last pane's top position to align the pane with the top of the window
				var lastPaneTopPosition = 0;
				var topPosition = 0;	
				var lastPaneHeight = 0;
				var baseHeight = parseInt( $(base).parent().css("height").replace("px","") );
				var scrollx = 0;
				var previousPane;
				
                if (changeColours) {
                    if (colourModeIndex < 2) {
					
                        //$(base).css("background-color", ColourValue(firstColour, secondColour));
						$( base ).css( 'background-color' , ColourComplement( ColourValue(firstColour, secondColour) ) );
						$(base).css("color", '#ffffff');
						
						// 07.06.2011 - infoPanes should have slightly different colouring
						$( '#' + $(base).attr('id') + ' > div > .generalContent' ).css( 'color' , ColourValue(firstColour, secondColour) );
						
						//23.11.2010 						
						if( colourModeIndex == 0 ){
							$( "#home" ).css( "color", "#ffffff" );
						}
						else{
							$( "#home" ).css( "color", "#a6a6a6" );
						}
                    }
                    else {
                        $(base).css( 'background-color' , defaultBackgroundColour);
                        $(base).css( 'color' , defaultColour);
						
						//23.11.2010 
						$( "#home" ).css( "color", "#a6a6a6" );
                    }
                }

                if (lastPane != undefined) // a pane was previously open...
                {
					/*// 11.17.2010 - determine the last pane's top position
					lastPaneTopPosition = $( lastPane ).position().top; 
					lastPaneHeight = parseInt( $( lastPane ).css("height").replace("px",""));*/
					previousPane = lastPane;
                    // ...so close all tiles in the last opened pane
                    $("#" + lastPane.id + " > ul > li > a").animate({ width: options.minimumWidth }, { queue: false, duration: options.duration });
                    SetCaption("#" + lastPane.id + " > .caption", defaultCaption);
                    lastTile = undefined;
                    
                    ClosePane(lastPane, false);
                }
				else{
					lastPaneHeight = options.minimumHeight;
				}

				// 04.11.2010 - determine the height of the largest image and use that to size the pane's height
				var pHeight = 0;
				var paneClass = $( base ).attr( 'class' );

				if( paneClass == 'pane' ){
					$('#' + base.id + ' > ul > li > a > img ').each( function( index ) {
						if( $(this).attr( 'height' ) > pHeight ){
							pHeight = $( this ).attr( 'height' );
						}
					});
					pHeight += 3 * options.minimumHeight;
				}
				else{				
					$( '#' + base.id + ' > * ' ).each( function( indexOf ) {
						pHeight += $( this ).height();
					});
					pHeight += options.minimumHeight;
				}
				
                // open the pane...               
                OpenPane( base, false, pHeight );
				scrollToPane( previousPane , base );
				/*topPosition = $(base).position().top;
				if( lastPaneTopPosition < topPosition ){
					topPosition = topPosition - lastPaneHeight + options.minimumHeight;
				}*/

                if (lastTile == undefined) // the last tile was not in this pane...
                {
                    // ...so wait (this is a bit of a band-aid pause)...
                    $("#" + base.id + " > ul > li:first > a").animate({ opacity: 1.0 }, options.duration)
                }

                // ...and mark this pane as the last one opened...
                lastPane = base;
                lastPaneIsOpen = true;
                //paneJustOpened = true; 

                // ...and open the first tile
                var tileWidth;// = $("#" + base.id + " > ul > li:first > a > img").width();

				// 17.11.2010 find the tile to open, if it was passed
				var currentCaption;
				var tRef;
				if( tileSrc != undefined ){
					//var tRef = "";
					$('#' + base.id + " > ul > li > a > img ").each( function( index ) {
						if( $( this ).attr( "src" ) == tileSrc ){
							tRef = '#' + base.id + " > ul > li:nth-child(" + (index+1) + ") > a ";						
						}
					});
				}
				else{
					tRef = "#" + base.id + " > ul > li:first > a";
				}		
				
				tileWidth = $( tRef + " > img " ).width();

				// open the tile, set the caption and note the last tile 
				OpenTile( tRef , false, tileWidth );
				currentCaption = $( tRef ).attr( "title" );
				lastTile = $( tRef ).get(0);

				// scroll the window so that the pane header is at the top of the window, if possible
				//$('html, body').animate( {scrollTop: topPosition }, {queue: true, duration:options.duration} );
				
				
				if (currentCaption == undefined) {
					currentCaption = defaultCaption;                    
                }
				else if (currentCaption.length < 1) {		
					currentCaption = defaultCaption;
                }

                SetCaption("#" + base.id + " > .caption", currentCaption);
				
				// set the browser url hash for permalinking
				var hash = $( tRef ).attr("class");
                if (hash != undefined) {
                    if (hash.length > 0) {
                        SetHash($(tRef).attr("class"));
                    }
                }
                lastTileInfo = $(tRef).attr("innerHTML");				
				
				// 22.11.2010 - left/right navigation added
				if( $(base).attr('class') == 'pane' ) {
					 
					$("#ctrl").animate( { opacity:options.previewOpacity } , { duration: options.fadeTime } );					
						
				}

            }
        }

        /*
         *	hide messages
         */
        HideMessage = function() {
            //$("#messages").attr( "innerHTML" , "" );
            $("#messages").fadeOut(options.duration);
			//$("#messages").animate({ opacity: 0.5 }, options.duration )
        }

        /*
         *	open a tile
         */
        OpenTile = function(tile, queueAnimation, maxWidth) {
            var w = options.maximumWidth;

            if (maxWidth != undefined) {
                if (maxWidth > 0) {
                    w = maxWidth;
                }
            }

            $(tile).animate({ width: w }, { queue: queueAnimation, duration: options.duration });
			
			lastTile = $(tile);
        }

        /*
         *	open a pane
         */
        OpenPane = function(pane, queueAnimation, paneHeight) {
			// 16.11.2010 hide previews
			if( showPreview ) {
				hidePreview();
			}
			
			if( paneHeight == null || paneHeight == 0 ){
				$(pane).animate({ height: options.maximumHeight }, { queue: queueAnimation, duration: options.duration });
			}
			else{
				$(pane).animate({ height: paneHeight }, { queue: queueAnimation, duration: options.duration });
			}
			
			lastPane = $(pane).get(0);
			lastPaneIsOpen = true;
			
			//$("#home").animate( {opacity:options.fadeOutOpacity},{duration:options.duration} );
			ToggleControls( true );
        }

        /*
         *	open a tile
         */
        RemoveHash = function() {
            window.location.hash = "#";
        }
		
		
		/**
			scroll from one pane to another
		 */
		scrollToPane = function( fromPane , toPane ){
			//TODO: handle event where fromPane is undefined....

			var fromPaneHeight;
			var lastPaneHeight;
						
			if( fromPane != undefined ) {
				 lastPaneTopPosition = $( fromPane ).position().top;
				 lastPaneHeight = parseInt( $( fromPane ).css("height").replace("px","") );
				 
			}
			else{
				 lastPaneTopPosition = 0;
				 lastPaneHeight = 0;
			}

			topPosition = $(toPane).position().top;
			
			if( lastPaneTopPosition == 0 ){
				topPosition = topPosition; // + options.minimumHeight;
			}
			else if( lastPaneTopPosition < topPosition ){
				topPosition = topPosition - lastPaneHeight + options.minimumHeight;
			}
			
			$('html, body').animate( {scrollTop: topPosition }, {queue: true, duration:options.duration} );				
		}
        /*
         *	set a tile's caption
         */
        SetCaption = function(captionRef, caption, changeColours) {
            if ( changeColours && colourModeIndex < 2 ) {
				if( captionRef != undefined ) {				
					ChooseNextColours();
				}
            }

            if (caption != undefined) {
                if (caption.length > 0) {
                    $(captionRef).html(caption).fadeIn(options.duration);
                    $(captionRef).attr("title", caption);
                }
            }
        };

        // Taken from AJAXY jquery.history Plugin
        SetHash = function(hash) {
            // Write hash
            if (typeof window.location.hash != 'undefined') {
                if (window.location.hash != hash) {
                    window.location.hash = hash;
                };
            } else if (location.hash != hash) {
                location.hash = hash;
            };

            // Done
            return hash;
        };
        // <-- End AJAXY code

        /*
         *	display action count
         */
        ShowActionCount = function() {
            $("#actions").attr("innerHTML", hoverCount + clickCount);
        }

        /*
         *	show messages
         */
        ShowMessage = function(msg) {
            $("#messages").attr("innerHTML", msg);
            $("#messages").fadeIn(options.duration);
        }

        /*
         *	show permalink
         */
        ShowPermaLink = function(msg) {
            ShowMessage(msg);
        }

		/*
		 *	toggle left, right, and top button opacity
		 */	
		ToggleControls = function( showControls ) {
			if( showControls ){
				$("#left").animate({opacity: Math.max( options.fadeOutOpacity , $("#left").css("opacity") )},{duration:options.fadeTime});
				$("#right").animate({opacity: Math.max( options.fadeOutOpacity , $("#right").css("opacity") )},{duration:options.fadeTime});
				$("#home").animate({opacity:options.fadeOutOpacity},{duration:options.fadeTime});
			}
			else{
				$("#left").animate({opacity:0},{duration:options.fadeTime});
				$("#right").animate({opacity:0},{duration:options.fadeTime});
				$("#home").animate({opacity:0},{duration:options.fadeTime});			
			}
		};

		/*
         *	return a random number
         */
        RandomNumber = function( upperBound ) {
			return Math.floor( Math.random() * upperBound );
		}
		
        /*
         *	open up the pane and tile a bookmarked image is in
         */
        GoToBookmark = function() {

            var ref = window.location.hash.substr(1);
			var showImage = false; 
			var showRandomImage = false;
			
            if (ref.length > 0) {
                var className = "." + ref;
                tileRef = "#" + $(className).parent().parent().parent().attr("id") + " > ul > li > " + className;
				showImage = true;
            }
			else {				
//				showRandomImage = true;		
				showRandomImage = options.showRandomImage;
				// var n = 11;
				// if( RandomNumber( n ) > 5 ) {
					// showRandomImage = true;
				// }
				
				if( showRandomImage ) {
					n = RandomNumber( $( '.pane > ul > li > a' ).length );					
					var className = "." + $( '.pane > ul > li > a' ).eq( n ).attr( 'class' );
					tileRef = "#" + $(className).parent().parent().parent().attr("id") + " > ul > li > " + className;
					showImage = true;
					SetHash( $( tileRef ).attr( 'class' ) );					
				}				
			}
			
			if( showImage ) {
			
				// 11.04.2010 - adjust pane height				
				var pHeight = GetPaneHeight( "#" + $(className).parent().parent().parent().attr('id') );
				
				// tileRef should have been set 
				var currentCaption = $(tileRef).attr("title");
                var paneRef = "#" + $(className).parent().parent().parent().attr("id");
                $(paneRef).css("background-color", defaultBookmarkedBackgroundColour);
				$(paneRef).css('color' , '#ffffff');

                var tileWidth = $(tileRef + " > img").width();

				if( pHeight > 0 ){
					$(className).parent().parent().parent().animate({ height: pHeight }, { queue: false, duration: options.duration });
				}
				else{
					$(className).parent().parent().parent().animate({ height: options.maximumHeight }, { queue: false, duration: options.duration });
				}
				
                OpenTile(tileRef, true, tileWidth);
                lastTile = $(tileRef).get(0);
                lastPane = $(paneRef).get(0);
                lastPaneIsOpen = true;
                SetCaption(paneRef + " > .caption ", currentCaption);

				// not really sure why at this point but the scroll position needs to be adjusted...
				$('html, body').animate( {scrollTop: $(paneRef).position().top /*- ( options.minimumHeight / 2 )*/ }, {queue:false, duration:options.duration} );	
			}

			if( lastPaneIsOpen ){
				ToggleControls( true );
			}
            return true;
        };

		GetPaneHeight = function( paneRef ) {
			var pHeight = 0;
			var paneClass = $( paneRef ).attr( 'class' );
			
			if( paneClass == 'pane' ){
				$('#' + $( paneRef ).attr( 'id' ) + ' > ul > li > a > img ').each( function( index ) {
					if( $(this).attr( 'height' ) > pHeight ){
						pHeight = $( this ).attr( 'height' );
					}
				});
				
				pHeight += 3 * options.minimumHeight;
			}
			else{				
				$( '#' + paneRef.attr( 'id' ) + ' > * ' ).each( function( indexOf ) {
					pHeight += $( this ).height();
				});
				pHeight += options.minimumHeight;
			}
			
			return pHeight;
		}
		
		
        // if a hash / bookmark link has been provided, go to it. 
        HideMessage();
        //SelectColourMode();
        
        // wait until all images have loaded 
		$(window).load(function () {
			GoToBookmark();	
			
		})
		
		
		// 04.11.2010 blog integration
//		$.fn.readFeed = function(options) {
		loadFeed = function(options) {

    	/* Feed method */ 
    	var feed = new google.feeds.Feed("http://donnydraws.blogspot.com/feeds/posts/default?alt=rss");
		baseOptions = $.extend(defaults, options);
		feed.setNumEntries( baseOptions.numBlogEntries ); 
		feed.includeHistoricalEntries();
    	feed.load(feedLoaded); 
    	
		// Our callback function, for when a feed is loaded. 
        function feedLoaded(result) { 
			if (!result.error) {
				// Grab the container we will put the results into 
				var container = document.getElementById("items");
				container.innerHTML = ''; 
            
				var innerHTML = "";
            
				// Loop through the feeds, putting the titles onto the page.
				// Check out the result object for a list of properties returned in each entry.
				// http://code.google.com/apis/ajaxfeeds/documentation/reference.html#JSON
				//for (var i = 0; i < result.feed.entries.length; i++) {
				for (var i = 0; i < result.feed.entries.length; i++) {
					var entry = result.feed.entries[i];
					innerHTML += '<div class="item"><div class="blogTitle"><a href="'+ entry.link + '">' + entry.title + '</a></div><br><div class="blogContent">' + entry.content.toString() + '</div></div>';					
				}
				
				container.innerHTML = innerHTML.replace(/<a /g,'<a id="ext" ') ;
			}
		}
        
		function OnLoad() {
			// Create a feed instance that will grab Digg's feed.
			//var feed = new google.feeds.Feed("http://donnydraws.blogspot.com/atom.xml");
        
				// Calling load sends the request off.  It requires a callback function.
				//feed.load(feedLoaded);
			}
    	
		};

		/**
		 * log clicks
		 */
		logClick = function(){
			/*$('<script type="text/javascript"> var sc_project=4745039; var sc_invisible=1; var sc_partition=54; var sc_click_stat=1; var sc_security="d7f8e445"; </script> <script type="text/javascript" src="http://www.statcounter.com/counter/counter.js"></script><noscript><div class="statcounter"><a title="joomla 1.5 statistics" href="http://www.statcounter.com/joomla/" target="_blank"><img class="statcounter" src="http://c.statcounter.com/4745039/0/d7f8e445/1/" alt="joomla 1.5 statistics" ></a></div></noscript>').appendTo(this);*/
			//alert( document.location );
			
			//var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
			
			/*document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));*/
			
			/*try {
				var pageTracker = _gat._getTracker("UA-4137149-2");
				pageTracker._trackPageview();		
			} catch(err) {}*/
		};
		
		// 15.11.2010 - added for image previews
		hidePreview = function() {
			if( previewWindow != undefined ) {				
				previewWindow.hide();
				previewIsVisible = false;
			}
		}
		
		move = function( e , paneRef ){
			if( paneRef != undefined ){
				// get the number of images in the pane
				var numImages = 0;
				var currentIndex = 0;
				var img = new Image();
				var images = new Array();
				var topPosition = $( '#' + paneRef ).position().top + options.minimumHeight;
			
				$( '#' + paneRef + ' > ul > li > a > img ').each( function( index ) {
					images[ index ] = $( this ).attr( 'src' );
					numImages++;
				});
			
				currentIndex = Math.min( numImages - 1 ,  Math.floor( e.pageX / $( window ).width() * 1.191 * numImages ) );
			
				if( images[currentIndex] != undefined ){
					img.src = images[ currentIndex ];
					$( '#previewImage' ).attr( 'src' , images[ currentIndex ] ) ;				}
			
				if( previewWindow != undefined ){
					previewWindow.css({
						width: img.width * .382,
						height: img.height * .382,
						left: Math.min( e.pageX , $( window ).width() - ( img.width * .382 ) ),
						//left: Math.min( $(window).width() * .809 , $( window ).width() - ( img.width * .382 ) ),
						top: $( '#' + paneRef ).position().top + options.minimumHeight //e.pageY + 10
					});	
				}
				/*preview.css({
					left: 0 ,
					top: 0 				
				});*/
			}
		};
		
		loadFeed();
    }
})(jQuery);

