//====================================================================================
//====================================================================================
//== EEM6Reports.js
//====================================================================================
//== JavaScript file that contains the definition for the following objects:
//==	ReportListObj
//==	ReportObj
//==	ReportCategoryObj
//==
//== All of these objects are non-visual and only used for storage
//====================================================================================
//====================================================================================

var RPT_AC_SAVED				= 15;

var RPT_ACTION_GRAPH			= 1;
var RPT_ACTION_TABLE			= 2;
var RPT_ACTION_DOWNLOAD			= 3;
var RPT_ACTION_SAVE				= 10;

//====================================================================================
//== ReportObj object
//====================================================================================
function ReportObj(RptID, RptName, RptDesc, ActionCode, CategoryID, bIsOwner) {
	this.ReportID							= RptID;
	this.ReportName							= DBToHTML(RptName);
	this.ReportDesc							= DBToHTML(RptDesc);
	this.ActionCode							= ActionCode;
	this.CategoryID							= CategoryID;
	this.SavedReport						= false;
	this.IsOwner								= bIsOwner;
	this.ArrayIndex							= null;
	this.AutoChart							= false;
	this.AutoSettings						= false;
	this.init								= function(){
		if (this.ActionCode == RPT_AC_SAVED){
			this.SavedReport				= true;
		}else{
			this.SavedReport				= false;
		}
	}
	this.init();
}

//====================================================================================
//== ReportCategoryObj object
//====================================================================================
function ReportCategoryObj(CatID, CatName, CatDesc){
	this.CategoryID							= CatID;
	this.CategoryName						= DBToHTML(CatName);
	this.CategoryDesc						= DBToHTML(CatDesc);
	this.ArrayIndex							= null;
	this.onCreate							= null;
}

