var splashCount = 3;
var normalProxy = root + '/php/proxy.php?url=';
var flickrProxy = root + '/php/flickr.php?args=';
var uiFadeTimeout = 2000;
var slideInterval = 3000;
var isSplashImage = true;

var freshImages = new Array();
var seenImages = new Array();
var currentImage = null;
var otherImage = null;
var nextSwitchT = 0;
var state = 'shouldLoad';
var firstTime = true;
var paused = false;
var sources = new Array();
var uiStartFadeT = 0;
var uiOpacity = 0;
var isInUI = false;
var lastGetFreshImages = 0;
var useCSSFade = (typeof(WebKitTransitionEvent) == 'object');
var sourceErrors = [];

var content = null;
var imageAnchor = null;
var sourceAnchor = null;
var spinner = null;
var playButton = null;
var sourceButton = null;
var aboutDiv = null;
var menuDiv = null;
var titleDiv = null;
var authorDiv = null;
var trayDiv = null;
var errorDiv = null;
var debugDiv = null;
var debugDiv2 = null;

var possibleSources = 
[
	{ name:'twitpic', proxy:normalProxy, handler:parseTwitpic, index:-1, 
	url:'http://search.twitter.com/search.json?rpp=60&q=twitpic.com' }, 
	
	{ name:'ffffound', proxy:normalProxy, handler:parseFound, index:0, count:25, times:2,
	url:'http://ffffound.com/feed?offset=' },
	
	{ name:'deviantart', proxy:normalProxy, handler:parseDeviantArt, index:0, count:60, 
	url:'http://backend.deviantart.com/rss.xml?q=boost%3Apopular%20meta%3Aall%20max_age%3A24h&type=deviation&offset=' },
	
	{ name:'flickr', proxy:flickrProxy, handler:parseFlickr, index:1, count:1,
	url:'method=flickr.interestingness.getList&per_page=60&page=' },
	
	{ name:'delicious', proxy:normalProxy, handler:parseDelicious,
	url:'http://feeds.delicious.com/v2/rss/tag/system:media:image?count=60' },
	
	{ name:'reddit', proxy:normalProxy, handler:parseReddit,
	url:'http://www.reddit.com/r/pics/.rss' },
	
	{ name:'default', sources:['ffffound', 'deviantart', 'flickr'] }
];

//--------------------------------------------------------------------------
function addAllSource()
{
	var names = [];
	var count = possibleSources.length;
	var a;
	for(a = 0; a < count; a++)
	{
		var source = possibleSources[a];
		if(source.sources)
			continue;
		
		names.push(source.name);
	}
	
	if(names.length)
	{
		source = new Object();
		source.name = 'all';
		source.sources = names;
		possibleSources.push(source);
	}
}

addAllSource();

//--------------------------------------------------------------------------
function startEngine()
{
	content = document.getElementById('content');
	imageAnchor = document.getElementById('imageAnchor');
	sourceAnchor = document.getElementById('sourceAnchor');
	spinner = document.getElementById('spinner');
	playButton = document.getElementById('play');
	sourceButton = document.getElementById('source');
	aboutDiv = document.getElementById('about');
	menuDiv = document.getElementById('menu');
	titleDiv = document.getElementById('title');
	authorDiv = document.getElementById('author');
	trayDiv = document.getElementById('tray');
	errorDiv = document.getElementById('errors');
	debugDiv = document.getElementById('debug');
	debugDiv2 = document.getElementById('debug2');
	
	setUIOpacity(uiOpacity);
	playButton.style.visibility = '';
//			aboutDiv.style.visibility = '';
	menuDiv.style.visibility = '';
	titleDiv.style.visibility = '';
	authorDiv.style.visibility = '';
	trayDiv.style.visibility = '';
	
//    			debugDiv.style.visibility = '';
//    			debugDiv2.style.visibility = '';
	
	positionUI();
	positionAbout();
	
	// ___ errors 
	if(sourceErrors.length || !sources.length)
	{	
		errorDiv.style.visibility = '';
		var count = sourceErrors.length;
		var a;
		for(a = 0; a < count; a++)
			errorDiv.innerHTML += sourceErrors[a] + '<br>';
		
		if(!sources.length)
		{
			errorDiv.innerHTML += 'No sources found.';
			return;
		}
	}
	
	// ___ spinner
	setOpacity(spinner, 0.25);
	spinner.style.visibility = '';
	
	// ___ slideInterval
	var seconds = parseFloat(getURLParam('seconds')) || 0;
	var minutes = parseFloat(getURLParam('minutes')) || 0;
	if(seconds || minutes)
		slideInterval = (seconds + (minutes * 60)) * 1000;
	
//	console.log(slideInterval);
	
	// ___ splash
	var image = new Object();
	image.url = root + '/img/splash/' + Math.floor(Math.random() * splashCount) + '.jpg';
	image.source = '';
	loadImage(image);
	
	// ___ sources
	getFreshImages();

	// ___ heartbeat
	window.setInterval(update, 67); // 15 fps
}

