/**************************************************************
* Copyright (c) ProcessDATA Ltd.
* All rights reserved.
*
* @title Scroller Library
* @note API NOT supported and will change in future releases
* @version Version 1.0.0 (beta)
*
* @changes
* - version 1.0.0 (beta) by Sergey Busel
***************************************************************/

function ScrollerSettings()
{
	var speed = 1;
	var pixels = 1;
	var delim = "***";
	
	this.setSpeed = function(aSpeed){
		if(isNaN(aSpeed) || aSpeed < 0)
			throw new Error("Speed should be a positive integer.");
		speed = aSpeed;
	}
	this.getSpeed = function getSpeed(){
		return speed;
	}
	this.setMovePixels = function(aPixels){
		if(isNaN(aPixels) || aPixels < 0)
			throw new Error("Number of pixels should be a positive integer.");
		pixels = aPixels;
	}
	this.getMovePixels = function(){
		return pixels;
	}
	this.setDelimeter = function(aDelim){
		delim = (aDelim != null) ? aDelim : "";
	}
	this.getDelimeter = function(){
		return delim;
	}
}

function ScrollMessage()
{
	var myId = 0;
	var myOrder = 0;
	var myEffDt = "";
	var myExpDt = "";
	var myText = "";
	var myUrl = "";
	
	this.setId = function(anId){
		if(anId == null || isNaN(anId) || anId < 0)
			throw new Error("Invalid ID.");
		myId = anId;
	}
	this.getId = function(){
		return myId;
	}
	this.setOrder = function(anOrder){
		if(anOrder == null || isNaN(anOrder) || anOrder < 0)
			throw new Error("Invalid Order.");
		myOrder = anOrder;
	}
	this.getOrder = function(){
		return myOrder;
	}
	this.setEffectiveDate = function(aDate){
		myEffDt = (aDate != null) ? aDate : "";
	}
	this.getEffectiveDate = function(){
		return myEffDt;
	}
	this.setExpirationDate = function(aDate){
		myExpDt = (aDate != null) ? aDate : "";
	}
	this.getExpirationDate = function(){
		return myExpDt;
	}
	this.setText = function(aText){
		myText = (aText != null) ? aText : "";
	}
	this.getText = function(){
		return myText;
	}
	this.setUrl = function(aUrl){
		myUrl = (aUrl != null) ? aUrl : "";
	}
	this.getUrl = function(){
		return myUrl;
	}
	this.toXML = function(){
		var xml = "<message id=\"" + myId + "\" effdt=\"" + myEffDt + "\" expdt=\"" + myExpDt + "\" order=\"" + myOrder + "\">";
		xml += "<text>" + escape(myText) + "</text>";
		xml += "<url>" + escape(myUrl) + "</url>";
		xml += "</message>";
		return xml;
	}
}

ScrollMessage.sortByOrder = function(a, b)
{
	return a.getOrder() - b.getOrder();
}
ScrollMessage.sortByEffectiveDate = function(a, b)
{
	var ad = Date.parse(a.getEffectiveDate());
	var bd = Date.parse(b.getEffectiveDate());
	if(isNaN(ad) && isNaN(bd))
		return 0;
	else if(isNaN(ad))
		return 1;
	else if(isNaN(bd))
		return -1;
	else
		return ad - bd;
}
ScrollMessage.sortByExpirationDate = function(a, b)
{
	var ad = Date.parse(a.getExpirationDate());
	var bd = Date.parse(b.getExpirationDate());
	if(isNaN(ad) && isNaN(bd))
		return 0;
	else if(isNaN(ad))
		return 1;
	else if(isNaN(bd))
		return -1;
	else
		return ad - bd;
}
ScrollMessage.sortByText = function(a, b)
{
	var at = a.getText().toUpperCase();
	var bt = b.getText().toUpperCase();
	if(at == bt)
		return 0;
	else if(at > bt)
		return 1;
	else
		return -1;
}

