// Server Sync Class
function LSSync(inClient)
{
this.request_queue = new Queue();
var client;								// reference to the client to which this object instance belongs.
var that = this;
var is_ready;
var request_counter;
var previous_request_id;				// ID of the last request sent. This is used to check if the user has got disconnected.

var timerID;

var that = this;

	this.init=function(client)
	{
		this.request_queue = new Queue();
		this.client = client;
		this.is_ready = true;
		this.request_counter = 0;
		this.SendRequestTimer();
	};
	
	this.SendRequestTimer=function()
	{
		if (that.request_queue.getSize())
		{
			top_request = that.request_queue.getOldestElement();
		
/*
			if (top_request.id == this.previous_request_id)
			{
				ShowDisconnectedMsg();				// this is defined in templates/lsoutliner.inc
				clearTimeout(this.timerID);
			}
			else
			{
*/
				that.SendRequest();
				this.previous_request_id = top_request.id;
//			}
		}
			
		this.timerID = setTimeout(that.SendRequestTimer, 1000);
	}
	
	this.CreateRequest=function(action, row)
	{
		var req = new LSSyncRequest(this.request_counter, action, row);
		this.request_counter++;
		
		this.request_queue.enqueue(req);
	};
	
	this.SendRequest=function()
	{
		var required_in_play = false;										// some calls are required in Play also.
		
		if (typeof gFromPlayPage == 'undefined')
			gFromPlayPage = false;
		
		if (this.is_ready && !this.request_queue.isEmpty())
		{
			var req = this.request_queue.getOldestElement();				// get the next request to be sent to the server
			
			var params = "{}";
			var q_method = "POST";
			
			var outline_id = this.client.outliner.GetOutlineId();
			if (typeof req.GetRow() !== 'undefined')
			{
				var row = req.GetRow();
				var row_sid = row.getAttribute('_sid');
			}
			
			switch (req.GetAction())
			{
			case 'addRow':		prev_row = this.client.outliner.GetPreviousSibling(row);
								if (prev_row == false)
									prev_str = "";
								else prev_str = ", previous_row_id: '"+prev_row.getAttribute("_sid")+"'";
								
								var parent_row = row.getParent();
								if (parent_row.getId() == 'body')
									parent_row_id = -1;
								else parent_row_id = parent_row.getAttribute("_sid");
								
								endpoint = "/api/outlines/"+outline_id+"/rows/addRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "', parent_id: '" + parent_row_id + "' " + prev_str + ", text: '" + addslashes(row.getAttribute('text')) + "', status: '" + row.getAttribute('_status') + "', color: '" + row.getAttribute('_color') + "', notes: '" + row.getAttribute('_notes') + "', amount: '" + row.getAttribute('_amount') + "'}";
								break;
			
			case 'updateRow':	endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/updateRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "', text: '" + addslashes(row.getAttribute('text')) + "', status: '" + row.getAttribute('_status') + "', color: '" + row.getAttribute('_color') + "', notes: '" + row.getAttribute('_notes') + "', amount: '" + row.getAttribute('_amount') + "'}";
								break;
			
			case 'deleteRow':	endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/deleteRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "'}";
								break;
			
			case 'moveRow':		prev_row = this.client.outliner.GetPreviousSibling(row);
								if (prev_row == false)
									prev_str = "";
								else prev_str = ", previous_row_id: '"+prev_row.getAttribute("_sid")+"'";
								
								var parent_row = row.getParent();
								if (parent_row.getId() == 'body')
									parent_row_id = -1;
								else parent_row_id = parent_row.getAttribute("_sid");
								
								endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/moveRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "', parent_id: '" + parent_row_id + "' " + prev_str + "}";
								break;
			
			case 'expandRow':	endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/expandRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "'}";
								break;
			
			case 'collapseRow':	endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/collapseRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "'}";
								break;
								
		case 'expandChildren':	endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/expandAll.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "'}";
								break;
			
			case 'expandAll':	endpoint = "/api/outlines/"+outline_id+"/rows/expandAll.json";
								params = "{last_modified_on: '" + this.client.GetLastModifiedOn() + "'}";
								break;
			
		case 'collapseChildren':endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/collapseAll.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "'}";
								break;
			
			case 'collapseAll':	endpoint = "/api/outlines/"+outline_id+"/rows/collapseAll.json";
								params = "{last_modified_on: '" + this.client.GetLastModifiedOn() + "'}";
								break;
	
			case 'setDueDate':	endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/updateRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "', due_date: '" + row.getAttribute('_duedate') + "'}";
								break;
			
		case 'setAttachment':	endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/updateRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "', attachment: '" + row.getAttribute('_file_id') + "'}";
								break;
			
			case 'getFiles':	endpoint = "/api/files/getByUserAndOutline.json";
								params = "{uid: '" + that.client.GetUserId() + "', outline_id: '"+outline_id+"'}";
								q_method = "GET";
								required_in_play = true;
								break;
								
			case 'getAllRows':	endpoint = "/api/outlines/"+outline_id+"/getAllRows.json";
								params = "{}";
								q_method = "GET";
								required_in_play = true;
								break;
								
			case 'touchOutline':endpoint = "/api/outlines/"+outline_id+"/touchOutline.json";
								params = "{}";
								q_method = "POST";
								break;
	
			case 'bleach':		endpoint = "/api/outlines/"+outline_id+"/rows/bleach.json";
								params = "{last_modified_on: '" + this.client.GetLastModifiedOn() + "'}";
								break;
								
			case 'getInvites':	endpoint = "/api/outlines/"+outline_id+"/getInvites.json";
								params = "{}";
								q_method = "GET";
								required_in_play = true;
								break;
								
			case 'assignRow':	endpoint = "/api/outlines/"+outline_id+"/rows/"+row_sid+"/assignRow.json";
								params = "{cid: '" + row.getId() + "', last_modified_on: '" + this.client.GetLastModifiedOn() + "', assigned_to: '" + row.getAttribute('_assigned_to') + "'}";
								break;
	
		case 'getLockStatus':	endpoint = "/api/outlines/"+outline_id+"/getLockStatus.json";
								params = "{session_id: '" + gSessionId + "'}";
								q_method = "GET";
								break;
			
			default:			alert("invalid request with action: "+req.GetAction());
								break;
			}

			if (!gFromPlayPage || required_in_play)
			{
				that.is_ready = false;
				
				new Ajax.Request(endpoint,
				{
					method: q_method,
					parameters: { 'params': JSON.stringify(params.evalJSON()) },
					onFailure: function() { alert('Something went wrong...'); },
					onSuccess: function(transport) {
						if (transport.getStatus() != 0)
							that.SendRequestCallBack(transport);
						else HandleDisconnection();
					}
				});
			}
			else that.request_queue.dequeue();				// remove the request from the queue as we are not going to send it
		}
	};
	
	// handles the response from the server
	this.SendRequestCallBack=function(t)
	{
	var response = t.responseText.evalJSON();

		if (response.status == 'error')
		{
			alert(response.error);
		}
		else
		{
			that.request_queue.dequeue();
			
			if (response.last_modified)
				that.client.SetLastModifiedOn(response.last_modified);
			
			switch (response.method)
			{
			case 'addRow':		row_cid = response.cid;
								row_sid = response.sid;
								row = that.client.outliner.GetRowById(row_cid);
								row.setAttribute('_sid', row_sid);
								break;
								
	case 'getByUserAndOutline':	that.client.StoreFiles(response.files);
								break;
								
			case 'getInvites':	that.client.GetInvitesCallBack(response.invites);
								break;
								
/*			case 'getAllRows1':	that.client.SetLastModifiedOn(response.last_modified);			// we set the last modified timestamp so that we can send it with the next API call
								that.client.outliner.LoadOPML(response);
								break;
*/						
			case 'getAllRows':	var xmlobject;
								if (window.DOMParser)
									xmlobject = (new DOMParser()).parseFromString(response.opml, "text/xml");
								else // Internet Explorer
								{
									xmlobject=new ActiveXObject("Microsoft.XMLDOM");
									xmlobject.async="false";
									xmlobject.loadXML(response.opml); 
								}
								
								that.client.SetLastModifiedOn(response.last_modified);			// we set the last modified timestamp so that we can send it with the next API call
								that.client.outliner.LoadOPML(xmlobject.documentElement);
								break;
								
		case 'getLockStatus':	UpdateLockCallBack(response.lock_status);
								break;			
			}
		}
		that.is_ready = true;
	};
	
	this.init(inClient);
};

// Request Class
function LSSyncRequest(inId, inAction, inRow)
{
var id;
var row;
var action = '';

	this.init = function(inId, inAction, inRow)
	{
		this.id = inId;
		this.row = inRow;
		this.action = inAction;
	};
	
	this.GetAction=function()
	{
		return this.action;
	};

	this.GetRow=function()
	{
		return this.row;
	};
		
	this.init(inId, inAction, inRow);
};