//--------------------------------------------------------------------------
function update()
{
	var now = getMilliseconds();
	
	updateXML();
	
	if(state == 'fade')
	{
		var stillFading = false;
		
		if(currentImage)
		{
			var currentOpacity = parseFloat(currentImage.style.opacity);
			if(currentOpacity < 1)
				stillFading = true;
			
			setOpacity(currentImage, Math.min(1, currentOpacity + 0.1));
		}
		
		if(otherImage)
		{
			var otherOpacity = parseFloat(otherImage.style.opacity);
			if(otherOpacity > 0)
				stillFading = true;

			setOpacity(otherImage, Math.max(0, otherOpacity - 0.1));
		}
		
		if(!stillFading)
			fadeDownComplete();
	}
	
	if(now > nextSwitchT && state == 'loaded' && !paused)
	{
		var temp = otherImage;
		otherImage = currentImage;
		currentImage = temp;
		
		if(currentImage)
			currentImage.style.zIndex = '200';
		
		if(otherImage)
			otherImage.style.zIndex = '100';

		nextSwitchT = now + (isSplashImage ? 3000 : slideInterval); 
		isSplashImage = false;
		
		if(useCSSFade)
		{
			if(currentImage)
				setOpacity(currentImage, 1);
			
			if(otherImage)
			{
				state = 'cssFade';
				otherImage.addEventListener('webkitTransitionEnd', fadeDownComplete, false);
				setOpacity(otherImage, 0);
			}
			else
				fadeDownComplete();
		}
		else
			state = 'fade';
		
		if(!firstTime)
			spinner.style.visibility = 'hidden';
			
		firstTime = false;
	}
	
	if(state == 'shouldLoad')
	{
//		console.log(freshImages.length, seenImages.length);
		var image = null;
		if(freshImages.length)
		{
			var index = Math.floor(Math.random() * freshImages.length);
			image = freshImages[index];
			freshImages.splice(index, 1);
			seenImages.push(image);
		}
		else if(seenImages.length)
		{
			var a;
			for(a = 0; a < 10; a++)
			{
				var index = Math.floor(Math.random() * seenImages.length);
				image = seenImages[index];
				if(!currentImage || currentImage.src != image.url)
					break;
			}
		}
		
		if(image)
			loadImage(image);
			
		if(freshImages.length < 2 && now > lastGetFreshImages + 10000)
			getFreshImages();
	}
	
	// UI Fading
	if(uiOpacity > 0 && uiStartFadeT < now && !paused && !isInUI)
	{
		setUIOpacity(Math.max(0, uiOpacity - 0.1));
	}
	
//    		debugDiv.innerHTML = state;
}

//--------------------------------------------------------------------------
function getFreshImages()
{
	lastGetFreshImages = getMilliseconds();
	
	var count = sources.length;
	var a;
	for (a = 0; a < count; a++)
	{
		var source = sources[a];
		var b;
		for(b = 0; b < source.times; b++)
		{
			if(source.done)
				continue;
				
			var url = source.url;
			if(typeof(source.index) != 'undefined')
			{
				if(source.index != -1)
				{
					url += source.index;
					source.index += source.count;
				}
			}
			else 
				source.done = true;
				 
			getXML(source.proxy + escape(url), source.handler);
		}
	}
}

