function SlideShowConfig()
{
	// the node that this slider is inserted into
	this.main_wrapper_node;

	// key_name gets prefixed to all ids and css class names (optional)
	this.key_name = '';
	
	// the function that is called to get the content of each slide (by ordinal slide number) 
	this.GetSlide_function_ptr;
	
	// the function that is called when a slide transitions starts (optional)
	this.onslidetransition_callback;

	// the function that is called when a slide changes without a transition (optional)
	this.onslidechange_callback;
	
	// the total slides available
	this.slide_count = 2;
	
	// shows the control area (the area with slide numbers and play/pause)
	this.is_show_control = true;
	
	// shows the interval bar
	this.is_show_control_interval_bar = true;
	
	// shows the play/pause button in the control area
	this.is_show_control_interval_pause = true;
	
	// the height of each slide (if = 0 then slide height will be determined from the slide content)
	this.height = 0;
	
	// the initial height (height when loaded) of the first slide
	this.initial_height = 200;
	
	// the amount of time it takes for a slide to transition across the viewable area
	this.transition_duration = 500;		// ms
	
	// the amount of time a slide is delayed before transitioning
	this.transition_delay = 10;			// ms
	
	// the distance between the first slide and the second slide during a transition
	this.transition_gap = 10;			// px
	
	// the amount of time a slide is still in-between transitions
	this.slide_duration = 2000;			// ms
	
	this.control_interval_pause_content = '||';
	this.control_interval_play_content = '>';
	this.control_interval_bar_innerHTML = '> > > >';
	this.control_interval_bar_size = 45;	// px
}


// create slideshow obj
function SlideShow(slideshow_config_obj)
{
	this.config_obj = slideshow_config_obj;
	this.SetupData();
}

SlideShow.prototype.SetupData = function()
{
	this.key_name = this.config_obj.key_name;
	this.key_name_with_underscore = this.key_name?this.key_name+'_':'';
	this.main_wrapper_node = this.config_obj.main_wrapper_node;

	this.interval_id;
	this.interval_animation = null;

	this.SetInternalState_SlideNum(1);

	// *** create html area
	this.wrapper_node = document.createElement('div');
	this.wrapper_node.id = this.key_name_with_underscore+'slide_wrapper';
	this.wrapper_node.className = this.key_name_with_underscore+'slide_wrapper';
	this.main_wrapper_node.appendChild(this.wrapper_node);

	if(this.config_obj.is_show_control == true)
	{
		this.control_node = document.createElement('div');
		this.control_node.id = this.key_name_with_underscore+'control_wrapper';
		this.control_node.className = this.key_name_with_underscore+'control_wrapper';
		this.main_wrapper_node.appendChild(this.control_node);
	}

	// *** create/setup slider obj
	var slider_config = new PaneSliderConfig();
	slider_config.is_wrapper_auto_height = parseInt(this.config_obj.height)?false:true;
	slider_config.is_wrapper_animate_height = parseInt(this.config_obj.height)?false:true;
	slider_config.height = parseInt(this.config_obj.height)?parseInt(this.config_obj.height):parseInt(this.config_obj.initial_height);
	slider_config.height_duration = parseInt(this.config_obj.transition_duration);
	slider_config.height_delay = parseInt(this.config_obj.transition_delay);
	slider_config.in_duration = parseInt(this.config_obj.transition_duration);
	slider_config.in_delay = parseInt(this.config_obj.transition_delay);
	slider_config.out_duration = parseInt(this.config_obj.transition_duration);
	slider_config.out_delay = parseInt(this.config_obj.transition_delay);
	slider_config.transition_gap = parseInt(this.config_obj.transition_gap);
	this.slider_obj = new PaneSlider(this.wrapper_node, slider_config);

}

