/* application.js contains general helper classes and funtions for settings, */
/* progressbars and HTTPRequest wrapping */

/* TODO:s
	Add function for browser-independent attach event : application_attachEvent(element, eventName); Bubble param?
*/

// Base prototype for all history actions.
function action(target)
{
	this.target = target;
	
	this.undo = function undo() 
	{
		if (this.target)
		{
			this.target.undo(this);
		}
		else
		{
			throw "The action has no target assigned"
		}
	}
	
	this.redo = function redo() 
	{
		if (this.target)
		{
			this.target.redo(this);
		}
		else
		{
			throw "The action has no target assigned"
		}
	}
}

// A undo/redo-history container

function history(application, parent)
{
	this.application = application;
	this.parent = parent;
	this.ishistory = true;
	this.history = new Array();
	this.history.length = 0;
	this.historyposition = -1; 
	
	this.do_undo = function do_undo(remove)
	{
		if (this.history[this.historyposition].ishistory) 
		{
			this.history[this.historyposition]._undoAll(remove);
		}
		else
		{
			this.history[this.historyposition].undo(remove);			
		}
		
		if (remove) {this.history.splice(this.historyposition,1);}
		
		this.historyposition--;	
	}
	
	this.do_redo = function do_redo()
	{
		this.historyposition++;
		if (this.history[this.historyposition].ishistory) 
		{
			this.history[this.historyposition]._redoAll();
		}
		else
		{
			this.history[this.historyposition].redo();			
		}
	
	}
	
	this.undo = function undo(remove)
	{
		if (this.historyposition < 0)
		{
			alert("Nothing left to undo.");
		}
		else
		{
			this.application.changing_history = true;
			this.do_undo(remove);
			this.application.changing_history = false;
		}
		
	}
	
	this.redo = function redo()
	{
		if (this.history.length == 0 || this.historyposition > this.history.length -2)
		{
			alert("Nothing to redo.");
		}
		else
		{
			this.application.changing_history = true;
			this.do_redo();
			this.application.changing_history = false;
		}
	}
	
	this.register_action = function register_action(action)
	{
		if (!this.application.changing_history)
		{
			this.historyposition ++;
			this.history.length = this.historyposition + 1;
			this.history[this.historyposition] = action;
		}
	}
	
	this._end_history = function _end_history()
	{
		// Remove any "unredone" actions.
		this.history.length = this.historyposition + 1;
		return this.parent;
	}
	
	this._undoAll = function _undoAll(remove)
	{
		while (this.historyposition > -1)
		{
			this.do_undo(remove);
		}
	}
	
	this._redoAll = function _redoAll()
	{
		if (this.history.length > 0)
		{
			while (this.historyposition < this.history.length -1 )
			{
				this.do_redo();
			}
		}
	}
}



/* The application object is supposed to hold application-wide settings*/
function application(title)
{
	this.title = title;
/*	TODO: Implement this section.
	this.makeprogress = function makeprogress(count, total, caption) {application_makeprogress(this,count,total,caption);}
	this.progressimage = null;
	this.progresscaption = null;
*/
	this.fulltextview = function fulltextview(caption) {application_fulltextview(this,caption);}
	this.errorcolor = "#FFAAAA";
	this.IEOKcolor = "#FFFFFF"; // Necessary since i haven't found a way to change back to the old style in IE. 
	
	// Undo/redo

	this.history = new history(this, null); // Init history
	this.current_history = this.history; 

	this.changing_history = false;

	this.undo = function undo(remove)
	{
		this.history.undo(remove);
	}
	
	this.redo = function redo()
	{
		this.history.redo();
	}
	
	this.register_action = function register_action(action)
	{
		this.current_history.register_action(action);
	}
	
	this.begin_history = function begin_history()
	{
		var new_history = new history(this,this.current_history);
		this.register_action(new_history);
		this.current_history = new_history;
		return new_history;
		
	}
	this.end_history = function end_history()
	{
		this.current_history = this.current_history._end_history();
	}
			
	this.editors = new Array();
	
	this.add_editor = function add_editor(element, datatype, onEdit, onError)
	{
		new editor_object(element, datatype, onEdit, onError, this);
		return element;
	}	
}

function application_makeprogress(appobj,count,total,caption)
{

}
function application_fulltextview(appobj,caption)
{
  document.title = appobj.title + " - " + caption ;
}

//Helper functions

function MakeParagraph(a_value, a_class)
{
	return '<p class="' + a_class + '">' + a_value + '</p>';
}
function MakeSpanned(a_value, a_class)
{
	return '<span class="' + a_class + '">' + a_value + '</span>';
}

// Get an XMLHttpRequest object in a portable way. -- Snitched from www.boutell.com
function newRequest()
{
	var req;
	req = false;
	// For Safari, Firefox, and other non-MS browsers
	if (window.XMLHttpRequest) {
		try {
			req = new XMLHttpRequest();
		} catch (e) {
			req = false;
		}
	} else if (window.ActiveXObject) 
	{
		// For Internet Explorer on Windows
		try {
			req = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				req = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {
				req = false;
			}
		}
	}
	return req;
}

function HTTPErrorcodeToString(code)
{
	switch (Number(code))
	{
	
		case 401: return "401: Unauthorized";
		case 403: return "403: Forbidden";
		case 404: return "404: Not Found";
		case 500: return "500: Internal server error";
		default: return code + ": Unrecognised code"
	}
}

function MakeRequest(URL, method, query)
{	
	var req = newRequest();
	if (method)
	{
		req.open(method, URL, false);
	  
		if (method == "POST")
		{
			req.setRequestHeader('Content-Type',
			'application/x-www-form-urlencoded');
		}
	}
	else
	{
		req.open("GET", URL, false);
	}

	if (query)
	{
	  req.send(query);
	}
	else
	{
		req.send("");
	}
	if (req.status == 200)
	{
		return req.responseText;
	}
	else
	{
		throw("Failed to get data through XMLHTTPrequest.\nError : " + HTTPErrorcodeToString(req.status) + ".");
	}

}

function add_tr_to_table(table, element, old)
{
	if (old)
	{
		//var new_tbody = document.createElement("tbody");
		//new_tbody.appendChild(element);
		old.parentNode.insertBefore(element, old);
	}
	else
	{
		if (table.tBodies.length == 1)
		{
		
			table.tBodies[0].appendChild(element);
		}
		else
		{
			var new_tbody = document.createElement("tbody");
			new_tbody.appendChild(element);
			table.appendChild(new_tbody);
		}
	}

}



function invert_element(obj)
{

  if (obj.currentStyle)
  {
		var tmpclr = obj.currentStyle.backgroundColor;
		obj.style.backgroundColor = obj.currentStyle.color;
	}
	else
	{
		var tmpclr = document.defaultView.getComputedStyle(obj, null).getPropertyValue("background-color");
		obj.style.backgroundColor = document.defaultView.getComputedStyle(obj, null).getPropertyValue("color");
	}
	obj.style.color = tmpclr;
}

function focusandblink(obj, iterations, color)
{
	obj.focus();

	if (!iterations)
	{
	  iterations = 3;
	}
	if (!color)
	{
		color = "#FFAAAA";
	}
	var oldcolor = obj.style.backgroundColor;
	for (var idx= 1 ;idx < iterations*2; idx = idx+2)
	{
		setTimeout('var target=document.getElementById("'+obj.id+'");target.style.backgroundColor = "'+color+'";',idx *70);
		setTimeout('var target=document.getElementById("'+obj.id+'");target.style.backgroundColor = "'+oldcolor+'";',(idx+1)*70);

	}	
	
}

