/* Platform Updater */

var PlatformUpdater = function(updatePeriodSeconds, timeoutPeriod, requestUrl, fImgPath) {

	var period = updatePeriodSeconds * 1000;
	var lastModified = 0;

	var block = false;
	var request = null;
	var requestCount = 0;

	var blockDraw = false;

	this.signalsList = new SignalsList();
	this.drawer = null;
	this.extensions = [];
	this.interceptor = null;

	this.setDrawer = function(drawer) {
		this.drawer = drawer;
	}

	this.addExtension = function(extension) {
		this.extensions.push(extension);
	}

	this.addInterceptor = function(interceptor) {
		this.interceptor = interceptor;
	};

	this.init = function() {
		var thisClosure = this;
		setInterval(function(){thisClosure.load();}, period);
		if (this.drawer == null)
			this.drawer = new PlatformDrawer();
		this.drawer.init(fImgPath);
		for (var i  in this.extensions)
			this.extensions[i].init(this);
	}

	this.load = function() {
		if (block)
			return;
		if (requestCount != 0) {
			if (++requestCount > timeoutPeriod)
				this.abortRequest();
			else
				return;
		}
		request = ((typeof XMLHttpRequest != 'undefined') ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
		requestCount = 1;
		var url = requestUrl + "?lastmodified=" + lastModified + "&requestId=" + (new Date().getTime());
		request.open("GET", url, true);
		var reqClosure = request;
		var thisClosure = this;
		request.onreadystatechange = function() {
			if (reqClosure.readyState == 4) {
				thisClosure.processResponse(reqClosure.responseText);
				thisClosure.abortRequest();
			}
		}
		request.send(null);
	}

	//synchronized
	this.processResponse = function(response) {
		if (block)
			return;
		block = true;
		if (response && (response != "") && (response != "null")) {
			try {
				var responseObj = eval("[" + response + "]")[0];
				if (lastModified != 0 && this.interceptor != null) {
					if (this.interceptor.intercept())
						return;
				}
				lastModified = responseObj.lastmodified;
				this.processSignals(responseObj.signals);
				this.draw();
				for (var j in this.extensions)
					this.extensions[j].notify();
			} catch(e) {}
		}
		block = false;
	}

	this.processSignals = function(signals) {
		var currentSignals = this.signalsList.getAll();
		var result = [];
		for (var i in signals) {
			var signal = new Signal(signals[i]);
			var isNew = true;
			for (var j in currentSignals) {
				if (signal.getSignature() == currentSignals[j].getSignature()) {
					isNew = false;
					result.push(currentSignals[j]);
					break;
				}
			}
			if (isNew)
				result.push(signal);
		}
		this.signalsList.setSignals(result);
	}

	//synchronized
	this.draw = function() {
		if (blockDraw) {
			var thisClosure = this;
			setTimeout(function(){thisClosure.draw();}, 50);
			return;
		}
		blockDraw = true;
		this.drawer.draw(this.signalsList.getAll());
		blockDraw = false;
	}

	this.abortRequest = function() {
		this.requestCount = 0;
		if (this.request != null)
			this.request.abort();
		this.request = null;
	}
}

/* SignalsList */

var SignalsList = function() {

	this.signals = [];

	this.setSignals = function(signals) {
		this.signals = signals;
	}

	this.getAll = function() {
		var result = [];
		return result.concat(this.signals);
	}
}

/* Signal */

var Signal = function(hash) {

	this.getSymbol = function() {
		return hash["symbol"];
	}

	this.getProduct = function() {
		return hash["product"];
	}

	this.getThumbs = function() {
		return hash["thumbs"];
	}

	this.getTime = function() {
		return hash["time"];
	}

	this.getPrice = function() {
		return hash["price"];
	}

	this.getSignature = function() {
		return hash["signature"];
	}

	this.isThumbsUp = function() {
		return (this.getThumbs() == "Up");
	}

	this.isThumbsDown = function() {
		return (this.getThumbs() == "Down");
	}

	this.isHU = function() {
		return (this.getProduct() == "HU");
	}

	this.isUH = function() {
		return (this.getProduct() == "UH");
	}

	this.isBM = function() {
		return (this.getProduct() == "BM");
	}
}

/* PlatformDrawer */

var PlatformDrawer = function() {

	var E_CONTENTTABLE = "contenttable";
	var E_LOADING = "contentloading";
	var E_CONTENTEMPTY = "contentempty";
	var P_ID = "datatow_";
	var C_DATAROW = "data";

	var table = null;
	var empty = null;
	var imgPath = null;

	this.init = function(fImgPath) {
		table = getElement(E_CONTENTTABLE);
		empty = getElement(E_CONTENTTABLE);
		imgPath = fImgPath;
	}

	this.draw = function(signals) {
		signals.reverse();
		hideElement(E_LOADING);
		if (signals.length == 0) {
			showElement(E_CONTENTEMPTY);
		} else {
			hideElement(E_CONTENTEMPTY);
			this.clearTable();
			this.drawSignals(signals);
		}
	}

	this.drawSignals = function(signals) {
		for (var i in signals) {
			this.drawSignal(signals[i]);
		}
	}

	this.drawSignal = function(signal) {
		var row = table.insertRow(1);
		row.className = C_DATAROW;
		row.id = this.getRowId(signal);
		this._drawnRow(row, signal);
		var index = 0;
		this.addCell(row, index++, this._symbol(signal));
		this.addSpacer(row, index++);
		this.addCell(row, index++, this._thumbs(signal));
		this.addSpacer(row, index++);
		this.addCell(row, index++, this._time(signal));
		this.addSpacer(row, index++);
		this.addCell(row, index++, this._price(signal));
		index = this._drawnPrice(row, index, signal);
		this._additionalRow(signal);
	}

	this._drawnRow = function(row, signal) {}

	this._drawnPrice = function(row, index, signal) {
		return index;
	}

	this._symbol = function(signal) {
		return signal.getSymbol();
	}

	this._thumbs = function(signal) {
		var thumbs = signal.isThumbsUp() ? "up" : "down";
		var img = '<img src="' + imgPath +'thumbs_' + thumbs + '.gif" width="20" height="20" alt="' + signal.getThumbs() + '"/>'
		var result = img;
		if (!signal.isHU())
			result += img;
		if (signal.isBM())
			result += img;
		return result;
	}

	this._time = function(signal) {
		return signal.getTime();
	}

	this._price = function(signal) {
		if (!signal.getPrice())
			return "&nbsp;";
		return ("$ " + signal.getPrice());
	}

	this._additionalRow = function(signal) {};

	this.getImgPath = function() {
		return imgPath;
	}

	this.getRowId = function(signal) {
		return this.getRowIdBySign(signal.getSignature());
	}

	this.getRowIdBySign = function(signature) {
		return P_ID + signature;
	}

	this.getDatarowClass = function() {
		return C_DATAROW;
	}

	this.addAdditionalRow = function() {
		return table.insertRow(2);
	}

	this.addSpacer = function(row, index) {
		this.addCell(row, index, "|", "spacer");
	}

	this.addCell = function(row, index, content, className) {
		var cell = row.insertCell(index);
		if (className)
			cell.className = className;
		cell.innerHTML = content;
		return cell;
	}

	this.clearTable = function() {
		while (table.rows.length != 1)
			table.deleteRow(1);
	};
}

/* PlatformUpdaterExtenstion interface */

var PlatformUpdaterExtension = function() {

	this.pUpdater = null;

	this.init = function(pUpdater) {
		this.pUpdater = pUpdater;
	};

	this.notify = function() {}
}

/* PlatformUpdaterInterceptor interface */

var PlatformUpdaterInterceptor = function() {

	this.intercept = function() {
		return false;
	}
}