//--------------------------------------------------------------------------
function getPossibleSource(name) 
{
	var count = possibleSources.length;
	var a;
	for(a = 0; a < count; a++)
	{
		if(possibleSources[a].name == name)
			return possibleSources[a];
	}
	
	sourceErrors.push('Unable to find source "' + name + '".');
	return null;
}

//--------------------------------------------------------------------------
function findSourceIndex(name)
{
	var count = sources.length;
	var a;
	for(a = 0; a < count; a++)
	{
		if(sources[a].name == name)
			return a;
	}
	
	return -1;
}

//--------------------------------------------------------------------------
// Source can be either of the two kinds of source, or a string with source 
// names separated by semicolons.
function addSource(source)
{
	if(!source)
		return;
	
	if(source.sources)
	{
		var count = source.sources.length;
		var a;
		for(a = 0; a < count; a++)
			addSource(getPossibleSource(source.sources[a]));
	}
	else if(source.name)
	{
		if(findSourceIndex(source.name) == -1)
		{
			source.done = false;
			if(typeof(source.times) == 'undefined')
				source.times = 1;
			
			sources.push(source);
		}
	}
	else
	{
		var names = source.split(';');
		var count = names.length;
		var a;
		for(a = 0; a < count; a++)
			addSource(getPossibleSource(names[a]));
	}
}

//--------------------------------------------------------------------------
// Source can be either of the two kinds of source, or a string with source 
// names separated by semicolons.
function removeSource(source)
{
	if(!source)
		return;
	
	if(source.sources)
	{
		var count = source.sources.length;
		var a;
		for(a = 0; a < count; a++)
			removeSource(getPossibleSource(source.sources[a]));
	}
	else if(source.name)
	{
		var index = findSourceIndex(source.name);
		if(index != -1)
			sources.splice(index, 1);
	}
	else
	{
		var names = source.split(';');
		var count = names.length;
		var a;
		for(a = 0; a < count; a++)
			removeSource(getPossibleSource(names[a]));
	}
}

//--------------------------------------------------------------------------
function addFreshImage(url, source, title, link, author)
{
	// ___ Weed out duplicates
	var count = freshImages.length;
	var a;
	for(a = 0; a < count; a++)
	{
		if(freshImages[a].url == url)
			return;
	}

	count = seenImages.length;
	for(a = 0; a < count; a++)
	{
		if(seenImages[a].url == url)
			return;
	}
	
	// ___ Push it onto the list
	var image = new Object();
	image.url = url;
	image.source = source;
	image.title = title;
	image.link = link;
	image.author = author;
	
	freshImages.push(image);
}

//--------------------------------------------------------------------------
function parseDelicious(http_request)
{
	var xml = http_request.responseXML;
	var items = xml.getElementsByTagName('item');
	var a;
	for(a = 0; a < items.length; a++)
	{
		var item = items.item(a);
		var url = xmlGetData(item, 'link');
		var title = xmlGetData(item, 'title');
		var link = xmlGetData(item, 'comments');

		addFreshImage(url, 'delicious', title, link);
	}
}

//--------------------------------------------------------------------------
function parseDeviantArt(http_request)
{
	var xml = http_request.responseXML;
	var items = xml.getElementsByTagName('item');
	var a;
	for(a = 0; a < items.length; a++)
	{
		var item = items.item(a);
		var title = xmlGetData(item, 'title');
		var link = xmlGetData(item, 'link');
		var author = xmlGetData(item, 'credit');
		
		var content = xmlGetNode(item, 'media:content');
		if(!content)
			content = xmlGetNode(item, 'content');
			
//		console.log(content);
		if(content)
		{
			var url = content.getAttribute('url');
			if(url && url.indexOf('.jpg') != -1)
				addFreshImage(url, 'deviantart', title, link, author);
		}
	}
}

//--------------------------------------------------------------------------
function parseFlickr(http_request)
{
	var xml = http_request.responseXML;
	var items = xml.getElementsByTagName('photo');
	var a;
	for(a = 0; a < items.length; a++)
	{
		var farm = items.item(a).getAttribute('farm');
		var server = items.item(a).getAttribute('server');
		var id = items.item(a).getAttribute('id');
		var secret = items.item(a).getAttribute('secret');
		var owner = items.item(a).getAttribute('owner');
		var title = items.item(a).getAttribute('title');
		
		var url = 'http://farm' + farm + '.static.flickr.com/'
				+ server + '/' + id + '_' + secret + '.jpg';

		var link = 'http://www.flickr.com/photos/' + owner + '/' + id;
		
		addFreshImage(url, 'flickr', title, link);
	}
}