function Scroller(aHolder)
{
	if(arguments.length == 0 || aHolder == null)
		throw new Error("Invalid argument passed to the scroller constructor.");
	
	var holder = aHolder;
	var scrolltext = "";
	var running = false;
	var varName = "";
	var settings = new ScrollerSettings();
	var spanEl = document.createElement("span");
	var spanWidth = 0;
	var textLen = 0;
	var deltaPx = 0;
	
	this.setText = function(aText){
		scrolltext = (aText != null) ? aText : "";
	}
	this.setSettings = function(aSettings){
		if(aSettings == null || aSettings.constructor != ScrollerSettings)
			throw new Error("Invalid settings object.");
		settings = aSettings;
	}
	this.start = function(aVarName){
		if(aVarName == null || aVarName == "")
			throw new Error("Invalid argument passed to scroller start function.");
			
		if(running){
			this.stop();
		}
		varName = aVarName;
		applySettings();
		createScrollElement();
		running = true;
		run();
	}
	this.pause = function(){
		deltaPx = 0;
	}
	this.resume = function(){
		deltaPx = settings.getMovePixels();
	}
	this.stop = function(){
		if(running){
			running = false;
			spanEl.innerHTML = "";
			holder.removeChild(spanEl);
			spanWidth = 0;
			textLen = 0;
		}
	}
	this.update = function(){
		run();
	}
	this.printStats = function(){
		var msg = "";
		msg = "left: " + spanEl.style.left + "; width: " + spanEl.offsetWidth;
		alert(msg);
	}
	
	var applySettings = function(){
		holder.style.overflow = "hidden";
		deltaPx = settings.getMovePixels();
		holder.onmouseover = function(){
			deltaPx = 0;
		}
		holder.onmouseout = function(){
			deltaPx = settings.getMovePixels();
		}
	}
	var createScrollElement = function(){
		spanEl.style.whiteSpace = "nowrap";
		spanEl.style.position = "relative";
		spanEl.style.left = holder.offsetWidth;
		spanEl.innerHTML = scrolltext;
		holder.appendChild(spanEl);
		textLen = scrolltext.length;
		spanWidth = spanEl.offsetWidth;
	}
	var run = function(){
		var j = parseInt(spanEl.style.left);
		j = j - deltaPx;
		spanEl.style.left = j + "px";
		if((j + spanEl.offsetWidth) < holder.offsetWidth){
			spanEl.innerHTML += scrolltext;
		}
		if(j < (0 - spanWidth)){
			spanEl.style.left = j + spanWidth + "px";
			spanEl.innerHTML = spanEl.innerHTML.substr(textLen);
		}
		if(running){
			setTimeout(varName + ".update()", settings.getSpeed());
		}
	}
}

Scroller.filterByDates = function(msgs)
{
	if(arguments.length == 0 || msgs == null)
		return new Array(0);
	else if(msgs.constructor != Array)
		return new Array(0);
	
	var result = [];
	var ef = false;
	var ex = false;
	var now = (new Date()).getTime();
	var temp;
	for(var i=0; i<msgs.length; i++) {
		ef = ex = false;
		var m = msgs[i];
		if(m.constructor != ScrollMessage)
		{
			continue;
		}
		if(utilIsDate(m.getEffectiveDate()))
		{
			temp = Date.parse(m.getEffectiveDate());
			if(temp < now)
			{
				ef = true;
			}
		}
		else
		{
			ef = true;
		}
		if(utilIsDate(m.getExpirationDate()))
		{
			temp = Date.parse(m.getExpirationDate());
			if(temp > now)
			{
				ex = true;
			}
		}
		else
		{
			ex = true;
		}
		if(ef && ex)
			result.push(m);
	}
	return result;
}

Scroller.createMessageString = function(msgs, delim)
{
	if(arguments.length < 1 || msgs == null)
		return "";
	else if(msgs.length == 0)
		return "";
	else if(arguments.length == 1) {
		var set = new ScrollerSettings();
		delim = set.getDelimeter();
		set = null;
	}
	
	msgs = Scroller.filterByDates(msgs);
	msgs.sort(ScrollMessage.sortByOrder);
	var out = "";
	for(var i=0; i<msgs.length; i++) {
		out += msgs[i].getText() + " &nbsp; " + delim + " &nbsp; ";
	}
	return out;
}

function utilIsDate(aDate) {
	try {
		if(aDate == null || aDate == "")
			return false;
		if(isNaN(Date.parse(aDate)))
			return false;
		return true;
	}
	catch(e) {
		return false;
	}
}
	