//====================================================================================
//== ReportListObj object
//====================================================================================
function ReportListObj(ObjectName){
	//== ObjectName							How to refer to this instance of the object
	this.ObjectName							= ObjectName;
	//== ReportID							The ID currently selected, loading, saving...
	//==										ID is what dataminer.dll gives us
	this.ReportID							= null;
	//== ReportList							array of ReportObj objects
	this.ReportList							= [];
	//== ReportIndex						The index of this.ReportList[] for the selected ReportObj
	this.ReportIndex						= null;
	//== CategoryList						array of ReportCategoryObj objects
	this.CategoryList						= [];
	//== CategoryIndex						the index of this.CategoryList[] for the selected ReportCategoryObj
	this.CategoryIndex						= null;
	//== UOMList							an array of UOMs we keep track of so we know if it is OK to graph 
	this.UOMList							= [];
	//== UOMEnabling						the ID of the UOM we are trying to enable
	this.UOMEnabling						= -1;
	//== PointList							an array of selected points we keep track of so we know if it is OK to graph
	this.PointList							= [];
	//== SettingsRetrieved					have we retrieved the settings for the current report already?
	this.SettingsRetrieved					= false;
	//== ReportAdding						the ReportObj object that we are trying to add
	this.ReportAdding						= null;
	//== ReportDeleting						the ReportObj object that we are trying to delete
	this.ReportDeleting						= null;
	//== CategoryAdding						the ReportCategoryObj object that we are trying to add
	this.CategoryAdding						= null;
	this.QueuedCommand						= null;
	this.QueuedParams						= null;
	this.QueuedTabpage						= null;
	this.TabLoading								= null;
	//== ReportIndexCheck					checks to see if "index" is valid (is it in this.ReportList[])
	this.ReportIndexCheck					= function(index){
		return IsBetween(index, 0, this.ReportList.length-1);
	}
	//== CategoryIndexCheck					checks to see if "index" is valid (is it in this.CategoryList[])
	this.CategoryIndexCheck					= function(index){
		return IsBetween(index, 0, this.CategoryList.length-1);
	}
	//== ReportFromID						given a ReportID, returns the ReportObj object it refers to
	this.ReportFromID						= function(ReportID){
		for (var iLoop=0; iLoop < this.ReportList.length; iLoop++){
			if (this.ReportList[iLoop].ReportID == ReportID){
				return this.ReportList[iLoop];
			}
		}
	}
	//== ReportIDCheck						checks to see if ReportID is in the list of reports
	this.ReportIDCheck						= function(ReportID){
		return NotNull(this.ReportFromID(ReportID));
	}
	//== CategoryFromID						given a CategoryID, returns the ReportCategoryObj object it refers to
	this.CategoryFromID						= function(CatID){
		for (var iLoop=0; iLoop < this.CategoryList.length; iLoop++){
			if (this.CategoryList[iLoop].CategoryID == CatID){
				return this.CategoryList[iLoop];
			}
		}
	}
	//== CategoryIDCheck					checks to see if CatID is in the list of report categories
	this.CategoryIDCheck					= function(CatID){
		return NotNull(this.CategoryFromID(CatID));
	}
	//== RegisterReport						adds a ReportObj to the list of reports we know about
	this.RegisterReport						= function(oRpt){
		DebugText("Registering report [" + oRpt.ReportID + "]: " + oRpt.ReportName + ", " + oRpt.ReportDesc);
		DebugText("   ActionCode = " + oRpt.ActionCode);
		DebugText("   CategoryID = " + oRpt.CategoryID);
		DebugText("   IsOwner = " + oRpt.IsOwner);
		var id								= this.ReportList.length;
		this.ReportList[id]					= oRpt;
		oRpt.ArrayIndex						= id;
	}
	//== _RecalcIndexes						recalculates all .ArrayIndex values of the reports in the .ReportList array
	this._RecalcIndexes						= function(){
		for (var iLoop=0; iLoop < this.ReportList.length; iLoop++){
			this.ReportList[iLoop].ArrayIndex = iLoop;
		}
	}
	//== UnregisterReport					removes the report from the list
	this.UnregisterReport					= function(oRpt){
		DebugText("Unregistering report [" + oRpt.ReportID + "]: " + oRpt.ReportName + ", " + oRpt.ReportDesc);
		//== Remove it from the list
		this.ReportList.splice(oRpt.ArrayIndex, 1);
		//== Recalculate array indexes
		this._RecalcIndexes();
	}
	//== RegisterCategory					adds a ReportCategoryObj to the list of report categories
	this.RegisterCategory					= function(oCat){
		DebugText("Registering report category [" + oCat.CategoryID + "]: " + oCat.CategoryName + ", " + oCat.CategoryDesc);
		var id								= this.CategoryList.length;
		this.CategoryList[id]				= oCat;
		oCat.ArrayIndex						= id;
	}
	//== SaveNew
	this.SaveNew							= function(){
		if (EEM6().Reports.ValidateData(RPT_ACTION_SAVE)){
			WindowOpenModal(PATH_HTML + "ReportSave.html", "dialogHeight:378px;scroll:no;resizable:no;status:no;");
		}
	}
	//== AddReport							add a new report to the system for this user by calling dataminer.dll
	this.AddReport							= function(oRpt, SaveChannels){
		//== Save the report object we are trying to add
		this.ReportAdding					= oRpt;
		var sParams							= "ReportName=" + escape(HTMLToDB(oRpt.ReportName)) 
												+ "&ReportDesc=" + escape(HTMLToDB(oRpt.ReportDesc))
												+ "&CategoryID=" + oRpt.CategoryID
												+ "&SaveChannels=" + SaveChannels;
		var sSettings						= EEM6().Reports.SettingsParams();
		if (sSettings.length > 0){
			sParams							= sParams + "&" + sSettings;
		}
		var oReq							= new RequestObj(null, "/ReportSaveNew", sParams, true);
		//== Register the request so we can get its RequestID, but don't process it yet
		EEM6().Session.AddRequest(oReq, false);
		oReq.onLoad							= this.ObjectName + ".AddReportDone(true, " + oReq.RequestID + ")";
		oReq.onError						= this.ObjectName + ".AddReportDone(false, " + oReq.RequestID + ")";
		EEM6().Session.ProcessRequests();
	}
	//== AddReportDone						event called by the EEM6().Session object after the dataminer request is completed
	this.AddReportDone						= function(Success, ReqID){
		var oReq							= EEM6().Session.RequestFromID(ReqID);
		var oRpt							= this.ReportAdding;
		this.ReportAdding					= null;
		if (Success){
			//== Grab the new report ID
			oRpt.ReportID					= oReq.ResultValue("ReportID");
			//== Register the new report in our report list
			this.RegisterReport(oRpt);
			//== Make sure we ID this one as the currently selected report
			//==	second param=false so we don't try to load it from the database (no need to)
			this.ReportSelect(oRpt.ReportID, false);
			//== Determine whether or not the "Delete" button is enabled
			//== DGS - 5/29/2003 - switched the frame reference to select_sites_contol frame //
			EEM6().fraMainControl.AllowDelete(oRpt.SavedReport && oRpt.IsOwner);
			DebugText("Added a new report to the system: [" + oRpt.ReportID + "] " + oRpt.ReportName + " (Category=" + oRpt.CategoryID + ")");
			var sParams						= "ReportID=" + oRpt.ReportID + "&Refresh=true";
			oReq							= new RequestObj(EEM6().fraSideMenuBar, "/LoadSideMenuBar", sParams, true);
			EEM6().Session.AddRequest(oReq)
		}else{
			alert("Error: Unable to add report '" + oRpt.ReportName + "'.");
		}
	}
	//== AddCategory						add a new report category to the system for this user by calling dataminer.dll
	this.AddCategory						= function(oCat){
		//== Save the category object we are trying to add
		this.CategoryAdding					= oCat;
		var sParams							= "CategoryName=" + escape(HTMLToDB(oCat.CategoryName)) 
												+ "&CategoryDesc=" + escape(HTMLToDB(oCat.CategoryDesc));
		var oReq							= new RequestObj(null, "/ReportCategoryCreate", sParams, true);
		//== Register the request so we can get its RequestID, but don't process it yet
		EEM6().Session.AddRequest(oReq, false);
		oReq.onLoad							= this.ObjectName + ".AddCategoryDone(true, " + oReq.RequestID + ")";
		oReq.onError						= this.ObjectName + ".AddCategoryDone(false, " + oReq.RequestID + ")";
		EEM6().Session.ProcessRequests();
	}
	//== AddCategoryDone					event called by the EEM6().Session object after the dataminer request is completed
	this.AddCategoryDone					= function(Success, ReqID){
		var oReq							= EEM6().Session.RequestFromID(ReqID);
		var oCat							= this.CategoryAdding;
		if (Success){
			this.CategoryAdding				= null;
			oCat.CategoryID					= oReq.ResultValue("CategoryID");
			this.RegisterCategory(oCat);
			DebugText("Added a new category to the system: [" + oCat.CategoryID + "] " + oCat.CategoryName);
			try{
				oCat.onCreate(oCat);
			}catch(err){
				DebugError("AddCategoryDone", err);
			}
		}else{
			alert("Error: Unable to add category '" + oCat.CategoryName + "'.");
		}
	}
	//== DeleteReport						deletes the report referred to by ReportID
	this.DeleteReport						= function(ReportID){
		var oRpt							= this.ReportFromID(ReportID);
		if (oRpt.SavedReport){
			if (confirm("Delete the report '" + oRpt.ReportName + "'?")){
				//== Keep track of the report object we are trying to delete
				this.ReportDeleting			= oRpt;
				var sParams					= "ReportID=" + oRpt.ReportID;
				var oReq					= new RequestObj(null, "/ReportDelete", sParams, true);
				//== Register the request so we can get its RequestID, but don't process it yet
				EEM6().Session.AddRequest(oReq, false);
				oReq.onLoad					= this.ObjectName + ".DeleteReportDone(true, " + oReq.RequestID + ")";
				oReq.onError				= this.ObjectName + ".DeleteReportDone(false, " + oReq.RequestID + ")";
				EEM6().Session.ProcessRequests();
			}
		}else{
			alert("You can only delete saved reports.");
		}
	}
	//== DeleteReportDone					event called by the EEM6().Session object after the dataminer request is completed
	this.DeleteReportDone					= function(Success, ReqID){
		var oReq							= EEM6().Session.RequestFromID(ReqID);
		var oRpt							= this.ReportDeleting;
		this.ReportAdding					= null;
		if (Success){
			oRpt.ReportID					= oReq.ResultValue("ReportID");
			DebugText("Deleted the report: [" + oRpt.ReportID + "] " + oRpt.ReportName + " from the system");
			this.UnregisterReport(oRpt);
			//== Refresh the side menu bar
			oReq							= new RequestObj(EEM6().fraSideMenuBar, "/LoadSideMenuBar", "Refresh=true", true);
			EEM6().Session.AddRequest(oReq)
		}else{
			var sMsg						= "Unable to delete report '" + oRpt.ReportName + "':"
												+ "\n\n" + oReq.ResultValue("ErrorMessage");
			alert(sMsg);
		}
	}
	//== DeleteSelected						deletes the current report selected
	this.DeleteSelected						= function(){
		var oRpt							= this.ReportSelected();
		if (NotNull(oRpt)){
			this.DeleteReport(oRpt.ReportID);
		}else{
			alert("No current report to delete");
		}
	}
	//== UOMsClear							clear out the list of UOMs
	this.UOMsClear							= function(){
		this.UOMList						= [];
	}
	//== UOMRegister						register a new UOM line from the "Channels - Traces" frame
	this.UOMRegister						= function(UOMID, bEnabled, UOMName, Traces, bValid){
		//== First, just create a new object and store it in the array for safe keeping
		var id								= this.UOMList.length;
		var oUOM							= new Object();
		oUOM.ID								= UOMID;
		if (oUOM.ID == this.UOMEnabling){
			//== This is the UOM the user just clicked on to try to Enable it
			if (!bEnabled){
				//== The server did not allow the UOM to become enabled
				//==	This SHOULD be the only reason why the request to enable it failed
				alert("You must select a point with '" + UOMName + "' before enabling it.");
			}
		}
		oUOM.Enabled						= bEnabled;
		oUOM.Name							= UOMName;
		oUOM.Traces							= Traces;
		oUOM.Valid							= bValid;
		this.UOMList[id]					= oUOM;
		oUOM.ArrayIndex						= id;
	}
	//== UOMsActive							returns the number of currently active UOMs
	this.UOMsActive							= function(bCheckValid){
		bCheckValid							= DefaultValue(bCheckValid, false);
		var iRet							= 0;
		for (var iLoop=0; iLoop < this.UOMList.length; iLoop++){
			if (this.UOMList[iLoop].Enabled){
				if (bCheckValid){
					if (this.UOMList[iLoop].Valid){
						iRet++;
					}
				}else{
					iRet++;
				}
			}
		}
		return iRet;
	}
	//== PointsClear						clear out the list of selected points
	this.PointsClear						= function(){
		this.PointList						= [];
	}
	//== PointRegister						register a new selected point from the "Selected Points" frame
	this.PointRegister						= function(NodeID, NodeName, LongName, UOMs){
		//== First, just create a new object and store it in the array for safe keeping
		var id					= this.PointList.length;
		var oPoint				= new Object();
		oPoint.ID				= NodeID;
		oPoint.Name				= NodeName;
		oPoint.LongName		= LongName;
		oPoint.UOMs				= UOMs;
		oPoint.elementIMG		= null;
		this.PointList[id]		= oPoint;
	}
	//== PointsActive						returns the number of currently "active" points
	//==										meaning that it is a selected node with at least one relevant UOM
	this.PointsActive						= function(){
		var iRet							= 0;
		for (var iLoop=0; iLoop < this.PointList.length; iLoop++){
			if (this.PointList[iLoop].UOMs.length > 0){
				iRet++;
			}
		}
		return iRet;
	}
	//== Clear								clears any selected report 
	this.Clear								= function(){
		this.ReportIndex					= null;
		this.CategoryIndex					= null;
		//== Next time they want to edit report settings, make sure to grab them from the server (DB) first
		this.SettingsRetrieved				= false;
	}
	//== ReportSelect						sets the selected report
	this.ReportSelect						= function(ReportID, bLoadReport, sParams){
		bLoadReport							= DefaultValue(bLoadReport, true);
		this.Clear();
		//== Only reset the graph tabs if we are loading a new report
		if (bLoadReport){
			this.GraphReset(true);
		}
		var oRpt							= this.ReportFromID(ReportID);
		if (NotNull(oRpt)){
			this.ReportIndex				= oRpt.ArrayIndex;
			var oCat						= this.CategoryFromID(oRpt.CategoryID)
			if (NotNull(oCat)){
				this.CategoryIndex			= oCat.ArrayIndex;
			}
			if (bLoadReport){
				this.SettingsLoad(oRpt.ReportID, sParams);
			}
		}
	}
	//== ReportSelected						returns the selected ReportObj, if any
	this.ReportSelected						= function(){
		if (this.ReportIndexCheck(this.ReportIndex)){
			return this.ReportList[this.ReportIndex];
		}
	}
	//== CategorySelected					returns the selected ReportCategoryObj, if any
	this.CategorySelected					= function(){
		if (this.CategoryIndexCheck(this.CategoryIndex)){
			return this.CategoryList[this.CategoryIndex];
		}
	}
	//== ReportExists						does this report already exist?  (name + category ID must be unique)
	this.ReportExists						= function(sName, CategoryID){
		var bRet							= false;
		sName								= sName.toUpperCase();
		for (var iLoop=0; iLoop < this.ReportList.length; iLoop++){
			if (this.ReportList[iLoop].ReportName.toUpperCase() == sName){
				if (this.ReportList[iLoop].CategoryID == CategoryID){
					bRet 					= true;
					break;
				}
			}
		}
		return bRet;
	}
	//== CategoryExists						does this category already exist?
	this.CategoryExists						= function(sName){
		var bRet							= false;
		sName								= sName.toUpperCase();
		for (var iLoop=0; iLoop < this.CategoryList.length; iLoop++){
			if (this.CategoryList[iLoop].CategoryName.toUpperCase() == sName){
				bRet 					= true;
				break;
			}
		}
		return bRet;
	}
	//== SettingsLoad						tell the server to load the saved values for a selected report
	this.SettingsLoad						= function(ReportID, sParams){
		sParams										= DefaultValue(sParams, "");
		var oReq;
		with (EEM6().Session){
			oReq							= new RequestObj(null, "/ReportLoad", "ReportID=" + ReportID + sParams, true);
			//== Add the request, but don't process yet, we want to get the RequestID
			AddRequest(oReq, false);
			oReq.onError					= this.ObjectName + ".SettingsLoadError(" + ReportID + ", " + oReq.RequestID + ")";
			oReq.onLoad						= this.ObjectName + ".SettingsLoadComplete(" + ReportID + ", " + oReq.RequestID + ")";
			AddRequest(new RequestObj(EEM6().fraSelectedPoints, "/SelectedPointsList", null, false));
			AddRequest(new RequestObj(EEM6().fraUOMTraces, "/UOMTraceList", null, false));
			oReq							= new RequestObj(EEM6().Tabsheet.TabFrame(TABPAGE_REPORT_SETTINGS), "/DisplaySettings", null, false);
			oReq.onLoad						= this.ObjectName + ".SettingsLoadDisplay(" + ReportID + ")";
			AddRequest(oReq);
		}
	}
	//== SettingsLoadComplete				called from the Session object if works
	this.SettingsLoadComplete				= function(ReportID, ReqID){
		//== Get the report object
		var oRpt							= this.ReportFromID(ReportID);
		//== Get the request object
		var oReq							= EEM6().Session.RequestFromID(ReqID);
		if (oReq.ResultValue("ReportID") == ReportID){
			try{
				oRpt.AutoChart				= eval(oReq.ResultValue("AutoChart"));
				oRpt.AutoSettings			= eval(oReq.ResultValue("AutoSettings"));
			}catch(err){
			}
			//== Determine whether or not the "Delete" button is enabled
			EEM6().fraMainControl.AllowDelete(oRpt.SavedReport && oRpt.IsOwner);
			//== OK, load worked!
			this.SettingsRetrieved			= true;
		}else{
			//== Wha?  ReportID received is not the one we asked for
			//== Construct the error message
			var sMsg							= "Problem Loading Report\n\n"
													+ "Report Name = " + oRpt.ReportName + "\n"
													+ "Report ID = " + oRpt.ReportID + "\n"
													+ "Error = Server returned invalid ReportID of " 
													+ oReq.ResultValue("ReportID") + ", expecting "
													+ oRpt.ReportID;
			alert(sMsg);			
		}
	}
	//== SettingsLoadError					called from the Session object if there is an error with the request
	this.SettingsLoadError					= function(ReportID, ReqID){
		//== Get the report object
		var oRpt							= this.ReportFromID(ReportID);
		//== Get the request object
		var oReq							= EEM6().Session.RequestFromID(ReqID);
		if (!oReq.ErrorHandled){
			//== Construct the error message
			var sMsg						= "Error Loading Report\n\n"
													+ "Report Name = " + oRpt.ReportName + "\n"
													+ "Report ID = " + oRpt.ReportID + "\n"
													+ "Error = " + oReq.ErrorText;
			//== Tell the user
			alert(sMsg);
		}
	}
	//== SettingsLoadDisplay				called when the /DisplaySettings is done after a /ReportLoad
	//==										decides whether or not to show the settings tab, auto-generate a graph
	this.SettingsLoadDisplay				= function(ReportID){
		var oRpt							= this.ReportFromID(ReportID);
		if (oRpt.AutoSettings){
			DebugText("Automatically displaying report settings for " + oRpt.ReportName);
			EEM6().Tabsheet.TabShow(TABPAGE_REPORT_SETTINGS);
		}
		if (oRpt.AutoChart){
			DebugText("Checking to see if we should auto-chart " + oRpt.ReportName);
			if (this.ValidateData(RPT_ACTION_GRAPH, false)){
				DebugText("Auto-charting " + oRpt.ReportName);
				//== set the 3rd parameter to False
				//==		don't want to send the Report Settings parameters since there is a timing issue
				//==		where the values have not changed by the time we ask for a graph
				//==		These settings should not have changed anyway between the time we loaded them from
				//==		the database and the time we tried to do an "AutoChart"
				this.Graph("", true, false);
			}
		}
	}
	//== SettingsShow						Show the selected report settings
	this.SettingsShow						= function(){
		var ReportID						= this.ReportID;
		if (this.SettingsRetrieved){
			//== We already have the settings at the browser, no need to refresh from the server
			DebugText("Report.SettingsShow: using local setttings");
			this.SettingsShowComplete();
		}else{
			DebugText("Report.SettingsShow: loading from server");
			with (EEM6().Session){
				var oReq 						= new RequestObj(EEM6().Tabsheet.TabFrame(TABPAGE_REPORT_SETTINGS), 
																"/DisplaySettings", null, false);
				//== Add the request so we can get the RequestID, but don't process it yet
				AddRequest(oReq, false);
				oReq.onError					= this.ObjectName + ".SettingsShowError(" + ReportID + ", " + oReq.RequestID + ")";
				oReq.onLoad						= this.ObjectName + ".SettingsShowComplete(" + ReportID + ", " + oReq.RequestID + ")";
				ProcessRequests();
			}
		}
	}
	//== SettingsShowComplete				we were able to get the settings from the server
	this.SettingsShowComplete				= function(ReportID, ReqID){
		this.SettingsLoaded					= true;
		EEM6().Tabsheet.TabShow(TABPAGE_REPORT_SETTINGS);
	}
	//== SettingsShowError					had a problem displaying the settings for the current report
	this.SettingsShowError					= function(ReportID, ReqID){
		//== Get the report object
		var oRpt							= this.ReportFromID(ReportID);
		//== Get the request object
		var oReq							= EEM6().Session.RequestFromID(ReqID);
		//== Construct the error message
		var sMsg							= "Error Retrieving Report Settings\n\n"
												+ "Report Name = " + oRpt.ReportName + "\n"
												+ "Report ID = " + oRpt.ReportID + "\n"
												+ "Error = " + oReq.ErrorText;
		//== Tell the user
		alert(sMsg);
	}
	//== SettingsParams						returns the settings parameters to save to the client datasets before
	//==										making calls to things like "Graph" or "Save Report"
	//==									add the params on to the request string when calling dataminer.dll
	this.SettingsParams						= function(){
		var sRet							= "";
		var oFrame							= EEM6().Tabsheet.TabFrame(TABPAGE_REPORT_SETTINGS);
		if (NotNull(oFrame)){
			try{
				//== Try to get the document in the report settings tab
				var oDoc					= oFrame.contentWindow.document;
				//== Find the first <form> on the document and assume it has all of the settings on it
				var oForm					= oDoc.forms(0);
				//== Now, grab the parameters
				sRet						= EEM6().Session.FormParams(oForm);
				DebugText("Report Settings = " + sRet);
			}catch(err){
				DebugError("Reports.SettingsParams", err);
			}
		}else{
			DebugText("Could not retrieve report settings parameters, could not find report settings tab");
		}
		return sRet;
	}
	this.ValidationMsg						= function(Msg, bShow){
		if (bShow){
			alert(Msg);
		}else{
			DebugText(sMsg);
		}
	}
	//== ValidateData						checks to see if you have valid data for doing any of the following:
	//==										Graph, Table, Download, Save
	//==									make sure to include the EEM6ReportSettings.js as well since we call
	//==										the masterValidation function
	this.ValidateData						= function(iAction, bShowMessages){
		iAction								= DefaultValue(iAction, RPT_ACTION_GRAPH);
		bShowMessages						= DefaultValue(bShowMessages, true);
		var bRet							= true;
		var bCheckForm						= false;
		var bCheckPoints					= false;
		var bCheckUOMs						= false;
		//== Is the report a Calendar Report?
		var bCalendar						= (this.ReportSelected().ActionCode == MENU_ACTION_RPT_CALENDAR);
		//== What type of action is the user trying to perform?
		switch (iAction){
			case RPT_ACTION_GRAPH:
			case RPT_ACTION_TABLE:
//				if (bCalendar){
//					bRet					= false;
//					this.ValidationMsg("You must graph the calendar report before displaying the table.", bShowMessages);
//				}
			case RPT_ACTION_DOWNLOAD:
//				if (bCalendar){
//					bRet					= false;
//					this.ValidationMsg("You must graph Calendar reports must be graphed before they can be downloaded.", bShowMessages);
//				}else{
					bCheckForm				= true;
					bCheckPoints			= true;
					bCheckUOMs				= true;
//				}
				break;
			case RPT_ACTION_SAVE:
			default:
		}
		//== First, just check the overall settings (Report Settings tab)
		if (bRet && bCheckForm){
			try{
				var oWin					= EEM6().Tabsheet.TabFrame(TABPAGE_REPORT_SETTINGS).contentWindow;
				if (oWin != null){
					//== The report settings HTML document should have a "doValidate()" method that we can call
					bRet					= oWin.doValidate();
				}else{
					this.ValidationMsg("Could not find report settings to validate", bShowMessages);
					bRet					= false;
				}
			}catch(err){
				DebugError("Reports.ValidateData", err);
				this.ValidationMsg("Could not validate report settings.", bShowMessages);
				bRet						= false;
			}
		}
		//== Do they have any selected points?
		if (bRet && bCheckPoints){
			if (this.PointsActive() == 0){
				this.ValidationMsg("No channels selected."
														+ "  Please select one or more channels from the Channels - Traces list."
														+ "  To create a list, selected points of interest in the Site Selection list.", bShowMessages);
				bRet 						= false;
			}else{
				if (bCalendar && this.PointsActive() > 1){
					//== Calendar report can only have a single point selected
					this.ValidationMsg("You must select a single point for this report.", bShowMessages);
					bRet					= false;
				}
			}
		}
		//== Do they have active UOMs?
		if (bRet && bCheckUOMs){
			var iActive						= this.UOMsActive();
			if (iActive == 0){
				this.ValidationMsg("You must have at least one enabled channel.", bShowMessages);
				bRet 						= false;
			}else{
				if (this.UOMsActive(true) != iActive){
					this.ValidationMsg("One or more enabled channels are missing their high/low values.", bShowMessages);
					bRet					= false;
				}else{
					if (bCalendar && this.UOMsActive() > 1){
						//== Calendar report can only have a single UOM selected
						this.ValidationMsg("You must select a single channel for this report.", bShowMessages);
						bRet					= false;
					}
				}
			}
		}
		//== Do they have traces selected for TI type reports (Historical, Trends, Custom)?
		if (bRet && bCheckUOMs){
		        oDoc                                             = EEM6().Tabsheet.TabDocument(TABPAGE_REPORT_SETTINGS);
		        if(oDoc.settingsForm.anType.value == "TI")
                          for(var iLoop=0; iLoop < this.UOMList.length; iLoop++){
                            if (this.UOMList[iLoop].Enabled && this.UOMList[iLoop].Traces == ""){
                              alert("One or more enabled channels are missing Trace information.\nClick the 'E' icon next to the the Channel to select a Trace.");
                              bRet = false;
                              break;}}
		}
		return bRet;
	}
	this._TabClose							= function(iTab){
		if (iTab != this.TabLoading){
			EEM6().Tabsheet.TabClose(iTab);
		}
	}
	this.GraphReset							= function(bClearAll){
		bClearAll							= DefaultValue(bClearAll, false);
		var oTabsheet						= EEM6().Tabsheet;
		if (NotNull(oTabsheet)){
			var oTab;
			if (bClearAll){
				//== Get rid of the report settings tab
				//== 	but only if we want to "clear all" tabs
				//==	which happens when we select a new report
				this._TabClose(TABPAGE_REPORT_SETTINGS);
			}
			//== Get rid of the main graph tab
			this._TabClose(TABPAGE_GRAPH_MAIN);
			//== Get rid of the table data tab
			this._TabClose(TABPAGE_TABLE);
			//== Get rid of any existing drilldowns
			var iLoop							= 0;
			while (iLoop < oTabsheet.TabPages.length){
				oTab							= oTabsheet.TabPages[iLoop];
				iLoop++;
				if (oTab.Visible){
					if (oTab.Tag.search("GRAPH.") == 0){
						//== The tag starts with "GRAPH.", so we know it is one of ours and we can close it
						this._TabClose(oTab.TabID);
						//== Since the TabPages array might have changed on the .TabClose, restart at the beginning
						iLoop					= 0;
					}
				}
			}
		}
	}
	this._Graph								= function(sCommand, sParams, iTabPage){
		this.QueuedCommand					= sCommand;
		this.QueuedParams					= sParams;
		this.QueuedTabpage					= iTabPage;
		this.TabLoading							= iTabPage;
		//== Set the main graph page to a "GraphLoading.html"
		//==	this should in turn call back to the this.GraphCallback() function
		EEM6().Tabsheet.TabSetCaption(iTabPage, "Loading...");
		EEM6().Tabsheet.TabSetSource(iTabPage, PATH_HTML + "GraphLoading.html");
	}
	this.Graph								= function(sParams, bClearAll, bAddSettings){
		bClearAll								= DefaultValue(bClearAll, false);
		bAddSettings						= DefaultValue(bAddSettings, true);
		if (this.ValidateData(RPT_ACTION_GRAPH)){
			this.GraphReset(bClearAll);
			sParams								= DefaultValue(sParams, "");
			if (bAddSettings){
				sParams 						= this.SettingsParams() + sParams;
			}
			this._Graph("/Graph", sParams, TABPAGE_GRAPH_MAIN);
		}
	}
	this.GraphDrilldown						= function(sParams, doc){
		var TabID;
		if (NotNull(doc)){
			//== We want to drilldown into the same tab
			TabID							= EEM6().Tabsheet.TabFromDocument(doc).TabID;
		}else{
			//== We want to drilldown into a new tab
			TabID							= EEM6().Tabsheet.NextTabID();
			var oTab						= new TabPageObj(TabID, "Drilldown");
			oTab.Tag						= "GRAPH.DRILLDOWN";
			oTab.CanTable					= true;
			oTab.CanDownload				= true;
			oTab.CanLaunch					= true;
			oTab							= EEM6().Tabsheet.AddTab(oTab);
		}
		this._Graph("/GraphDrilldown", sParams, TabID);
	}
	//== GraphShowChildren					Show the child traces for a graph
	//==										result should go back onto the same tab that
	//==										the current graph is on
	this.GraphShowChildren					= function(doc, sParams){
		var oTab							= EEM6().Tabsheet.TabFromDocument(doc);
		if (NotNull(oTab)){
			//== We found the tab where the current graph is, so get the "/ShowChildren"
			//==	output and put it back on the same tab
			this._Graph("/ShowChildren", sParams, oTab.TabID);
		}else{
			alert("Could not show children, unable to find output tab.");
		}
	}
	this.GraphCallback						= function(){
		//== Show the tab where we will be drawing on
		EEM6().Tabsheet.TabShow(this.QueuedTabpage);
		//== Make the request to replace myself with the graph
		var oReq 				= new RequestObj(EEM6().Tabsheet.TabFrame(this.QueuedTabpage), this.QueuedCommand, this.QueuedParams, false);
		//== These requests (Graph/Table/Download) can take awhile, so give us extra time
		oReq.TimeoutSeconds					= TIMEOUT_SERVER_LONG;
		oReq.TimeoutHandler					= this._GraphTimeout;
		oReq.onLoad									= "EEM6().Reports.TabLoading = null;";
		EEM6().Session.AddRequest(oReq);
	}
	this._GraphTimeout						= function(oReq){
		var sMsg							= "The data set requested is too large and this request has timed out."
												+ "  Please reduce the size of the data request and try again."
												+ "  Sorry for the inconvenience."
		alert(sMsg);
	}
	this._Table								= function(sCommand, sParams, iTabPage){
		this.QueuedCommand					= sCommand;
		this.QueuedParams					= sParams;
		this.QueuedTabpage					= iTabPage;
		//== Set the table page to a "GraphLoading.html"
		//==	this should in turn call back to the this.GraphCallback() function
		EEM6().Tabsheet.TabSetCaption(iTabPage, "Loading...");
		EEM6().Tabsheet.TabSetSource(iTabPage, PATH_HTML + "GraphLoading.html");
	}
	this.Table								= function(GraphSetID){
		if (NotNull(GraphSetID)){
			//== Get the table for the GraphSet ID passed in
			this._Table("/TableFromChart", GraphSetID, TABPAGE_TABLE);
		}else{
			//== Generate a new graph and then the table
			if (this.ValidateData(RPT_ACTION_TABLE)){
				this.GraphReset(false);
				var sParams						= this.SettingsParams();
				this._Table("/Table", sParams, TABPAGE_TABLE);
			}
		}
	}
	this._Download							= function(sCommand, sParams){
		var sFrame							= "Popup=dialogHeight:180px; scroll:no; resizable:no; status:no;";
		var oReq 							= new RequestObj(sFrame, sCommand, sParams, true);
		EEM6().Session.AddRequest(oReq);
	}
	this.Download							= function(GraphSetID){
		if (NotNull(GraphSetID)){
			//== Get the download data for the GraphSet ID passed in
			this._Download("/DownloadSelect", GraphSetID);
		}else{
			//== Generate a new graph and then download the data
			if (this.ValidateData(RPT_ACTION_DOWNLOAD)){
				this.GraphReset(false);
				var sParams					= this.SettingsParams();
				this._Download("/DownloadSelect", sParams );
			}
		}
	}
	//== DownloadData								call either /DownloadCreate or /DownloadFromChart
	//==															depending upon whether or not we have a GraphSetID
	//==														This makes a call to return the data in the specified format to be
	//==															opened or saved to file
	this.DownloadData								= function(GraphSetID, sParams){
		var sCommand;
		if (GraphSetID.length > 0){
			sCommand										= "/DownloadFromChart";
			//== Add the GraphSetID to the param string
			sParams											= "&Graphset=" + GraphSetID + sParams;
		}else{
			sCommand										= "/DownloadCreate";
		}
		var oReq 											= new RequestObj(null, sCommand, sParams, false);
		oReq.CheckResults							= false;
		oReq.NoResult									= true;
		EEM6().Session.AddRequest(oReq);
	}
}
