var Malarquee = function()
{
	var AJAX_TIMEOUT				= 3500;
	var CORRECT_AFTER_SCROLL_COUNT	= 5;

	var Indeces = {
		TEXT: 'text',
		TOTAL_CLIENTS: 'n',
		CLIENT: 'c',
		BACKGROUND_COLOR: 'bg',
		FONT_COLOR: 'f',
		SCROLL_AT_TIME: 't'
	};

	var multiplier 					= 5/4
	//var multiplier				= 41/40; // this is too much, it slows it down.
	var timeout;
	var defaultMultiClientScrollTime;
	var startingDate;
	var startingTimeout, cancelTimeout;
    var lastAbsoluteTime = '';
    var lastDelayAmount;

	var scroll = new Fx.Scroll( 'malarquee', {
		wait: true,
		duration: 1000,
		transition: Fx.Transitions.Expo.easeOut
	});

	var maxHeight;
	var correctCounter = 0;
	var serverTime;

	var clientNumber = Valdi.Params.GetInt( Indeces[ 'CLIENT' ], 1 );
	var totalClients = Valdi.Params.GetInt( Indeces[ 'TOTAL_CLIENTS' ], 1 );

	function getTotalWords()
	{
		return $$( '#malarquee .word' ).length;
	}

	function __getNextWord( currentWord )
	{
		//return currentWord.nextSibling ? currentWord.nextSibling : ( $( 'loop' ).checked == true ? currentWord.parentNode.firstChild : null );
		return currentWord.nextSibling ? currentWord.nextSibling : currentWord.parentNode.firstChild;
	}

	function __delay( interval )
	{
		timeout = window.setTimeout( function()
		{
			Malarquee.scroll.toNextWord();
		}, interval );
	}

	function displayTimeDifference( futureTime, pastTime )
	{
		if( pastTime == null ) pastTime = new Date();

		var seconds = Math.ceil( ( futureTime.getTime() - pastTime.getTime() ) / 1000 );
		var minutes = 0, hours = 0;
		if( seconds > 60 )
		{
			minutes = Math.floor( seconds / 60 );
			seconds = seconds % 60;
		}
		if( minutes > 60 )
		{
			hours = Math.floor( minutes / 60 );
			minutes = minutes % 60;
		}

		var hourStr = '', minuteStr = '';
		if( hours > 0 ) hourStr = hours + 'h ';
		if( minutes > 0 ) minuteStr = minutes + 'm ';

		return 'Scrolling in ' + hourStr + minuteStr + seconds + 's';
	};

    function updateHour()
    {
        var minutes = parseInt( $E('#scroll-at-time-input').value, 10 );
        var now = new Date();
        $E('#scroll-at-time-hour').innerHTML = minutes && minutes > now.getMinutes() ? now.getHours() : ( now.getHours() + 1 );
    }

    function getTimeString()
    {
        updateHour();
        return $E('#scroll-at-time-hour').innerHTML + ':' + $('scroll-at-time-input').value;
    }

    // rot 13 code courtesy of http://personal.inet.fi/cool/jjlammi/rot13.html
    var rot13map = new Array();
    var s = "abcdefghijklmnopqrstuvwxyz";
    for (i=0; i<s.length; i++)
        rot13map[s.charAt(i)] = s.charAt((i+13)%26);
    for (i=0; i<s.length; i++)
        rot13map[s.charAt(i).toUpperCase()] = s.charAt((i+13)%26).toUpperCase();

    function rot13(a)
    {
        var s = '';
        for (i=0; i<a.length; i++)
        {
            var b = a.charAt(i);
            s += (b>='A' && b<='Z' || b>='a' && b<='z' ? rot13map[b] : b);
        }
        return s;
    }

	return {
		onload: function()
		{
            if( totalClients > 1 )
			{
				defaultMultiClientScrollTime = new Date();
				var timeString = Valdi.Params.Get( Indeces[ 'SCROLL_AT_TIME' ] );
				if( timeString )
				{
                    var minutes = parseInt( timeString, 10 );
					defaultMultiClientScrollTime.setHours( minutes > defaultMultiClientScrollTime.getMinutes() ? defaultMultiClientScrollTime.getHours() : ( defaultMultiClientScrollTime.getHours() + 1 ) );
					defaultMultiClientScrollTime.setMinutes( minutes );
				} else {
					defaultMultiClientScrollTime.setTime( defaultMultiClientScrollTime.getTime() + 1000*60*2 ); // 2 minutes from now
				}

                var minutes = defaultMultiClientScrollTime.getMinutes();
                var minuteStr = ( minutes < 10 ? '0' : '' ) + minutes;
				$('scroll-at-time-input').value = minuteStr;
                updateHour();
                $E('#scroll-at-time').removeClass( 'hidden' );
			}

			Malarquee.init();

			$('update').onclick = function(e)
			{
				var text = prompt( 'What do you want to maLArquee?  Optionally separate slides with a | pipe character.', Malarquee.toString() );
				if( text != null )
				{
					Valdi.Params.Set( Indeces[ 'TEXT' ], rot13( text ) );
					Malarquee.reload( false );
				}
			};
            $('scroll-at-time-input').onblur = function(e){ updateHour(); }
			//$(window).onresize = Malarquee.reload();
			$('preferences-display').onclick = function(e)
			{
				$('preferences').toggleClass( 'hidden' );
			};
			$('clientsExecute').onclick = function(e)
			{
                clientNumber = Valdi.Params.Set( Indeces[ 'CLIENT' ], $('clientNumber').value );
				totalClients = Valdi.Params.Set( Indeces[ 'TOTAL_CLIENTS' ], $('totalClients').value );
				Valdi.Params.Set( Indeces[ 'SCROLL_AT_TIME' ], $('scroll-at-time-input').value );
				Valdi.Params.Set( Indeces[ 'BACKGROUND_COLOR' ], $('background-color-input').value );
				Valdi.Params.Set( Indeces[ 'FONT_COLOR' ], $('font-color-input').value );
				Malarquee.reload();
			};

			$('clientNumber').value = clientNumber;
			$('totalClients').value = totalClients;

			$$('body').setStyle( 'background-color', Valdi.Params.Get( Indeces[ 'BACKGROUND_COLOR' ], '#000' ) );
			$('background-color-input').value = Valdi.Params.Get( Indeces[ 'BACKGROUND_COLOR' ], '#000000' );
			$$('body').setStyle( 'color', Valdi.Params.Get( Indeces[ 'FONT_COLOR' ], '#f00' ) );
			$('font-color-input').value = Valdi.Params.Get( Indeces[ 'FONT_COLOR' ], '#FF0000' );
		},
		init: function( str )
		{
			if( timeout != null ) window.clearTimeout( timeout );
			var text = Valdi.Params.Get( Indeces[ 'TEXT' ] );
			if( text && text != '' && str == null ) str = rot13( text );

			Malarquee.setup( str );
			var content = $$( '#malarquee .content' );
			content.setStyle( 'display', 'block' );

			maxHeight = 0;
			$$( '#malarquee .word' ).every( function( element, j )
			{
				if( element.getStyle( 'display' ) != 'none' )
				{
					if( $$( '#malarquee .firstWord' ).length == 0 ) element.addClass( 'firstWord' );
					Malarquee.font.auto( element );
				}
				return true;
			} );

			var contentHeight = content[ 0 ].offsetHeight;
			content.setStyle( 'marginTop', Math.floor( Window.getHeight() / 2 - maxHeight / 2 ) );

			if( totalClients > 1 )
			{
				window.setTimeout( function()
				{
					serverTime = new Json.Remote( 'time.php',
					{
						method: 'get',
						autoCancel: true,
						async: true,
						onComplete: function( data )
						{
							//$E('#server-time').innerHTML = data.time.str;
							var delayAmount = data.time.initoffset;
                            /* if( data.time.initoffset < 0 ) delayAmount = data.time.initoffset + 1000*60*60*24; // add one day
                            else  delayAmount = data.time.initoffset;*/

                            lastAbsoluteTime = data.time.server;
                            lastDelayAmount  = delayAmount;

							Malarquee.scroll.delay( delayAmount );

							startingDate = new Date();
							startingDate.setTime( startingDate.getTime() + delayAmount );
							startingTimeout = setInterval( function()
							{
								$E('#update-in').innerHTML = displayTimeDifference( startingDate );
							}, 1000 );
						}
					}).send($('scroll-at-time-input').value);
				}, 2000 );
			} else {
				Malarquee.scroll.delay();
			}
		},
		setup: function( str )
		{
			var content = $$( '#malarquee .content' );
			if( str == null ) str = content[ 0 ].innerHTML;
			if( str.indexOf( '|' ) > -1 )
				var words = str.split( '|' );
			else
				var words = str.split( ' ' );

			content[ 0 ].innerHTML = '';
			var client = clientNumber - 1;

			if( words.length % totalClients > 0 )
				words.push( '&nbsp;' );

			for( var j = 0; j < words.length; j++ )
			{
				var element = ( new Element( 'span', { 'class': 'word' } ) ).setHTML( words[ j ] );
				content[ 0 ].adopt( element );
				if( j % totalClients != client ) element.setStyle( 'display', 'none' );
			}
		},
		reload: function( bSetText )
		{
			if( bSetText == null || bSetText == true ) Valdi.Params.Set( Indeces[ 'TEXT' ], rot13( Malarquee.toArray().join( '|' ) ) );
			window.location.href = 'index.html' + Valdi.Params.Encode();
		},
		toArray: function()
		{
			var str = [];
			var words = $$( '#malarquee .word' );
			for( var j = 0; j < words.length; j++ )
			{
				str.push( words[ j ].innerHTML );
			}
			return str;
		},
		toString: function()
		{
			return Malarquee.toArray().join( ' ' );
		},
		scroll: {
			reset: function()
			{
				Malarquee.scroll.toWord( $$( '#malarquee .word' )[ 0 ], $$( '#malarquee .firstWord' )[ 0 ] );
			},
			delay: function( overrideDelay )
			{
				var interval = overrideDelay;
				if( startingTimeout != null )
				{
					$E('#update-in').setStyle( 'display', 'none' );
					clearInterval( startingTimeout );
				}
				if( overrideDelay == null )
				{
					interval = AJAX_TIMEOUT;
				}
				correctCounter++;
				if( CORRECT_AFTER_SCROLL_COUNT == correctCounter && totalClients > 1 )
				{
					serverTime = new Json.Remote( 'time.php',
					{
						method: 'get',
						autoCancel: false,
						async: true,
						onComplete: function( data )
						{
                            var delayAmount = interval - ( data.time.server - ( lastAbsoluteTime + lastDelayAmount + ( CORRECT_AFTER_SCROLL_COUNT - 1 ) * AJAX_TIMEOUT ) );
							__delay( delayAmount );
							window.clearTimeout( cancelTimeout );
							correctCounter = 0;
                            lastDelayAmount  = delayAmount;
                            lastAbsoluteTime = data.time.server;
						}
					}).send(lastAbsoluteTime);
					cancelTimeout = window.setTimeout( function()
					{
						if( serverTime.running == true ) // this timeout shouldn't even run if the json call completed, but just to doublecheck
						{
							serverTime.cancel();
							Malarquee.scroll.toNextWord();
							correctCounter = 0;
						}
					}, interval );
				} else {
					__delay( interval );
                }
			},
			getCurrentWord: function()
			{
				var currentWord = $$( '#malarquee .firstWord' )[ 0 ];
				if( currentWord )
				{
					return currentWord;
				} else {
					return $$( '#malarquee .word' )[ 0 ];
				}
			},
			getNextWord: function()
			{
				var currentWord = Malarquee.scroll.getCurrentWord();
				var nextWord = __getNextWord( currentWord );
				var overflowCounter = 0;
				while( nextWord != null && nextWord.getStyle( 'display' ) == 'none' && overflowCounter < Valdi.Params.Get( Indeces[ 'TOTAL_CLIENTS' ], 1 ) )
				{
					nextWord = __getNextWord( nextWord );
					overflowCounter++;
				}
				return nextWord;
			},
			toNextWord: function()
			{
				Malarquee.scroll.toWord( Malarquee.scroll.getNextWord(), Malarquee.scroll.getCurrentWord() );
			},
			toWord: function( word, oldWord )
			{
				if( oldWord ) oldWord.removeClass( 'firstWord' );
				if( word )
				{
					word.addClass( 'firstWord' );
					scroll.toElement( word );
					Malarquee.scroll.delay();
				} else {
					// @todo set individual word font sizes so they fit on the screen.
					//Malarquee.font.auto( $$( '#malarquee .content' )[ 0 ] );
				}
			}
		},
		font: {
			bigger: function( obj )
			{
				var currentSize = obj.getStyle('fontSize').toInt();
				obj.setStyle( 'fontSize', Math.round( currentSize * multiplier ) );
			},
			smaller: function( obj )
			{
				var currentSize = obj.getStyle('fontSize').toInt();
				obj.setStyle( 'fontSize', Math.round( currentSize * ( 1 / multiplier ) ) );
			},
			auto: function( word )
			{
				var windowWidth = Window.getWidth(), windowHeight = Window.getHeight();
				if( word == null ) word = $$( '#malarquee .word' )[ 0 ];
				var counter = 0;
				while( ( word.offsetWidth < windowWidth || word.offsetHeight < windowHeight ) && counter < 400 )
				{
					Malarquee.font.bigger( word );
					counter++;
				}
				counter = 0;
				while( ( word.offsetWidth > windowWidth || word.offsetHeight > windowHeight ) && counter < 400 )
				{
					Malarquee.font.smaller( word );
					counter++;
				}
				if( word.offsetHeight > maxHeight ) maxHeight = word.offsetHeight;

				var newWidth = windowWidth - word.offsetWidth/*  - ( windowWidth / 20 ) */;
				word.setStyle( 'marginRight', newWidth > 0 ? newWidth : '0.6em' );
			}
		}
	};
}();

Malarquee.onload();