SlideShow.prototype.InitDisplay = function()
{
	// *** create control area
	if(this.config_obj.is_show_control == true && this.control_node)
	{
		this.control_node.style.display = '';
		this.control_node.innerHTML = '';
		
		for(i=0; i<this.GetSlideCount(); i++)
		{
			
			//tmp_node = document.createElement('span');
			//tmp_node.innerHTML = '<span id="slideshow_content_item_'+(i+1)+'" class="slideshow_counter_item_normal" onmouseover="slideshow_obj.StopOnSlide(\''+(i+1)+'\');" onmouseout="slideshow_obj.StartOnSlide(\''+(i+1)+'\');" onclick="window.location = \''+this.data_obj_array[i].link+'\'">' + (i+1) + '</span>';
			//this.control_node.appendChild(tmp_node);
			this.control_node.innerHTML += '<span id="'+this.key_name_with_underscore+'slideshow_content_item_'+(i+1)+'" class="slideshow_counter_item_normal" onmouseover="slideshow_obj.StopOnSlide(\''+(i+1)+'\');" onmouseout="slideshow_obj.StartOnSlide(\''+(i+1)+'\');">' + (i+1) + '</span>';
		}
	}
	else if(this.control_node)
	{
		this.control_node.style.display = 'none';
	}

	if(this.config_obj.is_show_control_interval_pause == true && this.control_node)
	{
		tmp_node = document.createElement('span');
		tmp_node.innerHTML = '<span id="'+this.key_name_with_underscore+'slideshow_interval_pause" style="" class="'+this.key_name_with_underscore+'slideshow_counter_pause" onclick="slideshow_obj.Stop();">'+this.config_obj.control_interval_pause_content+'</span>';
		tmp_node.innerHTML += '<span id="'+this.key_name_with_underscore+'slideshow_interval_play" style="" class="'+this.key_name_with_underscore+'slideshow_counter_play" onclick="slideshow_obj.Start();">'+this.config_obj.control_interval_play_content+'</span>';
		this.control_node.appendChild(tmp_node);
		this.ClearIntervalAnimation();
	}
	
	if(this.config_obj.is_show_control_interval_bar == true)
	{
		tmp_node_wrapper = document.createElement('div');
		tmp_node_wrapper.id = this.key_name_with_underscore+'slideshow_interval_bar_wrapper';
		tmp_node_wrapper.className = this.key_name_with_underscore+'slideshow_interval_bar_wrapper';
		
		tmp_node = document.createElement('span');
		tmp_node.id = this.key_name_with_underscore+'slideshow_interval_bar';
		tmp_node.className = this.key_name_with_underscore+'slideshow_interval_bar';
		tmp_node.innerHTML = this.config_obj.control_interval_bar_innerHTML;
		tmp_node_wrapper.appendChild(tmp_node);
		this.main_wrapper_node.appendChild(tmp_node_wrapper);
		this.ClearIntervalAnimation();
	}




}

SlideShow.prototype.GetInternalState_SlideNum = function()
{
	return parseInt(this.cur_state_slide_num);
}
SlideShow.prototype.SetInternalState_SlideNum = function(slide_num)
{
	this.cur_state_slide_num = parseInt(slide_num);
}

// instantly show slide
SlideShow.prototype.SetForegroundSlide = function(slide_num)
{
	var previous_slide_num = this.GetInternalState_SlideNum();
	
	this.SetInternalState_SlideNum(slide_num);
	this.DoControlHighlight(slide_num);
	this.slider_obj.SetForegroundContent(this.GetSlideContent(this.GetInternalState_SlideNum()));
	
	if(this.config_obj.onslidechange_callback)
		this.config_obj.onslidechange_callback(slide_num, previous_slide_num);
}
// transition for current slide content to slide_num slide content
SlideShow.prototype.DoForegroundTransition = function(slide_num)
{
	var previous_slide_num = this.GetInternalState_SlideNum();
	this.SetInternalState_SlideNum(slide_num);
	this.DoControlHighlight(slide_num)
	this.slider_obj.SetBackgroundContent(this.GetSlideContent(slide_num));
	this.slider_obj.DoTransition(0);
	
	if(this.config_obj.onslidetransition_callback)
		this.config_obj.onslidetransition_callback(slide_num, previous_slide_num);
}

// instantly highlight the specified control number (and un-highlight the rest)
SlideShow.prototype.DoControlHighlight = function(slide_num)
{
	var i=0;
	if(this.config_obj.is_show_control == true && this.control_node)
	{	
		for(i=0; i<this.GetSlideCount(); i++)
		{
			dojo.byId(this.key_name_with_underscore+'slideshow_content_item_'+(i+1)).className = this.key_name_with_underscore+'slideshow_counter_item_normal';
		}
		dojo.byId(this.key_name_with_underscore+'slideshow_content_item_'+slide_num).className = this.key_name_with_underscore+'slideshow_counter_item_highlight';
	}
}

// transition the highlight of the from_num slide to the slide_num slide (and un-highlight the rest)
SlideShow.prototype.DoControlHighlightTransition = function(slide_num, from_num)
{
	// to-do: if needed
}

