/* 	Copyright 2008 Maximum Processing Inc
	This script provides communication between the server and client

	ABOUT THIS SCRIPT

	DEPENDENCIES
	  1. logging.js
	  
	
	Change Log
 	Created 11/19/2008 Nathan Townsend
 	11/22/2008 - added logging NT
*/




Communication = new function()
{
  try{

    /* Private Properties */

		// if ajax is currently working on a request
    var working = false; 	     			
    
		// the standard xml document for communicating with stingray
    var xmlResponse = null;  	    	
    
		// the vrm xml document
    var vrmEdit = null;		    		  
    
		// an array of recent request objects
    var RequestHistory = null;      
    
		// an incrementing id used for matching command / response messages
    var itemId = 0;                 
		
		// a a copy of the vrm file attempting to save, used to prevent loss in case of save failure
		var _vrmSave = null;

		// used for session expiration
		var boolNotifiedTimeout = false;  
		
		// the last request sent to stingray
		var _lastRequest;

		// the last response sent from stingray
		var _lastResponse;




    /* Public Methods */
    return{

				/* + + + + Session Expiration Timer + + + + + */

		    // set to current time each time a page is loaded
			  LastPageTransition: null,
				
				// the number of seconds until a session expires
				SessionExpiration: 3600,
				
				// call from script to begin the session timer (AppList.OnLoad() custom script as of 03/05/2009)
				StartTimer: function(){
					setTimeout("Communication.CheckTimeout()", 1000);
				},
				
				// disables the session timer
				EnableSessionTimer: true,
				
				// how many seconds before expiration to display the expiration message
				ShowNotification: 120,

				// resets the session timer on every ajax request)
				ResetTimeout: function(){
				  boolNotifiedTimeout = false;
					Communication.LastPageTransition = new Date();
				},
				
				// stops the session timer, calls stingray end session method, and transfers the user to the login page
				LogOff: function(){
					boolNotifiedTimeout = false;
					Communication.LastPageTransition = null;
					//TODO: call stingray to expire session on the server 
				  window.location = "../../login.max?preprocess=true&sessionexpired=true";
				},
				
				// once the message displays this function keeps the time remaining updated every second (
				ShowTimeRemaining: function(){
  				
					if(!boolNotifiedTimeout)
					  return;
						
				  var s = Communication.LastPageTransition.getTime();
					
					var n = new Date().getTime();
					
					var t = (n - s) / 1000;
					
					var tr = Communication.SessionExpiration - Math.round(t);

					if(tr<60)
  					$("#ExpirationNoticeTimer").text(tr + " seconds");
					else	
					{
					  var m = Math.floor(tr / 60);
						var s = tr % 60;
						if(m>1)
						  msg = m + " minutes and " + s + " seconds"
						else
						  msg = m + " minute and " + s + " seconds"
							
					  $("#ExpirationNoticeTimer").text(msg);
					}
						
					setTimeout("Communication.ShowTimeRemaining()", 1000);
				},
				
				// occurs if the dialog is closed without pressing one of the buttons, should reset timer or log the user off
				TimeoutDialogClosed: function(){
				  if(!boolNotifiedTimeout)
					  return;

					Communication.ResetTimeout();
					//Communication.LogOff();

				},				
				
				// checks to see if the user session should be expired and shows a message before it expires
				CheckTimeout: function(){
				
				  if(Communication.LastPageTransition == null)
					  return;
						
					if(Communication.EnableSessionTimer == false)
					  return;
				
				  var s = Communication.LastPageTransition.getTime();
					
					var n = new Date().getTime();
					
					var t = (n - s) / 1000;
					
					var tr = Communication.SessionExpiration - Math.round(t);
										
					setTimeout("Communication.CheckTimeout()", 1000);
					
					if((t > (Communication.SessionExpiration - Communication.ShowNotification)) && (!boolNotifiedTimeout))
					{
					  
						var div = $("<div/>");
						
						div.append("<h3>Your session is about to expire</h3><p>Due to system inactivity your session is about to expire.</p> <p>You will be automatically logged off in <span id='ExpirationNoticeTimer'></span>.</p><p>&nbsp;</p>");
						
						div.append("<p><input type='button' onclick='Communication.ResetTimeout(); Global.HideMessage();' value='Continue Using System'> &nbsp; <input type='button' onclick='Communication.LogOff(); Global.HideMessage();' value='Log Off'></p>");
						
						$("#ModalWindow").bind('dialogclose', function(){ Communication.TimeoutDialogClosed(); $("#ModalWindow").unbind('dialogclose'); } );
						
						Global.ShowMessage(div);
						
						setTimeout("Communication.ShowTimeRemaining()", 1000);
						
						boolNotifiedTimeout = true;						
						
					}
					
					if(tr<= 0)
					{
						Communication.LogOff(); 
						Global.HideMessage();
  					Communication.ResetTimeout();						
					}
					
				},
		
		
		
		
		
				/* + + + + Ajax Server Requests + + + + + */
				
				GetLastRequest: function(){
				  return _lastRequest;
				},
				
				GetLastResponse: function(){
				  return _lastResponse;
				},
        
        // creates a new vrm file on the server
        EditorCreateNew: function()
        {
          try{

					    //Communication.ResetTimeout();

              var VRMName = prompt("Please enter a name for the new rule", "");
            
              var request = new Request();
            
              request.requestType = "Editor Create New Request";
            
              request.addToHistory = false;
            
              request.template = "createtemplate.max";
            
              request.id = $(xmlResponse).find("stingray").find("id").text();
            
              request.data = "id=" + request.id + "&templatename=" + VRMName;
            
              request.onSuccess = function(xml){ 
            
                ShowResponse(xml.xml);
            
                if( $(xml).find('stingray>html')[0] == null) // returned a new vrm file
                {
            
                  if(IsValidVRM(xml)) 
                  {
            
                    vrmEdit = xml;
            
                    $("#middle").attr("VRMName",  $(vrmEdit).find('vrm>function>fn').text() );
            
                    var _html = $(vrmEdit).find('vrm>html').text();
             
                    $("#middle").html(_html);
            
                    Editor.EnableEditor();
										
										RulesMaker.Enable();
                    
                    ExecuteCallback(null, true);
                    
                    Log.Add("Communications.EditorCreateNew", "Succeeded", LogType.Info);
            
                  }
            
                } else {
            
                  var html = $(xml).find('stingray>html').text();
            
                  Global.ShowMessage(html);
            
                }
                
            
              };
            
              request.onError = function(msg){
							  Log.Add("Communications.EditorCreateNew", "Failed", LogType.Warning);  
								ShowResponse(msg);  
								Global.ShowMessage("<h3>Editor Create New failed</h3><p>Please diagnose the problem using the information found in the 'Ajax' and 'Logging' tabs.</p>");							  	
							};
            
              ProcessRequest(request);
              
          } catch(err){ Log.Add("Communications.EditorCreateNew", err, LogType.Error); }
        },
        
        

        // loads the editable content and starts the editor
        EditorRequest: function(VRMName)
        {
          try{
					
					  //Communication.ResetTimeout();
            
            var request = new Request();
            
            request.requestType = "Editor Request";
            
            request.addToHistory = false;
          
            var html = $("div[VRMName='" + VRMName + "']");
          
            request.template = "edittemplate.max";
          
            if(xmlResponse != null)
              request.id = $(xmlResponse).find("stingray").find("id").text();
          
            request.data = "id=" + request.id + "&templatename=" + VRMName;
          
            request.onSuccess = function(xml){ 
          
              ShowResponse(xml.xml);
          
              if(IsValidVRM(xml)) 
              {
							  // is vrm xml, show editable content
								
                vrmEdit = xml;
               
                var _html = $(vrmEdit).find('vrm').find('html').text();
								
								var _vrmName = $(vrmEdit).find('vrm>function>fn').text(); 
          
                $("#middle").html(_html);
								
								$("#middle").attr("VRMName", _vrmName);
                
                Editor.EnableEditor();
                
                RulesMaker.Load(vrmEdit);
								
								$("#EditVRMButton").attr("disabled", "true");
								
								$("#EditVRMButton").val("Edit " + _vrmName);
          
              } else {
								
								var _html = $(xml).find("stingray>html").text();
								
								Global.ShowMessage(_html);
							}
           
              Log.Add("Communications.EditorRequest", "Succeeded", LogType.Info);
          
              ExecuteCallback(xml);
          
            };
          
            request.onError = function(msg){
						
						  Log.Add("Communications.EditorRequest", "Failed", LogType.Warning);  
						
							ShowResponse(msg);  
						
							Global.ShowMessage("<h3>Editor Request failed</h3><p>Please diagnose the problem using the information found in the 'Ajax' and 'Logging' tabs.</p>");
							
						};
          
            ProcessRequest(request);
        
          } catch(err){ Log.Add("Communications.EditorRequest", err, LogType.Error); }
        },



        // Updates the vrm on the server with the new content from the editor
        CloseEditor: function()
        {
          try{
					
					    //Communication.ResetTimeout();
							
              var VRMName = $("#middle").attr("VRMName");

              var request = new Request();
            
              request.requestType = "Editor Close Request";
            
              request.addToHistory = false;
            
              request.template = "closetemplate.max";
            
              request.id = $(xmlResponse).find("stingray").find("id").text();
            
              request.processData = false;
            
							request.data = "id=" + request.id + "&templatename=" + VRMName;
							
							_vrmSave = vrmEdit;
            
              request.onSuccess = function(xml){ 
            
                var status = $(xml).find('stingray>status').text();
								
								var _html = $(xml).find('stingray>html').text();
					 
                if(status == "success")
								{
								  
									
									Log.Add("Communications.CloseEditor", "Succeeded", LogType.Info);
								}
                else
								{
								
									Global.ShowMessage(_html);
									
                  vrmEdit = _vrmSave;
                  
                  _html = $(vrmEdit).find('vrm').find('html').text();
                
                  $("#middle").html(_html);
                  
                  Editor.EnableEditor();
                  
                  RulesMaker.Load(vrmEdit);
                  
                  $("#EditVRMButton").attr("disabled", "true");
									
									var errorComponent = $(xml).find('stingray>errorcomponent').text();
									
									errorComponent = errorComponent.split("_")[1];
									
									var errorProcess = $(xml).find('stingray>errorprocess').text();
									
									if(errorProcess == "PREPROCESS" || errorProcess == "POSTPROCESS")
									{
									  var proc = (errorProcess == "POSTPROCESS") ? "postproc" : "preproc";

									  RulesMaker.HighlightComponent(proc, errorComponent);
									}									
									
									Log.Add("Communications.CloseEditor", "Failed", LogType.Warning);
								}

              };
							
              request.onError = function(msg){
							  
								Log.Add("Communications.EditorUpdate", "Failed", LogType.Warning); 
								
                vrmEdit = _vrmSave;
               
                var _html = $(vrmEdit).find('vrm').find('html').text();
          
                $("#middle").html(_html);
                
                Editor.EnableEditor();
                
                RulesMaker.Load(vrmEdit);
								
								$("#EditVRMButton").attr("disabled", "true");

								ShowResponse(msg);
								
								Global.ShowMessage("<h3>Editor Update failed</h3><p>Please diagnose the problem using the information found in the 'Ajax' and 'Logging' tabs.</p>");  
								
							};

              ProcessRequest(request);

          } catch(err){ Log.Add("Communications.CloseEditor", err, LogType.Error); }    
        },        							


        // Updates the vrm on the server with the new content from the editor
        EditorUpdate: function()
        {
          try{
					
					    //Communication.ResetTimeout();

              var urlparts = window.location.href.split('/');
              var host_url = urlparts[0] + '/' + urlparts[1] + '/' + urlparts[2];
              var host_fix = new RegExp(host_url, "g");

							
              var VRMName = $("#middle").attr("VRMName");
              
              var template = $("#middle").html();
           
              var request = new Request();
            
              request.requestType = "Editor Update Request";
            
              request.addToHistory = false;
            
              var html = $("div[VRMName='" + VRMName + "']");
            
              request.template = "savetemplate.max";
            
              request.id = $(xmlResponse).find("stingray").find("id").text();
            
              request.processData = false;
            
              ReplaceSection(template, "html");
              
		  var toPost = CleanVRM(vrmEdit.xml);

		  //URL fix for the URL in the path...
              toPost= toPost.replace(host_fix, "../..");
              
							
              request.data = "id=" + request.id + "&templatename=" + VRMName + "&vrm=" + toPost;
							
							_vrmSave = vrmEdit;
            
              request.onSuccess = function(xml){ 
            
                ShowResponse(xml.xml);
            
                var status = $(xml).find('stingray>status').text();
            
                var _html = $(xml).find('stingray>html').text();
            
                if(status == "success")
								{
                  PropertiesEditor.ShowMessage("Saved Successfully");
									
									Log.Add("Communications.EditorUpdate", "Succeeded", LogType.Info);
								}
                else
								{
								
									Global.ShowMessage(_html);
									
                  vrmEdit = _vrmSave;
                  
                  _html = $(vrmEdit).find('vrm').find('html').text();
                
                  $("#middle").html(_html);
                  
                  Editor.EnableEditor();
                  
                  RulesMaker.Load(vrmEdit);
                  
                  $("#EditVRMButton").attr("disabled", "true");
									
									var errorComponent = $(xml).find('stingray>errorcomponent').text();
									
									var errorProcess = $(xml).find('stingray>errorprocess').text();
									
									errorComponent = errorComponent.split("_")[1];
									
									if(errorProcess == "PREPROCESS" || errorProcess == "POSTPROCESS")
									{
									  var proc = (errorProcess == "POSTPROCESS") ? "postproc" : "preproc";

									  RulesMaker.HighlightComponent(proc, errorComponent);
									}									
									
									Log.Add("Communications.EditorUpdate", "Failed", LogType.Warning);
								}

              };

              request.onError = function(msg){
							  
								Log.Add("Communications.EditorUpdate", "Failed", LogType.Warning); 
								
                vrmEdit = _vrmSave;
               
                var _html = $(vrmEdit).find('vrm').find('html').text();
          
                $("#middle").html(_html);
                
                Editor.EnableEditor();
                
                RulesMaker.Load(vrmEdit);
								
								$("#EditVRMButton").attr("disabled", "true");

								ShowResponse(msg);
								
								Global.ShowMessage("<h3>Editor Update failed</h3><p>Please diagnose the problem using the information found in the 'Ajax' and 'Logging' tabs.</p>");  
								
							};

              ProcessRequest(request);

          } catch(err){ Log.Add("Communications.EditorUpdate", err, LogType.Error); }    
        },        
        
        LinkRequest: function(url, replaceDiv)
        {
          try{
					
 					  //Communication.ResetTimeout();
						
					  var request = null;

					  // url param is a request object during automated testing 					
					  if(typeof url == "string") {

              request = new Request();
            
              request.addToHistory = true;
            
              request.requestType = "Link Request";
            
              if(xmlResponse != null)
                request.id = $(xmlResponse).find("stingray").find("id").text();
            
              request.template = url; //resource;
            
              if(xmlResponse != null)
                request.data = "id=" + request.id + "&preprocess=true";
						} else {
						  request = url;
						}
						
            request.onSuccess = function(xml){ 
          
              ShowResponse(xml.xml);
          
              xmlResponse = xml;
          
              var status = $(xml).find('stingray').find('status').text();
          
              var target = (replaceDiv == null) ? $(xml).find('stingray').find('target').text() : replaceDiv;
          
              var vrmName = $(xml).find('stingray').find('vrmname').text();
          
              var html = $(xml).find('stingray').find('html').text();
          
              if(status == "success")
              {
							  var tar = $("#" + target);
                tar.html(html);
          
                tar.attr("VRMName", vrmName);
								
                tar.find(".component").each(function(){
                  try 
                  {
											var ctrl = Helper.GetEditorComponent(this);
                      
                      ctrl.DefaultMode();
                      
                  } catch(err) {Log.Add("Editor.EnableEditor", err, LogType.Error); }
                });
								
								Global.Tooltips(Global.DisableTooltips);
								
								Editor.DisableEditor();
								
								$("#EditorNotes #save").attr("disabled", "true");
								
								$("#EditorNotes textarea").val("");		
		  
    							
              }    
              else
                Global.ShowMessage(html);
								
              Log.Add("Communications.LinkRequest", "Succeeded", LogType.Info);
          
              Editor.Refresh();
          
              ExecuteCallback(xml);
          
            };
          
            request.onError = function(msg){Log.Add("Communications.LinkRequest", "Failed", LogType.Warning);  ShowResponse(msg);  };
          
            ProcessRequest(request);            
            
          } catch(err){ Log.Add("Communications.LinkRequest", err, LogType.Error); }
        },
      
      
			
			
        // serializes the data from an html block and posts it to the target
				// html can be a jquery / dom object or a string of the element id and pass in params with ?name=value syntax
        SerialRequest: function(html, AddToHistory, srcElement, hideProgress)
        {
          try{
					if(hideProgress == null)hideProgress = false;					

					   //Communication.ResetTimeout();
						 
						 var request = null;
						 

						 if(html.requestType){
						   // the html param is a request object being used for automated testing
							 request = html;
							 						 
						 } else {
					
						   // the html param is html elements
  					   var strParams = "";
  						 
  					   if(typeof html == "string")
  						 {
  						   var temp = "";
  							 
  							 var id = html;
  						 
  						   if(html.indexOf("?") > -1)
  							 {
  						     temp = html.split("?");
  								 
  								 id = temp[0];
  								 
  								 strParams = temp[1];
  								 
  								 if(!strParams.beginsWith("&"))
  								   strParams = "&" + strParams;  
  							 }
  							 
  							 if(id.substring(0,1) != "#")
  							   id = "#" + id;
  								 
  							 html = $(id);
  						 }
  
  					    var validate = false;
  					
  					    var SubmitAct = null;
  							
  							// used when a submit event is triggered from outside the event.target element
  							if(srcElement != null)
  							{
  							  SubmitAct = $(srcElement).attr("name");  // 01/23/2009 - can't set the event.srcElement attr so pass the elem when triggering via script 
  								validate = ($(srcElement).attr("CauseValidation") == "true");									
  							}
  							
  							// when a submit event is triggered from an element
  					    if(event != null) 
  							{
  							  if(event.srcElement != null)
  								{
  								  srcElement = event.srcElement;
  								  var btn = $(event.srcElement);
  								  if(btn.parent().attr("REF")!="EditorSubmitButton")
  									  btn = $(".EditorSubmitButton input[DefaultButton='true']");
  
    							  SubmitAct = btn.attr("name");  // 12/17/08 - capture the name of the button that caused submit and add to data
  									validate = btn.attr("CauseValidation") == "true";									
  								}
  							}
  							
  							// temporarily disable the element causing the submit
  							var src = $(srcElement).attr("type");
  							if(src == "button")
  							{
  							  $(srcElement).attr("disabled", "true").attr("submitAct", "true");
  							  var id = $(srcElement).attr("id");
  							  setTimeout(function(){ var c = $("#" + id + "[submitAct='true']"); c.removeAttr("disabled"); c.removeAttr("submitAct"); }, 2000);
  							}
  							
  							if(validate)
  							{
  					      if(!Validator.Validate(html))
							//Michal & Sarah added this to check to see if the Validation passed before calling other functions if needed.    
                                          return false;
  							}					
 						 					
                request = new Request();
              
                var n = $(html).attr("VRMName");
              
                if(n == null)
                  n = $("#middle").attr("VRMName");
                
                request.template = n  + ".max";
  							
                if(AddToHistory == null)
                  AddToHistory = true;
              
                request.addToHistory = AddToHistory;
                
                request.requestType = "Serial Request";
              
                if(xmlResponse != null)
                  request.id = $(xmlResponse).find("stingray").find("id").text();
  
                request.data = "id=" + request.id;
  							
  							if(SubmitAct != null)
  							  request.data += "&SubmitAct=" + SubmitAct;
  								
  							request.data += strParams;
  							
  								
  							var d = Utilities.Serialize($(html));
  							
  							if(d.indexOf("=") > -1)
  							  request.data += "&" + d;
							}

              request.onSuccess = function(xml){
							  try{


			if(!hideProgress)Global.ShowProgress();

                  ShowResponse(xml.xml);

								  								
                  xmlResponse = xml;
									
									var stingray = $(xml).find('stingray'); 
              
                  var status = stingray.find('status').text();
              
                  var target = stingray.find('target').text();
              
                  var vrmName = stingray.find('vrmname').text();
              
                  var html = stingray.find('html').text();


                  if(status == "success")
                  {

									  var tar =  $("#" + target);
									  
									  tar.find("*").each(function(){
										  CleanFunctions($(this)[0]);
										});
									  
									  tar.empty();
			
                    tar.html(html);
              
                    tar.attr("VRMName", vrmName);

                    tar.find(".component").each(function(){
                      try 
                      {
    											var ctrl = Helper.GetEditorComponent(this);
                          
                          ctrl.DefaultMode();
                          
                      } catch(err) {Log.Add("Editor.EnableEditor", err, LogType.Error); }
                    });
										
										Global.Tooltips(Global.DisableTooltips);
  
    								if(target.toLowerCase() == "admintabs")
  									  setTimeout("Global.InitializeAdmin()", 250);
  										
    								if(target.toLowerCase() == "menu")
  									{
  									  var menu = $("#menu");
  										var root = menu.find(">ul");
  										var main = root.find(">li");
  										main.hover(function(){
  											var ul = $("<ul><li><a href='#'>test</a></li><li><a href='#'>test</a></li></ul>");
  											$("menu").append(ul);
  											ul.css("position", "absolute");
  											ul.css("display", "block");
  											ul.css("top", $(this).offset().top);
  											ul.css("left", $(this).offset().left);
  										});
  									}
										
                  } else {
									  var code = stingray.find('errorcode').text();
										if(code != "0101")
                      Global.ShowMessage(html);
  								}
									

                  Log.Add("Communications.SerialRequest", "Success", LogType.Info);
              
                  ExecuteCallback(xml);
	
								}catch(err){Log.Add("Communication.SerialRequest.onSuccess", err, LogType.Error);}
            
              };
            
              request.onError = function(msg){ 
		  if(!hideProgress)Global.ShowProgress();
		  
							  
								Log.Add("Communications.SerialRequest", "Failed", LogType.Warning);  
								
								ShowResponse(msg);
								
								Global.ShowMessage("<h3>Serial Request failed</h3><p>Please diagnose the problem using the information found in the 'Ajax' and 'Logging' tabs.</p>");      
								
							};
		
	
		  if(!hideProgress)Global.ShowProgress('open');

              ProcessRequest(request);

              
          } catch(err){ Log.Add("Communications.SerialRequest", err, LogType.Error); }
        },
				
				
				
				
				
				OpenWindow: function(url){
				    Communication.ResetTimeout();
	  			  var location = "../../window.htm?template=" + url.replace("?", "="); 
						window.open(location);
				},
				
				
				
				
				
				
				ModalWindow: function(url){
          try{
					
					  //Communication.ResetTimeout();
					
					  //Global.ShowMessage('');

            var request = new Request();
          
            request.requestType = "Modal Window Request";
          
            if(xmlResponse != null)
              request.id = $(xmlResponse).find("stingray").find("id").text();
          
            request.template = url; //resource;
          
            if(xmlResponse != null)
              request.data = "id=" + request.id + "&preprocess=true";
						
            request.onSuccess = function(xml){ 
          
              ShowResponse(xml.xml);
          
              var status = $(xml).find('stingray').find('status').text();
          
              var html = $(xml).find('stingray').find('html').text();
          
              if(status == "success")
              {

                Global.ShowMessage(html);
								
                $("#ModalWindow").find(".component").each(function(){
                  try 
                  {
											var ctrl = Helper.GetEditorComponent(this);
                      
                      ctrl.DefaultMode();
                      
                  } catch(err) {Log.Add("Editor.EnableEditor", err, LogType.Error); }
                });
								
								// disable tooltips 
								Global.Tooltips(Global.DisableTooltips);
    							
              }    
              else
                Global.ShowMessage(html);
								
              Log.Add("Communications.ModalWindow", "Succeeded", LogType.Info);
          
              Editor.Refresh();
          
            };
          
            request.onError = function(msg){Log.Add("Communications.ModalWindow", "Failed", LogType.Warning);  ShowResponse(msg);  };
          
            ProcessRequest(request);            
            
          } catch(err){ Log.Add("Communications.ModalWindow", err, LogType.Error); }
				},
				
			
				// url as follows vrmname.max?param1=value1&param2=value2.....
				// replaceID is either an element id to accept new innerHTML, or is a javascript function that will be passed the html 
				CustomRequest: function(url, replaceID, data)
				{
          try{
					
 					  //Communication.ResetTimeout();
					
  			    if(event != null)
  					{
  					  if(event.srcElement != null)
  						{
							  if(url.indexOf("?") == -1)
								  url += "?";
								else
								  url += "&";
									
								if($(event.srcElement).val() != "")
  							  url += "value=" + $(event.srcElement).val();
							}
						}
					
            var request = new Request();
          
            request.addToHistory = false;
          
            request.requestType = "Custom Request";
						
            if(xmlResponse != null)
              request.id = $(xmlResponse).find("stingray").find("id").text();
          
            request.template = url; //resource;
						
						request.processData = false;

            if(xmlResponse != null)
              request.data = "id=" + request.id;
							
						if(data)
						  request.data += data.beginsWith("&") ? data : "&" + data; 
          
            request.onSuccess = function(xml){ 

              ShowResponse(xml.xml);

              xmlResponse = xml;

              var status = $(xml).find('stingray').find('status').text();

              var html = $(xml).find('stingray').find('html').text();

              if(status == "success")
              {

							  if(typeof replaceID == "function")
								  replaceID(html);
								else
                  $("#" + replaceID).html(html);

              }    
              else
                Global.ShowMessage(html);

              Log.Add("Communications.CustomRequest", "Succeeded", LogType.Info);

              ExecuteCallback(xml);
          
            };
          
            request.onError = function(msg){Log.Add("Communications.CustomRequest", "Failed", LogType.Warning);  ShowResponse(msg);  };
          
            ProcessRequest(request);            
            
          } catch(err){ Log.Add("Communications.LinkRequest", err, LogType.Error); }
				}   
				
				  
    }
		
    
    /* PRIVATE METHODS */
    // Adds a request to the history object
    function AddToHistory(objRequest)
    {
      try{
			
			    return; // do not keep history
     
          objRequest.isLastRequest = true;
        
          if(!objRequest.addToHistory)
            return;
        
          if(RequestHistory == null)
            RequestHistory = new Array();
						
				  var _index = 0;
					
					// identify the desired requests, nullify the irrelevant
				  for(var i = 0; i<RequestHistory.length; i++)
					{
					  var req = RequestHistory[i];
						
						if(_index>0)
						  RequestHistory[i] = null;
						
						if(req.isLastRequest)
						{
						  _index = i;
							req.isLastRequest = false;
						}
					}
					
					// copy desired requests to a new array and clear objects from the old
					var newHist = new Array();
					
					if(_index < RequestHistory.length)
					{
					  for(var i = 0; i<=_index; i++)
						{
						  newHist[i] = RequestHistory[i];
						}
					}
					
					RequestHistory = null;

					RequestHistory = newHist;
					
					// add the new request
          RequestHistory[RequestHistory.length] = objRequest;
          
      } catch(err){ Log.Add("Communications.AddToHistory", err, LogType.Error); }
    }
    
        
    
    
    // Executes a callback if instructed in xml
    //TODO: make this not suck
    function ExecuteCallback(xml, boolExecute)
    {
      try{
        
          var callback;
        
          if(!boolExecute)
            callback= $(xml).find('stingray>callback').text();
          else
            callback = 1;
          
          if(callback == 1)
          {
            var div = document.createElement('div');
        
            $(div).attr("VRMName", "callback");
        
            Communication.SerialRequest(div, false);
            
            Log.Add("Communications.ExecuteCallback", "Executed", LogType.Info);
          }
      } catch(err){ Log.Add("Communications.ExecuteCallback", err, LogType.Error); }
    }


    function IsValidVRM(xml)
    { 
      try{
      
        var fn = $(xml).find("vrm>function>fn").text();
				
				if(fn == null || fn == "")
				  return false;
					
				return true;
        
      } catch(err){ Log.Add("Communications.IsValidVRM", err, LogType.Error); }
    }    
  
  
    

    // executes an ajax request using a request object
    function ProcessRequest(objRequest)
    {
      try{
			
          if(working)
            return;
						
					
          working = true;
					
          AddToHistory(objRequest);
        
          if(objRequest.url == null)
            objRequest.url = objRequest.host + objRequest.template;
        
          var date = new Date();
        
          var s = Utilities.ReplaceAll(date.toString(), " ", "");
        
          s = Utilities.ReplaceAll(s, ":", "");
        
          s += date.getMilliseconds();
         
          if(objRequest.url.indexOf("?") == -1)
            objRequest.url += "?t=" + s;
          else
          {
            if(objRequest.url.indexOf("&t=") != -1)
              objRequest.url += "&t=" + s;
          }
					
					
					if(objRequest.url.indexOf("IconTray.max") == -1)
			      Communication.ResetTimeout();
				
          //ShowCommand(objRequest.toString());
					ShowCommand(Utilities.ToString(objRequest));
					
          var memRequest = $.ajax({
        
            url: objRequest.url,
        
            data: objRequest.data,
        
            cache: objRequest.cache,
        
            timeout: objRequest.timeout,
        
            processData: true, //objRequest.processData,
        
            dataType: objRequest.dataType,
        
            type: objRequest.method,
        
            success: function(data){ 
						  try{
							
                working = false;
								
	  						ReqList.Show(data);
								
                objRequest.onSuccess(data);
								
								data = null;
								
              } catch(err){ Log.Add("Communications.ProcessRequest.success", err, LogType.Error); }
            },
        
            error: function(XMLHttpRequest, textStatus, errorThrown){
						  try{  

  							working = false;

	  						objRequest.onError(errorThrown +  textStatus);
								
              } catch(err){ Log.Add("Communications.ProcessRequest.error", err, LogType.Error); }							
						},
						
            complete: function(){ working = false; }
        
          });
					
					delete(objRequest);
					
         working = false;
         
      } catch(err){ Log.Add("Communications.ProcessRequest", err, LogType.Error); }
    }
    
    
    
    // replace a cdata section with new cdata
    function ReplaceSection(content, section)
    {
      try{
        
          var cdata = vrmEdit.createCDATASection(Utilities.CleanHTML(content));
        
          var newNode = vrmEdit.createElement(section);
        
          $(newNode).append(cdata);
        
          var replace = $(vrmEdit).find('vrm').find(section)[0];
        
          $(vrmEdit).find('vrm')[0].replaceChild(newNode, replace);  
          
       } catch(err){ Log.Add("Communications.ReplaceSection", err, LogType.Error); }
    }
    
    
    
    
    function Request()
    {
      try{
     
          this.isLastRequest = false;
        
          this.addToHistory = true;
        
          this.template = "";
        
          this.cache = false;
          
          this.method = "POST";
        
          this.data = null;
        
          this.id = "";
        
          this.processData = true;
        
          this.host = "../../";
        
          this.onSuccess = null;
        
          this.onError = null;
        
          this.timeout = 30000;
        
          this.dataType = "xml";
        
          this.url = null;
        
          this.requestType = "";
					
          
      } catch(err){ Log.Add("Communications.Request", err, LogType.Error); }
    }
    
    
    // sets all requests IsLastRequest property to false    
    function SetAllRequests()
    {
      try{
          for(var i = 0; i<RequestHistory.length; i++) 
          {
            RequestHistory[i].isLastRequest = false;
          }
       
       } catch(err){ Log.Add("Communications.SetAllRequests", err, LogType.Error); }
    }
    

    
    
    
    /* =================== DEBUGGING SCRIPT =================== */
    
    function ShowCommand(strCommand)
    {
     try{
		 
		     _lastRequest = strCommand;
    
         if($("#Commands").length == 0)
           return;
        
         var d = new Date();
        
         var h = d.getHours();
         if(h < 10)
           h = "0" + h;
        
         var m = d.getMinutes();
         if(m <  10)
           m = "0" + m;
        
         var s = d.getSeconds();
         if(s < 10)
           s = "0" + s;
        
         var time = "<span style='color:red;'>[" + itemId + "] " + h + ":"+ m + ":" + s + "</span> <br/>";
         
         var div = $("<div/>");
				 
				 var json = $("<div style='background:transparent;'/>");
        
         div.attr("itemId", itemId);
        
         json.text(strCommand);
        
         div.prepend(time);
				 
				 div.append(json);
				 
				 if(strCommand.indexOf("addToHistory\":false") == -1)
				 {
  			   //var request = eval('(' + strCommand + ')');
				 
    			 //AutomatedTesting.AddCommand(request);
				 }
        
         $(div).addClass("item");
        
         $(div).click(function(){  ResetBackgrounds(); SetBackground(this); });
        
         $("#Commands").append(div);
         
      } catch(err){ Log.Add("Communications.ShowCommand", err, LogType.Error); }
    }
    
    function SetBackground(div)
    {
      try{     
         var id = $(div).attr("itemId");
        
         $("#Commands div[itemId='" + id + "']").css("background-color", "#ddd"); 
        
         $("#Responses div[itemId='" + id + "']").css("background-color", "#ddd"); 
    
      } catch(err){ Log.Add("Communications.SetBackground", err, LogType.Error); }
    }
    
    function ResetBackgrounds()
    {
      try{
        $("#Commands div").each(function(){ $(this).css("background-color", "#fff") });
    
        $("#Responses div").each(function(){ $(this).css("background-color", "#fff") });
      
      } catch(err){ Log.Add("Communications.ResetBackgrounds", err, LogType.Error); }
    }
    
    function ShowResponse(strResponse)
    {
      try{
			
			   _lastResponse = strResponse;
			
         if($("#Responses").length == 0)
           return;
        
         var d = new Date();
        
         var h = d.getHours();
         if(h < 10)
           h = "0" + h;
        
         var m = d.getMinutes();
         if(m <  10)
           m = "0" + m;
        
         var s = d.getSeconds();
         if(s < 10)
           s = "0" + s;
        
        
         var time = "<span style='color:red;'>[ " + itemId + " ] " + h + ":"+ m + ":" + s + "</span> <br/>";
         
         var div = document.createElement('div');
        
         $(div).attr("itemId", itemId);
        
         $(div).text(strResponse);
        
         $(div).prepend(time);
        
         $(div).addClass("item");
        
         $(div).click(function(){  ResetBackgrounds(); SetBackground(this); });
        
         $("#Responses").append(div);
        
         itemId++;
         
      } catch(err){ Log.Add("Communications.ShowResponse", err, LogType.Error); }
    }
   
	  function CleanVRM(toPost){
		  try{
			
    		toPost = toPost.replace(/done[0-9]{1,}=\"[0-9]{1,}\"\s{0,}/g, "");
				
				var strs = ['ui-resizable-knob', 'ui-resizable-autohide', 'unselectable="on"', 'unselectable="off"', 'ui-sortable', 'ui-sortable-disabled', 'ui-state-disabled', 'aria-disabled="true"', 'aria-disabled="false"', '-disabled', 'aria="true"'];
				
				for(var i = 0; i<strs.length; i++)
				{
				  var str = strs[i];
					toPost = Utilities.ReplaceAll(toPost, str, "");
				}
				
				return toPost;
				
      } catch(err){ Log.Add("Communications.CleanVRM", err, LogType.Error);}
		}   
		
		
		function CleanFunctions(Elem)
		{
  
  		


		} 
    
  } catch(err){ Log.Add("Communications", err, LogType.Error); }
}
