var meVideoPresentation = (function()
{
	//ident to inform slide template that response should be ajax compatible
	var _pageRequestIdent = "meVidPresClientRequest";
	
	//object of page index (second) => url
	var _pages = null;
	
	//lookup array of seconds where pages begin
	var _pagelut = null;
	
	//url to startslide
	var _startslide = null;
	
	//url to endslide
	var _endslide = null;
	
	//currently shown page index (second)
	var _currentPage = null;
	
	//cache for fetched pages (url => data)
	var _pageCache = {};
	
	//players previous state, initially 0 (stop)
	var _prevstate = 0;
	
	
	/**
	 * Get url from given index
	 *
	 * @param int index Index
	 * @return string URL
	 */
	function getUrlByIndex(index)
	{
		if(_pages[index] === undefined)
			return null;
		
		return _pages[index].url;
	}
	
	
	/**
	 * Change page (slide) to url at given index
	 *
	 * @param int index Index in _pages object
	 */
	function changeToPage(index)
	{
		var url = getUrlByIndex(index);
		var segment = _pages[index].segment;
		
		changeSlide(url, index, segment);
		
		_currentPage = index;
	}
	
	
	/**
	 * Change slide
	 *
	 * @param string url URL where to fetch slide contents
	 * @param int highlight Index of slide item to highlight
	 * @param int tab Tab to activate
	 */
	function changeSlide(url, highlight, tab)
	{
		if(highlight === undefined)
			highlight = null;
		
		if(tab === undefined)
			tab = null;
		
		var changefunc = function(data)
		{
			$("#diacontent").html(data.content);
			playerControl.highlightSlide(highlight);
		}
		
		//if page is not already fetched, do it now
		if(_pageCache[url] === undefined)
		{
			fetchPage(url, function(data)
			{
				changefunc.call(this, data);
			}, this);
		}
		//else call page changing function with cached page data
		else
		{
			changefunc.call(this, _pageCache[url]);
		}
	}
	
	
	/**
	 * Prefetch image from given url to browser's cache
	 *
	 * @param string url
	 */
	function cacheImage(url)
	{
		var img = new Image();
		img.src = url;
	}
	
	
	//object of callbacks to perform on url after successful download
	var _fetchCallback = {};
	
	//object of urls that are being currently downloaded
	var _pendingFetches = {};
	
	
	/**
	 * Fetch page data from given index, perform callback after successful download
	 *
	 * @param string url URL to download
	 * @param function cb Callback function to perform after page data has been fetched
	 * @param ref contect Context where to perform callback
	 */
	function fetchPage(url, cb, context)
	{
		if(!url)
			return;
		
		//ensure that url has an array for callbacks
		if(_fetchCallback[url] === undefined)
			_fetchCallback[url] = [];
		
		//if callback is set, add it to _fetchCallback object
		if(cb !== undefined && cb.call !== undefined)
		{
			if(context === undefined)
				context = null;
			
			_fetchCallback[url][_fetchCallback[url].length] = function(data) {
				cb.call(context, data);
			}
		}
		
		//if requested page is already being fetched, no need to start another ajax request
		if(_pendingFetches[url] !== undefined && _pendingFetches[url] === true)
			return;
		
		//onsuccess callback for ajax
		var success = function(data, status)
		{
			var i;
			
			//cache images
			for(i=0; i<data.cacheableImages.length; i++)
				cacheImage(data.cacheableImages[i]);
			
			//store page data to cache
			_pageCache[url] = data;
			
			//get callback functions for fetched url, and reset
			var funcs = _fetchCallback[url];
			_fetchCallback[url] = [];
			
			//reset fetch flag
			_pendingFetches[url] = false;
			
			//perform all callbacks
			for(i in funcs)
				funcs[i].call(null, data);
		};
		
		var data = {};
		data[_pageRequestIdent] = 1;
		
		_pendingFetches[url] = true;
		
		$.ajax({
			"url" : url,
			"data" : data,
			"async" : true,
			"cache" : false,
			"type" : "POST",
			"dataType" : "json",
			"success" : success
		});
	}
	
	
	/**
	 * Public interface
	 */
	var pubint = {};
	
	
	/**
	 * Init
	 *
	 * @param object data JSON object of slides
	 */
	pubint.init = function(data)
	{
		var i, k, page;
		var pages = {}, pagelut = [];
		
		//build page map and lookup table
		for(i=0; i<data.pages.length; i++)
		{
			page = data.pages[i];
			pages[page.time] = {"url" : page.url, "segment" : page.segment};
			pagelut[pagelut.length] = page.time;
		}
		
		_pages = pages;
		_pagelut = pagelut;
		
		//startslide
		if(data.startslide !== undefined)
			_startslide = data.startslide.url;
		
		//endslide
		if(data.endslide !== undefined)
			_endslide = data.endslide.url;
		
		//if there is slides, fetch first one to cache
		if(pagelut.length > 0)
			fetchPage(pages[pagelut[0]].url);
	}
	
	
	/**
	 * Function to call when time on video changes
	 *
	 * @param int sec Seconds from beginning
	 */
	pubint.onVideoTimeChange = function(sec)
	{
		var i;
		/*
		//if player is stopped, current page is not a sequence slide and startslide is set
		if(_prevstate == 0 && _currentPage === null && _startslide !== null)
		{
			changeSlide(_startslide);
			return;
		}
		
		//if player has state "end" and endslide is set
		if(_prevstate == 3 && _endslide !== null)
		{
			changeSlide(_endslide);
			return;
		}
		*/
		//search for page to show on given second
		var current = null;
		for(i=0; i<_pagelut.length; i++)
		{
			if(_pagelut[i] > sec)
				break;
			current = _pagelut[i];
		}
		
		var nextpage = _pagelut[i] || null;
		
		//if slide has changed from previous, change it to GUI
		if(current !== null && _currentPage != current)
			changeToPage(current);
		
		//if there is next page, prefetch it to cache
		var nexturl = getUrlByIndex(nextpage);
		if(_pageCache[nexturl] === undefined)
			fetchPage(nexturl);
	}
	
	
	/**
	 * Function to call when state on videoplayer changes
	 *
	 * @param int player Player state (0 = stop, 1 = play, 2 = buffer, 3 = end)
	 */
	pubint.onVideoStateChange = function(state)
	{
if(state == "STARTING") {
				if(_startslide !== null)
				{
					changeSlide(_startslide);
					_currentPage = null;
				}
}
if(state == "COMPLETED") {
				if(_endslide !== null)
				{
					changeSlide(_endslide);
					_currentPage = null;
				}
}
/*
		if(state == 0)
		{
			//startslide
			if(_prevstate == null)
			{
				if(_startslide !== null)
				{
					changeSlide(_startslide);
					_currentPage = null;
				}
			}
			//endslide
			else if(_prevstate == 3)
			{
				if(_endslide !== null)
				{
					changeSlide(_endslide);
					_currentPage = null;
				}
			}
		}
		
		_prevstate = state;
*/
	}
	
	
	return pubint;
})();