// requires jquery library

var SSDisplay = jQuery.extend({},{
	
	_parameters: {},
	_html_content: {},
	_preloaded: {},
	_html_caption: {},
	_html_swf_data: {},
	_loading_content: {},
	_random_order_offsets: {},
	_auto_advance_token: {},
	
	_pause_speed: 200,
	_animate_pause: false,
	_debug_enabled: false,
	
	getParameter: function(id, name, default_val) {
		if (typeof(this._parameters[id][name]) == 'undefined') return default_val;
		return this._parameters[id][name];
	},
	getBooleanParameter: function(id, name, default_val) {
		return (this.getParameter(id, name, default_val) == '1' || this.getParameter(id, name, default_val) == true);
	},
	setParameter: function(id, name, value) {
		if (typeof(this._parameters[id]) == 'undefined') this._parameters[id] = {};
		this._parameters[id][name] = value;
	},
	
	setParameters: function(id, parameters) {
		this._parameters[id] = parameters;
	},
	setParametersOnLoad: function(id, parameters) {
		jQuery(document).ready(function() { SSDisplay.setParameters(id, parameters);	});
	},

	setContent: function(id, content_offset, html_content, image_src) {
		if (typeof(this._html_content[id]) == 'undefined') this._html_content[id] = {};
		this._html_content[id][content_offset] = html_content;
		if (image_src.length > 0) {
			this._preloadImage(id, content_offset, image_src);
		} else {
			// load into a hidden div
			jQuery('<div>').append(html_content);
			this._setContentPreloaded(id, content_offset, true);
		}
	},
	setContentOnLoad: function(id, content_offset, html_content, image_src) {
		jQuery(document).ready(function() { SSDisplay.setContent(id, content_offset, html_content, image_src);	});
	},

	setCaption: function(id, content_offset, html_caption) {
		if (typeof(this._html_caption[id]) == 'undefined') this._html_caption[id] = {};
		this._html_caption[id][content_offset] = html_caption;
	},
	setCaptionOnLoad: function(id, content_offset, html_caption) {
		jQuery(document).ready(function() { SSDisplay.setCaption(id, content_offset, html_caption);	});
	},

	setSWFData: function(id, content_offset, swf_data) {
		if (typeof(this._html_swf_data[id]) == 'undefined') this._html_swf_data[id] = {};
		this._html_swf_data[id][content_offset] = swf_data;

		// do not setContent - because swfobject won't work
		// set content so we know it exists
		// this.setContent(id, content_offset, '', '');
	},
	setSWFDataOnLoad: function(id, content_offset, html_caption) {
		jQuery(document).ready(function() { SSDisplay.setSWFData(id, content_offset, html_caption);	});
	},

	setRandomOffsets: function(id, random_order_offsets) {
		if (typeof(this._random_order_offsets[id]) == 'undefined') this._random_order_offsets[id] = [];
		this._random_order_offsets[id] = random_order_offsets;
	},
	setRandomOffsetsOnLoad: function(id, random_order_offsets) {
		jQuery(document).ready(function() { SSDisplay.setRandomOffsets(id, random_order_offsets);	});
	},
	

	init: function(id) {
		jQuery(document).ready(function() {
			SSDisplay.setAutoAdvance(id, false);
		});
	},

	setAutoAdvance: function(id, add_fade_time) {
		// this._debug('setAutoAdvance '+id);
		var advance_type = this.getParameter(id,'advance_type','manual');
		// alert('setAutoAdvance advance_type='+advance_type+'')
		if (advance_type == 'timed') {
			var time_delay = parseInt(this.getParameter(id, 'time_delay', 0));
			if (add_fade_time) {
				// wait for the image to fade in before auto advancing again
				time_delay = time_delay + parseInt(this.getParameter(id, 'fade_length', 0));
			}

			// minimum delay of 5 ms
			if (time_delay <= 0) time_delay = 5;
			
			// update the auto advance token
			var next_token = this._updateAutoAdvanceToken(id);

			// wait for delay
			window.setTimeout(function() { SSDisplay.autoAdvance(id, next_token); }, time_delay);
		}
	},

	autoAdvance: function(id, token) {
		// this._debug('autoAdvance(id, '+token+') this._getAutoAdvanceToken(id)='+this._getAutoAdvanceToken(id))

		// if the token is old, just ignore it
		if (token < this._getAutoAdvanceToken(id)) return;
		
		// if paused, ignore it
		if (this.getBooleanParameter(id, 'paused', false)) return;
		
		// increment the offset
		var new_offset = this._nextOffset(id, this.getParameter(id, 'offset', 0));

		// animate the new content
		// this._debug('advancing to '+new_offset)
		return this.advanceTo(id, new_offset);
	},

	manualAdvance: function(link_type, id) {
		if (link_type == 'pause' || link_type == 'play') {
			this.pause(id);

			// cancel the click event
			return false;
		}
		
		// increment the offset
		var new_offset = this._nextManualOffset(link_type, id);
		
		// animate the new content
		return this.advanceTo(id, new_offset);
	},

	pause: function(id) {
		var paused = this.getBooleanParameter(id, 'paused', false);
//		this._debug('paused = '+paused)
		if (paused) {
			// start playing
			this.setParameter(id, 'paused', false);
			if (this._animate_pause) {
				this._beginPlay(id);
			} else {
				this._switchToPauseLink(id);
			}
			this.manualAdvance('next', id);
		} else {
			// stop playing
			this.setParameter(id, 'paused', true);
			if (this._animate_pause) {
				this._beginPause(id);
			} else {
				this._switchToPlayLink(id);
			}
		}
	},
	
	advanceTo: function(id, new_offset) {
		var old_offset = this.getParameter(id, 'offset', 0);
		this.setParameter(id, 'offset', new_offset);
		
		// mark no offset as currently displayed
		this.setParameter(id,'displayed_offset',-1);
		
		// begin the fade out
		var speed = this.getParameter(id,'fade_length',0);
		this._beginFadeOut(id);
		if (speed > 0 && !this._swfDataExists(id, this._resolveOffset(id, old_offset))) {
			// fade caption with no callback
			jQuery('#_awcSSCaption'+id).fadeTo(speed, 0);
			jQuery('#_awcSSContent'+id).fadeTo(speed, 0, function() {
				SSDisplay._endFadeOut(id);
				SSDisplay.showCurrentOffset(id);
			});
		} else {
			// speed is 0 - no fade out
			//  jump directly to showing the new content
			this._endFadeOut(id);
			this.showCurrentOffset(id);
		}

		// cancel the onclick event
		return false;
	},
	
	showCurrentOffset: function(id) {
		var offset = this.getParameter(id,'offset',0);
		var content_offset = this._resolveOffset(id, offset);
//		this._debug('resolved offset '+offset+' = '+content_offset+'');

		var image_rows_count = this.getParameter(id,'image_rows_count',0);
		// if there are no image rows to show, just exit
		if (image_rows_count < 1) return true;
		
		
		var displayed_offset = this.getParameter(id,'displayed_offset',-1);
		// this._debug('=== begin showCurrentOffset offset='+offset+'')
		if (displayed_offset != -1 && displayed_offset == content_offset) {
			// this._debug('in showCurrentOffset displayed_offset ('+displayed_offset+') was equal to content_offset ('+content_offset+') so we are done')
			// already displayed
			return true;
		}

		// load the content from memory
		var content = this._getContent(id, content_offset);
		if (content == null) {
//			this._debug('in showCurrentOffset content is null - initiating load content from server')
			// content is not in memory, load it from the server
			this._loadContentFromServer(id, content_offset);
			return false;
		}
//		this._debug('in showCurrentOffset content was '+escape(content).substr(0, 20)+'...')
		
		// if not preloaded, then wait 250 ms and try again
		if (!this._isContentPreloaded(id, content_offset)) {
			// this._debug('in showCurrentOffset _isContentPreloaded was false - trying again later')
			window.setTimeout(function() { SSDisplay.showCurrentOffset(id); }, 250);
			return false;
		}
		// this._debug('in showCurrentOffset _isContentPreloaded was true')
		

		// assume caption exists if content exists
		var caption = this._getCaption(id, content_offset);

		// initiate the fade in
		this._showContent(id, content_offset, content, caption);
		
		// mark as currently displayed
		this.setParameter(id,'displayed_offset',content_offset);
		
		// set auto advance
		this.setAutoAdvance(id, true);
		
		// load any other content we might need
		this._prefetchNextOffset(id, offset);
		
		// highlight the correct page if it exists
		this._updateHighlightedPage(id, offset);
		
//		this._debug('end showCurrentOffset offset='+offset+'')
		return true;
	},
	
	_updateHighlightedPage: function(id, offset) {
		var page_class_name = this.getParameter(id, 'page_class', false);
		var highlighted_page_class_name = this.getParameter(id, 'page_highlighted_class', false);
		
		// highlight the current one
		//  and turn off all other highlights
		var prefix = '_awcSSPage'+id+'-';
		jQuery("*[id^='"+prefix+"']").each(function(index) {
			var jq_obj = jQuery(this);
			var current_offset = jq_obj.attr('id').substr(prefix.length);
			if (current_offset == offset) {
				// is highlighted
				if (page_class_name !== null && page_class_name.length) jq_obj.removeClass(page_class_name);
				if (highlighted_page_class_name !== null && highlighted_page_class_name.length) jq_obj.addClass(highlighted_page_class_name);
			} else {
				// is not highlighted
				if (highlighted_page_class_name !== null && highlighted_page_class_name.length) jq_obj.removeClass(highlighted_page_class_name);
				if (page_class_name !== null && page_class_name.length) jq_obj.addClass(page_class_name);
			}
		});
	},
	
	
	// prefetches the next needed item - but no more than one
	_prefetchNextOffset: function(id, offset) {
		var maximum_preload_count = this.getParameter(id,'maximum_preload_count',0);
		var starting_offset = offset;
		var next_offset = starting_offset;
		for (var i=0; i < maximum_preload_count; i++) {
			next_offset = this._nextOffset(id, next_offset);
			var content_offset = this._resolveOffset(id, next_offset);
//			this._debug('_contentExists for '+content_offset+'='+this._contentExists(id, content_offset))
			if (!this._contentExists(id, content_offset)) {
				this._loadContentFromServer(id, content_offset);
				return true;
			}
		}
		
		// all are already in memory
		return true;
	},
	
	_loadContentFromServer: function(id, content_offset) {
		if (this._loading_content[id]) return;
		
		// call the server to update the content
		var params = {
			'id':id,
			'stage_id':this.getParameter(id,'stage_id',0),
			'component':'snapshot_display',
			'method':'rotateImage',
			// 'link_type':link_type,
			'offset':content_offset
		};
		
		jQuery.post('/_awc_ajax', params, function(response_html){ SSDisplay._loadComplete(id, content_offset, response_html); });

		this._loading_content[id] = true;
	},
	
	_loadComplete: function(id, content_offset, response_html) {
//		this._debug('_loadComplete for '+content_offset+'')
		// evaluate the scripts contained in the response html
		// jQuery.globalEval(response_html);

//		this._debug('_loadComplete BEGIN eval of '+escape(response_html).substr(0,40)+'')
		eval(''+response_html);
//		this._debug('_loadComplete END eval of '+escape(response_html).substr(0,40)+'')

		// mark as no longer loading
		this._loading_content[id] = false;
		
		// always try to display the current offset, even if it is not necessary
		this.showCurrentOffset(id);
	},

	_getContent: function(id, content_offset) {
		if (typeof(this._html_content[id]) == 'undefined') return null;
		if (typeof(this._html_content[id][content_offset]) == 'undefined') return null;
		return this._html_content[id][content_offset];
	},
	_contentExists: function(id, content_offset) {
		if (typeof(this._html_content[id]) == 'undefined') return false;
		if (typeof(this._html_content[id][content_offset]) == 'undefined') return false;
		return true;
	},
	_getCaption: function(id, content_offset) {
		if (typeof(this._html_caption[id]) == 'undefined') return null;
		if (typeof(this._html_caption[id][content_offset]) == 'undefined') return null;
		return this._html_caption[id][content_offset];
	},
	_getSWFData: function(id, content_offset) {
		if (typeof(this._html_swf_data[id]) == 'undefined') return null;
		if (typeof(this._html_swf_data[id][content_offset]) == 'undefined') return null;
		return this._html_swf_data[id][content_offset];
	},
	_swfDataExists: function(id, content_offset) {
		if (typeof(this._html_swf_data[id]) == 'undefined') return false;
		if (typeof(this._html_swf_data[id][content_offset]) == 'undefined') return false;
		return true;
	},

	_showContent: function(id, content_offset, content, caption) {
		// replace the content
		jQuery('#_awcSSContent'+id).empty();
		jQuery('#_awcSSCaption'+id).empty();

		var swf_data = this._getSWFData(id, content_offset);
		if (swf_data != null) {
			// write a new div inside the div
				jQuery('#_awcSSContent'+id).append('<div id="_awcmovie">...</div>');
			
			// use swobject2 to load in the data
			swfobject.embedSWF(swf_data['url'], '_awcmovie', swf_data['width'], swf_data['height'], '7.0.0');

			// use swobject to load in the data
			// var so = new SWFObject(swf_data['url'], "_awcmovie", swf_data['width'], swf_data['height'], "8", "");
			// so.write('_awcSSContent'+id);
			
			// no fade in
			this._endFadeIn(id);
		} else {
			jQuery('#_awcSSContent'+id).append(content);
			jQuery('#_awcSSCaption'+id).append(caption);

			var speed = this.getParameter(id,'fade_length',0);
			this._beginFadeIn(id);
			if (speed > 0) {
				jQuery('#_awcSSCaption'+id).fadeTo(speed, 1);
				jQuery('#_awcSSContent'+id).fadeTo(speed, 1, function() {
					SSDisplay._endFadeIn(id);
				});
			} else {
				this._endFadeIn(id);
			}
		}
		

		
		return true;
	},
	


	_nextManualOffset: function(link_type, id) {
		var offset = this.getParameter(id,'offset',0);
		var image_rows_count = this.getParameter(id,'image_rows_count',0);
//		alert('getParameter('+id+',\'image_rows_count\',0) = '+image_rows_count+'')

		switch(link_type) {
			case 'next':
				offset = this._nextOffset(id, offset);
			break;
			case 'previous':
				--offset;
				if (offset < 0) {
					offset = image_rows_count - 1;
					var advance_type = this.getParameter(id,'advance_type','manual');
					if (advance_type == 'timed') {
						var random_order = this.getBooleanParameter(id, 'random_order', false);
						if (random_order) {
							// this is a timed, random order
							//  there is no end
							offset = 0;
						}
					}
				}
			break;
			case 'start_over': offset = 0; break;
		}

		return offset;
	},
	
	_nextOffset: function(id, offset) {
		var advance_type = this.getParameter(id,'advance_type','manual');
		var image_rows_count = this.getParameter(id,'image_rows_count',0);
		++offset;
		
		var offset_cycles = true;
		if (advance_type == 'timed') {
			var random_order = this.getBooleanParameter(id, 'random_order', false);
			if (random_order) offset_cycles = false;
		}

		if (offset_cycles && offset > image_rows_count-1) offset = 0;
		return offset;
	},
	

	_beginFadeOut: function(id) {
		
	},
	_endFadeOut: function(id) {
		
	},
	_beginFadeIn: function(id) {
		
	},
	_endFadeIn: function(id) {
		
	},
	
	_resolveOffset: function(id, offset) {
		var advance_type = this.getParameter(id,'advance_type','manual');
		switch(advance_type) {
			case 'timed':
				var random_order = this.getBooleanParameter(id, 'random_order', false);
				if (random_order) {
					this._fillRandomOrderOffsetThroughOffset(id, offset);
//					this._debug('this._random_order_offsets['+offset+'] = '+this._random_order_offsets[id][offset]);
					return this._random_order_offsets[id][offset];
				}
			break;

			default:
				// don't do anything special
			break;
		}

		return offset;
	},
	
	_fillRandomOrderOffsetThroughOffset: function(id, offset) {
		var image_rows_count = this.getParameter(id,'image_rows_count',0);
		if (image_rows_count < 1) return;
		var cycle_all = this.getBooleanParameter(id, 'cycle_all', false);
		var safety_counter = 100;
		while (this._random_order_offsets[id].length - 1 < offset) {
			if (cycle_all) {
				var starting_offset = this._random_order_offsets[id].length - (this._random_order_offsets[id].length % image_rows_count);
				if (isNaN(starting_offset)) {
					break;
				}
				// this._debug('this._random_order_offsets[id].length='+this._random_order_offsets[id].length+' starting_offset='+starting_offset+'');

				// load this cycle map
				var cycle_offsets = [];
				for (var i=starting_offset; i < this._random_order_offsets[id].length; i++) {
					cycle_offsets[cycle_offsets.length] = this._random_order_offsets[id][i];
				}

				// build this cycle
				var cycle_offsets = this._completeCycle(cycle_offsets, image_rows_count);

				// add this cycle to the random order offsets
				var ending_offset = starting_offset + cycle_offsets.length;
				var cycle_counter = 0;
				for (var i=starting_offset; i < ending_offset; i++) {
					this._random_order_offsets[id][i] = cycle_offsets[cycle_counter];
					++cycle_counter;
				}

//				this._debug('offset='+offset+' starting_offset='+starting_offset+' ending_offset='+ending_offset+' image_rows_count='+image_rows_count+' cycle_offsets='+cycle_offsets+'');
//				this._debug('ALL='+this._random_order_offsets[id]+'');
			} else {
				// just add a random number to the end
				do {
					next_number = Math.round(Math.random() * (image_rows_count - 1));
				} while (this._random_order_offsets[id][this._random_order_offsets[id].length] > 0 && next_number == this._random_order_offsets[id][this._random_order_offsets[id].length - 1] && image_rows_count > 1);
				this._random_order_offsets[id][this._random_order_offsets[id].length] = next_number;
			}
			// if (--safety_counter < 	1) {
			// 	this._debug('safety_counter reached');
			// 	break;
			// }
		}
	},
	
	_completeCycle: function(cycle_offsets, image_rows_count) {
		// init the used map
		var used_map = [];
		for (var i=0; i < image_rows_count; i++) {
			used_map[i] = false;
		}
		for (var i=0; i < cycle_offsets.length; i++) {
			used_map[cycle_offsets[i]] = true;
		};

		var remaining = image_rows_count - cycle_offsets.length;
		var map_offset;
		while (remaining > 0) {
			random = Math.round(Math.random() * (remaining-1));
			for(map_offset in used_map) {
				var used_flag = used_map[map_offset];
				if (!used_flag) {
					if (random <= 0) {
						break;
					} else {
						--random;
					}
				}
			}

			cycle_offsets[cycle_offsets.length] = map_offset;
			used_map[map_offset] = true;
			--remaining;
		}

		return cycle_offsets;
	},
	
	_updateAutoAdvanceToken: function(id) {
		if (typeof(this._auto_advance_token[id]) == 'undefined') this._auto_advance_token[id] = 0;
		++this._auto_advance_token[id];
		return this._auto_advance_token[id];
	},

	_getAutoAdvanceToken: function(id) {
		if (typeof(this._auto_advance_token[id]) == 'undefined') return -1;
		return this._auto_advance_token[id];
	},

	_beginPause: function(id) {
		jQuery('#_awcSSPause'+id).fadeTo(this._pause_speed, 0, function() {
			SSDisplay._endPause(id);
		});
	},
	_endPause: function(id) {
		this._switchToPlayLink(id);
		jQuery('#_awcSSPause'+id).fadeTo(this._pause_speed, 1);
	},
	_switchToPauseLink: function(id) {
		var link_html = this.getParameter(id,'pause_link','');
		jQuery('#_awcSSPause'+id).empty();
		jQuery('#_awcSSPause'+id).append(link_html);
	},

	_beginPlay: function(id) {
		jQuery('#_awcSSPause'+id).fadeTo(this._pause_speed, 0, function() {
			SSDisplay._endPlay(id);
		});
	},
	_endPlay: function(id) {
		this._switchToPauseLink(id);
		jQuery('#_awcSSPause'+id).fadeTo(this._pause_speed, 1);
	},
	_switchToPlayLink: function(id) {
		var link_html = this.getParameter(id,'play_link','');
		jQuery('#_awcSSPause'+id).empty();
		jQuery('#_awcSSPause'+id).append(link_html);
	},


	// preloading
	_isContentPreloaded: function(id, content_offset) {
//		this._debug('_isContentPreloaded content_offset=content_offset typeof(this._preloaded[id])='+typeof(this._preloaded[id])+' typeof(this._preloaded[id]['+content_offset+']='+typeof(this._preloaded[id][content_offset])+' returning '+this._preloaded[id][content_offset]);
		if (typeof(this._preloaded[id]) == 'undefined') return false;
		if (typeof(this._preloaded[id][content_offset]) == 'undefined') return false;
		return this._preloaded[id][content_offset];
	},
	_setContentPreloaded: function(id, content_offset, preloaded) {
		// this._debug('begin _setContentPreloaded('+id+', '+content_offset+', '+preloaded+')')
		if (typeof(this._preloaded[id]) == 'undefined') this._preloaded[id] = {};
		this._preloaded[id][content_offset] = preloaded;
		// this._debug('_setContentPreloaded this._preloaded[id]['+content_offset+'] set to '+this._preloaded[id][content_offset])
	},
	_preloadImage: function(id, content_offset, image_src) {
		// this._debug('_preloadImage '+content_offset+'');
		if (image_src.length > 0) {
			var img = new Image();
			img.onload = function() {
				SSDisplay._debug('img onload '+content_offset+' complete')
				SSDisplay._setContentPreloaded(id, content_offset, true);
			}
			img.src = image_src;
		}
	},

	
	_debug: function(text) {
		if (!this._debug_enabled) return;
		jQuery('body').append(text+'<br />');
	},
	
	_end: {}
});


