function ProgramModule(prefix) {
	this.num_panels = 0;
	this.active_panel = 0;
	this.prefix = prefix?prefix:'pm';

	this.currentPanel = 0;
	this.panels = [];
	this.indicators = [];
	this.timer = null;
	this.animTimer = null;
	this.intTimer = null;
	this.topPanel;
}

ProgramModule.PLAY_INTERVAL = 10000;
ProgramModule.INTERACTION_DELAY = 10000; //wait this much before starting interval again
ProgramModule.FADE_SPEED = 0.1;
ProgramModule.BOTTOM_ZINDEX = "50";
ProgramModule.MIDDLE_ZINDEX = "53";
ProgramModule.TOP_ZINDEX = "55";
ProgramModule.INDICATOR_CLASS_OFF = "indicator";
ProgramModule.INDICATOR_CLASS_ON = "indicator active";
ProgramModule.TRANSITION_NONE = "none";
ProgramModule.TRANSITION_FADE = "fade";
ProgramModule.TRANSITION = ProgramModule.TRANSITION_FADE;


ProgramModule.prototype.loadPanel = function() {
	this.num_panels++;
}

ProgramModule.prototype.startPlayback = function () {
	try	{
		//TODO: what to do if < 2 panels?

		//load panels into array for easy access
		for (var i=0; i<this.num_panels; i++) {
			this.panels[i] = document.getElementById(this.prefix + "_panel_" + i);
			this.indicators[i] = document.getElementById(this.prefix + "_ind_" + i);
			//this.panels[i].style.left = i * 5 + 'px';
			//this.panels[i].style.top = (6 - i) * 5 + 'px';
		}

		this.updateIndicators();
		this.nextPanel_finished();
	} catch(e) {
		alert('an error occured while trying to start playback');
	}
}

ProgramModule.prototype.autoplay = function () {
	this.reset();
	var self = this;
	if (this.num_panels > 1) {
		this.timer = setTimeout(function(){self.nextPanel()}, ProgramModule.PLAY_INTERVAL);
	}
}

ProgramModule.prototype.updateIndicators = function() {
	for (var i=0; i<this.indicators.length; i++) {
		this.indicators[i].className = ProgramModule.INDICATOR_CLASS_OFF;
	}
	this.indicators[this.currentPanel].className = ProgramModule.INDICATOR_CLASS_ON;
};

ProgramModule.prototype.nextPanel = function(frame, forceTransition) {
	this.topPanel = this.currentPanel;
	if (typeof frame != 'undefined')
		this.currentPanel = frame;
	else
		this.currentPanel = this.getNextIndex();
	this.updateIndicators();
	this.prepareBuffer(this.currentPanel);

	//depending on mode, show next panel
	var trans = forceTransition || ProgramModule.TRANSITION;
	if (trans == ProgramModule.TRANSITION_NONE)
		this.quickSwitch();
	else if (trans == ProgramModule.TRANSITION_FADE)
		this.fadeOut(1);
};

/**
 * gets called when animation is done
 */
ProgramModule.prototype.nextPanel_finished = function() {
	// now move current to top and the rest to bottom, and reset those
	for (var i=0; i<this.panels.length; i++) {
		var panel = this.panels[i];
		if (i!=this.currentPanel) {
			panel.style.zIndex = ProgramModule.BOTTOM_ZINDEX;
		} else {
			panel.style.zIndex = ProgramModule.TOP_ZINDEX;
		}
		this.setOpacity(panel, 100);
	}
	this.reset();
	this.autoplay();
};

/**
 * reset all timers and put everything in a usable state
 */
ProgramModule.prototype.reset = function() {
	clearTimeout(this.animTimer);
	clearInterval(this.timer);
	clearTimeout(this.intTimer);
};

ProgramModule.prototype.getNextIndex = function() {
	var next = this.currentPanel + 1;
	if (next >= this.panels.length)
		next = 0;
	return next;
};

ProgramModule.prototype.jumpToFrame = function(frame) {
	this.nextPanel_finished();
	if (frame != this.currentPanel) { //don't do anything if we are already viewing this
		this.nextPanel(frame, ProgramModule.TRANSITION_NONE);
	}

	var self = this;
	this.intTimer = setTimeout(function() {
		//self.autoplay();
	}, ProgramModule.INTERACTION_DELAY)
}

/**
 * move "buffer" layer to middle so when top layer goes away, this one shows
 */
ProgramModule.prototype.prepareBuffer = function(index) {
	if (this.panels[index])
		this.panels[index].style.zIndex = ProgramModule.MIDDLE_ZINDEX;
};

ProgramModule.prototype.setOpacity = function(target, opacity) {
	if (opacity < 0) opacity = 0;
	else if (opacity > 1) opacity = 1;
	target.style.opacity = opacity;
	var ie_opacity = 100 * opacity;
	target.style.filter = "alpha(opacity=" + ie_opacity + ");";
}

ProgramModule.prototype.quickSwitch = function(opacity) {
	clearTimeout(this.animTimer);
	this.nextPanel_finished();
};

ProgramModule.prototype.fadeOut = function(opacity) {
	clearTimeout(this.animTimer);
	opacity = opacity - ProgramModule.FADE_SPEED;
	this.setOpacity(this.panels[this.topPanel], opacity);
	var self = this;
	if (opacity > 0) {
		this.animTimer = setTimeout(function(){self.fadeOut(opacity);}, 20);
	} else {
		this.nextPanel_finished();
	}
}