// start the slide loop
SlideShow.prototype.Start = function()
{
	if(parseInt(this.config_obj.slide_duration))
	{
		this.StartIntervalAnimation();
		this.interval_id = setInterval(this.GoNext, parseInt(this.config_obj.slide_duration));
		if(this.config_obj.is_show_control_interval_pause == true && dojo.byId(this.key_name_with_underscore+'slideshow_interval_pause'))
		{
			dojo.byId(this.key_name_with_underscore+'slideshow_interval_pause').style.display = '';
			dojo.byId(this.key_name_with_underscore+'slideshow_interval_play').style.display = 'none';
		}
	}
}

SlideShow.prototype.StartIntervalAnimation = function()
{
	if(this.config_obj.is_show_control_interval_bar == true)
	{
		if(this.interval_animation)
		{
			this.interval_animation.stop();
		}
	
		if(dojo.byId(this.key_name_with_underscore+'slideshow_interval_bar_wrapper'))
		{
			dojo.byId(this.key_name_with_underscore+'slideshow_interval_bar_wrapper').style.display = '';
			dojo.byId(this.key_name_with_underscore+'slideshow_interval_bar_wrapper').style.width = '0';

			this.interval_animation = dojo.animateProperty( 
			{
				node: dojo.byId(this.key_name_with_underscore+'slideshow_interval_bar_wrapper'),
				duration: parseInt(this.config_obj.slide_duration), // ms to run animation
				delay: 0, // ms to stall before playing
				properties:{width: {end: this.config_obj.control_interval_bar_size}}
			});
			this.interval_animation.play();
		}
	}
}

SlideShow.prototype.ClearIntervalAnimation = function()
{
	if(this.config_obj.is_show_control_interval_bar == true)
	{
		if(this.interval_animation)
		{
			this.interval_animation.stop();
		}
	
		if(dojo.byId(this.key_name_with_underscore+'slideshow_interval_bar'))
		{
			dojo.byId(this.key_name_with_underscore+'slideshow_interval_bar_wrapper').style.width = '0';
			dojo.byId(this.key_name_with_underscore+'slideshow_interval_bar_wrapper').style.display = 'none';
		}
	}
}

// stop the slide loop
SlideShow.prototype.Stop = function()
{
	 clearInterval(this.interval_id);
	 this.ClearIntervalAnimation();
	 if(this.config_obj.is_show_control_interval_pause == true && dojo.byId(this.key_name_with_underscore+'slideshow_interval_play'))
	 {
	 	dojo.byId(this.key_name_with_underscore+'slideshow_interval_play').style.display = '';
	 	dojo.byId(this.key_name_with_underscore+'slideshow_interval_pause').style.display = 'none';
	 }
}

// instantly go to a specific slide and stop the loop
SlideShow.prototype.StopOnSlide = function(slide_num)
{
	this.SetForegroundSlide(slide_num);
	this.Stop();
}

// transition directly to a specific slide and stop the loop
SlideShow.prototype.StopOnSlideTransition = function(slide_num)
{
	
	
	this.DoForegroundTransition(slide_num);

	this.Stop();
}

// instantly go to a specific slide and start the loop
SlideShow.prototype.StartOnSlide = function(slide_num)
{
	this.Stop();
	
	this.SetInternalState_SlideNum(slide_num);
	this.SetForegroundSlide(slide_num);
	
	this.Start();
}

// transition directly to a specific slide and start the loop
SlideShow.prototype.StartOnSlideTransition = function(slide_num)
{
	this.Stop();
	
	this.DoForegroundTransition(slide_num);
	
	this.Start();
}


SlideShow.prototype.GetSlideContent = function(slide_num)
{
	if(this.config_obj.GetSlide_function_ptr)
		return this.config_obj.GetSlide_function_ptr(slide_num);
	else
		return 'No content function defined.';
}

SlideShow.prototype.GetSlideCount = function()
{
	return parseInt(this.config_obj.slide_count);
}

// transition to the next slide in the loop
SlideShow.prototype.GoNext = function()
{
	var cur_scope_parent;
	var new_slide_num;
	if(this.slider_obj)
	{
		cur_scope_parent = this;
	}
	else
	{
		cur_scope_parent = slideshow_obj;
	}
	
	if(cur_scope_parent.GetInternalState_SlideNum() < cur_scope_parent.GetSlideCount())
	{
		new_slide_num = cur_scope_parent.GetInternalState_SlideNum() + 1;
	}
	else
	{
		new_slide_num = 1;
	}
	
	cur_scope_parent.DoForegroundTransition(new_slide_num);
	
	cur_scope_parent.StartIntervalAnimation();
}