//--------------------------------------------------------------------------
function parseFound(http_request)
{
	var xml = http_request.responseXML;
	var items = xml.getElementsByTagName('item');
	var a;
	for(a = 0; a < items.length; a++)
	{
		var item = items.item(a);
		var title = xmlGetData(item, 'title');
		var link = xmlGetData(item, 'link');
		
		var source = xmlGetNode(item, 'ffffound:source');
		if(!source)
			source = xmlGetNode(item, 'source');

		if(source)
		{
			var url = source.getAttribute('url');
			if(url)
				addFreshImage(url, 'found', title, link);
		}
	}
}

//--------------------------------------------------------------------------
function parseReddit(http_request)
{
	var xml = http_request.responseXML;
	var items = xml.getElementsByTagName('item');
	var a;
	for(a = 0; a < items.length; a++)
	{
		var item = items.item(a);
		var title = xmlGetData(item, 'title');
		var link = xmlGetData(item, 'link');

		var description = xmlGetData(item, 'description');
		var chunks = description.split('"');
		var b;
		for(b = 0; b < chunks.length; b++)
		{	
			var chunk = chunks[b];
			if(chunk.indexOf('.jpg') != -1)
				addFreshImage(chunk, 'reddit', title, link);
		}
	}
}

//------------------------------------------------------------------------------
function parseTwitpic(http_request)
{
    var file = http_request.responseText;
    if(!file)
        return;
        
    var entries = eval('(' + file + ')');
	var count = entries.results.length;
	if(count)
	{
        var a;
        for(a = 0; a < count; a++)
        {           
            var entry = entries.results[a];
            var title = entry.text;
            var avatar = entry.profile_image_url;
            var name = entry.from_user;
            
            var matches = title.match(/http:\/\/twitpic\.com\/(\w+)/);
            if(matches && matches.length && matches.length >= 2 && matches[0] && matches[1])
            {
	            var text = title.replace(matches[0], '');
	            addFreshImage('http://twitpic.com/show/full/' + matches[1], 'twitpic', text, matches[0], name);
	        }   
//            console.log(id, title);
//             var tag = 'http://twitpic.com/';
//             var start = title.indexOf(tag);
//             if(start != -1
// 
//             if(a >= 10)
//                 controller.addWaiting(name, avatar, title, parent);
//             else    
//                 controller.addIncoming(name, avatar, title, parent);
        }
	}
	
//	alert(controller.incoming.length);
}

//--------------------------------------------------------------------------
function positionUI()
{
	var windowSize = getWindowSize();
	var imageSize = getImageSize(spinner);
	
	spinner.style.left = ((windowSize.width - imageSize.width) / 2) + 'px';
	spinner.style.top = ((windowSize.height * 0.66) - (imageSize.height / 2)) + 'px';
}

//--------------------------------------------------------------------------
function positionImage(image)
{
	var windowSize = getWindowSize();
	var imageSize = getImageSize(image);
	
	var ratio = windowSize.width / imageSize.width;
	if(imageSize.height * ratio > windowSize.height)
		ratio = windowSize.height / imageSize.height;
		
	imageSize.width *= ratio;
	imageSize.height *= ratio;
	
	image.style.width = imageSize.width + 'px';
	image.style.height = imageSize.height + 'px';
	image.style.left = ((windowSize.width - imageSize.width) / 2) + 'px';
	image.style.top = ((windowSize.height - imageSize.height) / 2) + 'px';
}

//--------------------------------------------------------------------------
function fadeDownComplete()
{
	sourceButton.src = root + '/img/source/' + currentImage.gsImage.source + '.png';
	sourceButton.style.visibility = '';
	
	if(currentImage.gsImage.title)
		titleDiv.innerHTML = currentImage.gsImage.title;
	else
		titleDiv.innerHTML = '';

	if(!isIE)  // For some bizarre reason, IE throws an error on (authorDiv.innerHTML = '').
	{
		if(currentImage.gsImage.author)
			authorDiv.innerHTML = currentImage.gsImage.author;
		else
			authorDiv.innerHTML = '';
	}

	if(currentImage.gsImage.link)
	{
		imageAnchor.href = currentImage.gsImage.link;
		imageAnchor.onclick = null;

		sourceAnchor.href = currentImage.gsImage.link;
		sourceAnchor.onclick = null;
	}
	else
	{
		imageAnchor.href = '';
		imageAnchor.onclick = 'return false';

		sourceAnchor.href = '';
		sourceAnchor.onclick = 'return false';
	}

	state = 'shouldLoad';
}

