var IE = (typeof(document.all) == 'undefined' ? false : true)

var current_id = 0

// fade parameters. be careful. make sure they divide evenly
var fade_time = 250
var fade_granularity = (IE ? 10 : 15) // IE is pretty slow and doesn't actually fade in time, so we have to reduce the granularity so it can cope with the copious timeouts ;)
var fade_interval = fade_time / fade_granularity
var fade_adjustment = 1 / fade_granularity
var fade_pause = 50

function debug(text) {
	if (IE) return alert('debug: ' + text)
	var text = document.createTextNode('debug: ' + text)
	var p = document.createElement('p')
	p.appendChild(text)
	document.documentElement.appendChild(p)
}

function get_child_elements(parent) {
	var nodes = parent.childNodes
	var children = []
	for (var i = 0; i < nodes.length; i++)
		if (nodes[i].nodeType == 1) children.push(nodes[i])
	return children
}

var get_opacity = function(element) {
	return parseFloat((element.constructor == Array ? element[0] : element).style.opacity)
}

var set_opacity = function(element, opacity) {
	element.style.opacity = opacity
	if (IE)	element.style.filter = 'alpha(opacity=' + Math.round(opacity == 0 ? 0 : opacity * 100) + ')'
}

var adjust_opacity = function(element, adjustment) {
	if (element.constructor == Array) {
		var opacity
		for (var i = 0; i < element.length; i++) {
			opacity = adjust_single_opacity(element[i], adjustment)
		}
		return opacity
	} else
		return adjust_single_opacity(element, adjustment)
}

var adjust_single_opacity = function(element, adjustment) {
	opacity = get_opacity(element) + adjustment
	set_opacity(element, opacity)
	return opacity
}

var hide = function(element, opacity) {
	if (typeof(opacity) == 'undefined') opacity = 0

	if (element.constructor == Array) {
		for (var i = 0; i < element.length; i++) {
			set_opacity(element[i], opacity)
			element[i].style.display = 'none'
		}
	} else {
		set_opacity(element, opacity)
		element.style.display = 'none'
	}
}

var show = function(element, opacity) {
	if (typeof(opacity) == 'undefined') opacity = 1
	
	if (element.constructor == Array) {
		for (var i = 0; i < element.length; i++) {
			set_opacity(element[i], opacity)
			element[i].style.display = 'block'
		}
	} else {
		set_opacity(element, opacity)
		element.style.display = 'block'
	}
}

/* Slideshow class */

function Slideshow(items, index, scroll_interval, on_scroll) {
	this.items = items
	this.active_index = (typeof(index) != 'undefined' ? index : 0)
	for (var i = 0; i < items.length; i++) {
		if (i == this.active_index)
			show(items[i])
		else
			hide(items[i])
		if (IE && !items[i].currentStyle.hasLayout) items[i].style.zoom = 1
	}
	
	this.on_scroll = on_scroll
	this.scroll_timer = null
	this.scroll_function = this.scroll_forward
	this.scroll_interval = (typeof(scroll_interval) != 'undefined' ? scroll_interval : 5000)
	
	this.fade_out_timer = null
	this.fade_in_timer = null
	
	// so we can reference ourself in call backs and the like
	this.id = 'Slideshow_ref' + current_id++
	window[this.id] = this
	this.id = 'window.' + this.id
}

Slideshow.prototype.start_fade_out = function(new_index) {
	if (this.fade_out_timer == null) {
		this.fade_out_timer = -1
		clearInterval(this.fade_in_timer)
		this.fade_in_timer = null
		this.fade_out_timer = setInterval(this.id + '.fade_out(' + this.active_index + ')', fade_interval)
	}
	this.active_index = new_index
}

Slideshow.prototype.fade_out = function(old_index) {
	if (adjust_opacity(this.items[old_index], -fade_adjustment) <= 0) {
		clearInterval(this.fade_out_timer)
		setTimeout(this.id + '.start_fade_in(' + old_index + ')', fade_pause)
	}
}

Slideshow.prototype.start_fade_in = function(old_index) {
	hide(this.items[old_index])
	var new_index = this.active_index
	show(this.items[new_index], 0)
	this.fade_in_timer = setInterval(this.id + '.fade_in(' + new_index + ')', fade_interval)
	this.fade_out_timer = null
}

Slideshow.prototype.fade_in = function(new_index) {
	if (adjust_opacity(this.items[new_index], fade_adjustment) >= 1) {
		clearInterval(this.fade_in_timer)
		this.fade_in_timer = null
	}
}

Slideshow.prototype.switch_to = function(new_index) {
	if (this.active_index != new_index && new_index < this.items.length && new_index >= 0 ) {
		this.start_fade_out(new_index)
		if (this.scroll_timer) this.scroll_function() // restart the scrolling if it's on
		this.call_on_scroll(new_index)
	}
}

Slideshow.prototype.switch_to_next = function() {
	var new_index = (this.active_index < this.items.length - 1 ? this.active_index + 1 : 0)
	this.start_fade_out(new_index)
	if (this.scroll_timer) this.scroll_forward() // restart the scrolling if it's on
	this.call_on_scroll(new_index)
	return new_index
}

Slideshow.prototype.switch_to_previous = function() {
	var new_index = (this.active_index > 0 ? this.active_index - 1 : this.items.length - 1)
	this.start_fade_out(new_index)
	if (this.scroll_timer) this.scroll_backward() // restart the scrolling if it's on
	this.call_on_scroll(new_index)
	return new_index
}

Slideshow.prototype.scroll_forward = function() {
	clearInterval(this.scroll_timer)
	this.scroll_timer = setInterval(this.id + '.switch_to_next()', this.scroll_interval)
	this.scroll_function = this.scroll_forward
}

Slideshow.prototype.scroll_backward = function() {
	clearInterval(this.scroll_timer)
	this.scroll_timer = setInterval(this.id + '.switch_to_previous()', this.scroll_interval)
	this.scroll_function = this.scroll_backward
}

Slideshow.prototype.play = function() {
	this.scroll_function()
}

Slideshow.prototype.stop = function() {
	clearInterval(this.scroll_timer)
	this.scroll_timer = null
}

Slideshow.prototype.toggle_scroll = function() {
	if (this.scroll_timer == null) {
		this.play()
		return true
	} else {
		this.stop()
		return false
	}
}

Slideshow.prototype.set_scroll_interval = function(interval) {
	this.scroll_interval = interval
	if (this.scroll_timer != null) this.scroll_function()
}

Slideshow.prototype.create_numbered_controls = function(container, new_id) {
	if (this.items == null) return null 
	if (typeof(new_id) == 'undefined') new_id = 'control'

	var controls = []
	for (var i = 0; i < this.items.length; i++) {
		var a = document.createElement('a')
		a.name = a.id = 'control' + i
		a.href = 'javascript: ' + this.id + '.switch_to(' + i + ')'
		var text = document.createTextNode(i + 1)
		a.appendChild(text)
		container.appendChild(a)
		controls.push(a)
	}
	return controls
}

Slideshow.prototype.call_on_scroll = function(index) {
	if (this.on_scroll != null) this.on_scroll(index)
}