//--------------------------------------------------------------------------
function imageLoad()
{
//    		assert('loading other image', img == otherImage);
	
	positionImage(otherImage);

	otherImage.style.position = 'absolute';
	setOpacity(otherImage, 0);
	
	imageAnchor.appendChild(otherImage);
	otherImage.gsAttached = true;
	
	state = 'loaded';
}

//--------------------------------------------------------------------------
function imageError()
{
//    		assert('loading other image', img == otherImage);

	state = 'shouldLoad';
}

//--------------------------------------------------------------------------
function loadImage(image)
{
	if(otherImage && otherImage.gsAttached)
		imageAnchor.removeChild(otherImage);

	state = 'loading';

	otherImage = document.createElement('img');
	otherImage.gsImage = image;
	otherImage.onload = imageLoad;
	otherImage.onerror = imageError;
	otherImage.onabort = imageError;
	
	if(useCSSFade)
	{
		otherImage.style.webkitTransitionProperty = "opacity";
		otherImage.style.webkitTransitionDuration = "1000ms";
	}
	
	otherImage.src = image.url; // must be last line, for IE 
}

//--------------------------------------------------------------------------
function handleMouseMove(event)
{
	setUIOpacity(1.0);
	uiStartFadeT = getMilliseconds() + uiFadeTimeout;
}

//--------------------------------------------------------------------------
function handleUIMouseOver(event)
{
	setUIOpacity(1.0);
	isInUI = true;
}

//--------------------------------------------------------------------------
function handleUIMouseOut(event)
{
	uiStartFadeT = getMilliseconds() + uiFadeTimeout;
	isInUI = false;
}

//--------------------------------------------------------------------------
function handleKey(event)
{
	var keynum;
	var keychar;
	
	if(window.event) // IE
		keynum = event.keyCode;
	else if(event.which) // Netscape/Firefox/Opera
		keynum = event.which;

	keychar = String.fromCharCode(keynum);
	if(keychar == ' ')
		togglePlay();
}

//--------------------------------------------------------------------------
function handleResize()
{
	if(currentImage)
		positionImage(currentImage);

	if(otherImage)
		positionImage(otherImage);
	
	positionUI();
	positionAbout();
}

//--------------------------------------------------------------------------
function toggleAbout()
{
	if(aboutDiv.style.visibility)
		aboutDiv.style.visibility = '';
	else
		aboutDiv.style.visibility = 'hidden';
}

//--------------------------------------------------------------------------
function positionAbout()
{
	var windowSize = getWindowSize();
	var aboutWidth = parseInt(aboutDiv.style.width);
	var aboutHeight = parseInt(aboutDiv.style.height);
	
	aboutDiv.style.left = ((windowSize.width - aboutWidth) / 2) + 'px';
	aboutDiv.style.top = ((windowSize.height - aboutHeight) / 2) + 'px';
}

//--------------------------------------------------------------------------
function togglePlay()
{
	paused = !paused;
	
	if(paused)
	{
		playButton.src = root + '/img/play.png';
		
		setUIOpacity(1.0);
	}
	else
	{
		playButton.src = root + '/img/pause.png';

		uiStartFadeT = getMilliseconds() + uiFadeTimeout;
	}
}

//--------------------------------------------------------------------------
function setUIOpacity(opacity)
{
	setOpacity(playButton, opacity);
	setOpacity(sourceButton, 0.5 * opacity);
	setOpacity(menuDiv, 0.5 * opacity);
	setOpacity(titleDiv, 0.8 * opacity);
	setOpacity(authorDiv, 0.8 * opacity);
	setOpacity(trayDiv, 0.4 * opacity);
	
	uiOpacity = opacity;
}
