using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using IndianHealthService.BMXNet.Ado;
using IndianHealthService.BMXNet.Services;
using IndianHealthService.BMXNet.Model;

namespace IndianHealthService.BMXNet
{  
    /// <summary>
    /// All server-side RPMS RPC calls are performed through this interface.  Each instance of RemoteSession corresponds to a single job (e.g. Cache process) on RPMS.  There is always one primary RemoteSession and potentially more when using RemoteSessionPool.  When the primary RemoteSession is closed all secondary pooled sessions are also closed and the server broker connection is terminated.
    /// </summary>
    public interface RemoteSession
    {
        #region General Properties
        /// <summary>
        /// BMX Broker's host address name or IP Address
        /// </summary>               
        String HostAddress { get; }

        /// <summary>
        /// Authenticated user associated with this remote session
        /// </summary>
        /// <example>
        /// this.StatusLabel.Text="Logged in: "+ aRemoteSession.User.Name;
        /// </example>
        /// /// <remarks>
        /// If there is a remoteSession user, it will be the same as the localSession User object
        /// </remarks>               
        User User { get; }

        /// <summary>
        /// The active AppContext (OPTION) of this remote session.
        /// </summary>
        /// <remarks>
        /// Normally the AppContext is set once, after logging into the BMX, with a
        /// single AppContext for the current applications.  The AppContext can also be set in every RPC call.  If the AppContext
        /// is the same as the currently set AppContext, the AppContext will not be re-set.
        /// </remarks>
        /// <example>
        /// The VEN namespace is for PCC+ and the example below would be used at the beginning
        /// of a PCC+ application.
        /// <code>
        /// aRemoteSession.AppContext = "VEN RPC";
        /// </code>
        /// </example>
        String AppContext { get; set; }

        #endregion

        #region Remote Procedure Call Services
        
        /// <summary>
        /// Calls a remote procedure on the RPMS server and returns the result as a String.
        /// </summary>
        /// <remarks>
        /// Presumes that the AppContext was set prior to the call.
        /// </remarks>
        /// <example>
        /// <code>
        /// ...
        /// this.RemoteSession.AppContext="VEN RPC";
        /// ...
        /// String asqThreadholds= this.RemoteSession.TransmitRPC("VEN ASQ GET DATA", this.Context.Patient.Ien);
        /// </code>                    
        /// </example>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <returns>The result of the RPC call</returns>
        String TransmitRPC(String rpcCommand, String rpcParameter);

        /// <summary>
        /// Calls a remote procedure on the RPMS server and returns the result as a String.
        /// </summary>
        /// <remarks>
        /// Use this for usage patterns where the AppContext is changed often and should be explicity set
        /// for each call and not implicitly through a prior invocation of this.RemoteSession.AppContext
        /// </remarks>
        /// <example>
        /// <code>
        /// ...
        /// this.RemoteSession.AppContext=;
        /// ...
        /// String asqThreadholds= this.RemoteSession.TransmitRPC("VEN ASQ GET DATA", this.Context.Patient.Ien,"VEN RPC");
        //  </code>                    
        /// </example>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <param name="aContext">The AppContext (OPTION) to be set prior to the call(</param>                
        /// <returns>The result of the RPC call</returns>
        String TransmitRPC(String rpcCommand, String rpcParameter, String aContext);


        /// <summary>
        /// Calls a remote procedure on the RPMS server and returns the result as a String.  If there are any exceptions a
        /// colon delimited string in the format Exception:Message is returned.
        /// </summary>
        /// <remarks>
        /// Presumes that the AppContext was set prior to the call.
        /// </remarks>
        /// <example>
        /// <code>
        /// ...
        /// this.RemoteSession.AppContext="VEN RPC";
        /// ...
        /// String asqThreadholds= this.RemoteSession.SafelyTransmitRPC("VEN ASQ GET DATA", this.Context.Patient.Ien);
        ///  </code>                    
        /// </example>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <returns>The result of the RPC call.  If there are any exceptions a colon delimited string in the format Exception:Message is returned.</returns>
        String SafelyTransmitRPC(String rpcCommand, String rpcParameter);


        /// <summary>
        /// Calls a remote procedure on the RPMS server and returns the result as a String.  If there are any exceptions a
        /// colon delimited string in the format Exception:Message is returned.
        /// </summary>
        /// <remarks>
        /// Presumes that the AppContext was set prior to the call.
        /// </remarks>
        /// <example>
        /// <code>
        /// ...
        /// this.RemoteSession.AppContext="VEN RPC";
        /// ...
        /// String asqThreadholds= this.RemoteSession.SafelyTransmitRPC("VEN ASQ GET DATA", this.Context.Patient.Ien);
        ///  </code>                    
        /// </example>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <param name="aContext">The AppContext (OPTION) to be set prior to the call(</param>                
        /// <returns>The result of the RPC call.  If there are any exceptions a colon delimited string in the format Exception:Message is returned.</returns>
        String SafelyTransmitRPC(String rpcCommand, String rpcParameter, String context);
        
        #endregion
        // ADO Services

        #region ADO.NET Table Services

        /// <summary>
        /// 
        /// <example>
        /// 
        /// <code>
        /// 
        /// this.Context.Visit.Create();
        /// if (this.Context.Visit.IsStub)
        /// {
        ///     if (!this.Context.Visit.Create())
        ///     {
        ///         return false;
        ///     }
        /// }
        /// this.RemoteSession.SaveChanges(this.ScoreTable);
        /// </code>
        /// </example>
        /// </summary>
        /// <param name="aDataTable"></param>
        /// <returns></returns>
        bool SaveChanges(DataTable aDataTable);


        /// <summary>
        /// Calling a Custom Remote Procedure call (RPC) registered in VA FileMan’s REMOTE PROCEDURE file that results in a DataTable.  You must design your remote procedure’s M routine to build its result its data in the specific format described later in this document.  
        /// </summary>
        /// <param name="aCommand">The co        /// </param>
        /// <remarks>
        /// Normally the AppContext is set once, after logging into the BMX, with a
        /// single AppContext for the current applications or specified in every RPC call.  
        /// </remarks>
        /// <example>
        /// The VEN namespace is for PCC+ and the example below would be used at the beginning
        /// of a PCC+ application.
        /// <code>
        /// aRemoteSession.AppContext = "VEN RPC";
        /// </code>
        /// The M code for a simple remote procedure call (BMX PATIENT DEMO) with two parameters to return a list of patients.  See the following example. Note the inclusion of an error trap in the routine; BMXNet RPC routines must contain a functional error trap.       
        /// <code>
        /// Figure 5 2 shows the M code for a simple remote procedure call (BMX PATIENT DEMO) with two parameters to return a list of patients.  See the following example. Note the inclusion of an error trap in the routine; BMXNet RPC routines must contain a functional error trap.
        /// PDEMO(BMXY,BMXPAT,BMXCOUNT)	;EP
        /// 	;This simple RPC demonstrates how to format data
        /// ;for the BMXNet ADO.NET data provider
        /// ;
        /// ;Returns a maximum of BMXCOUNT records from the
        /// ;VA PATIENT file whose names begin with BMXPAT
        /// ;
        /// N BMXI,BMXD,BMXC,BMXNODE,BMXDOB
        /// ;
        /// ; BMXY is passed in by reference.  Set it to 
        /// ;the value of the variable in which we will return our data:
        /// S BMXY="^TMP(BMX,"_$J_")"
        /// ;
        /// ;The first subnode of the data global contains the column header information
        /// ;in the form "txxxxxCOLUMN1NAME^txxxxxCOLUMN2NAME"_$C(30)
        /// ;where t is the column data type:
        /// ;	T for text
        /// ;	I for integer
        /// ;	N for floating point number
        /// ;	D for date/time.
        /// ;xxxxx is the length of the column in characters.
        /// ;
        /// S BMXI=0,BMXC=0
        /// S ^ TMP(BMX,$J,BMXI)="T00030NAME^T00010SEX^D00020DOB"_$C(30)
        /// ;
        /// ;You MUST set an error trap:
        /// S X="PDERR^BMXRPC6",@^%ZOSF("TRAP")
        /// ;
        /// ;Strip CR, LF, TAB from BMXCOUNT parameter
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(13),"")
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(10),"")
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(9),"")
        /// ;
        /// ;Iterate through the global and set the data nodes:
        /// S:BMXPAT="" BMXPAT="A"
        /// S BMXPAT=$O(^DPT("B",BMXPAT),-1)
        /// S BMXD=0
        /// F  S BMXPAT=$O(^DPT("B",BMXPAT)) Q:BMXPAT=""  S BMXD=$O(^DPT("B",BMXPAT,0)) I +BMXD  S BMXC=BMXC+1 Q:(BMXCOUNT)BMXC BMXCOUNT)  D
        /// . Q:'$D(^DPT(BMXD,0))
        /// . S BMXI=BMXI+1
        /// . S BMXNODE=^DPT(BMXD,0)
        /// . ;Convert the DOB from FM date to external form
        /// . S Y=$P(BMXNODE,U,3)
        /// . I +Y X ^DD("DD")
        /// . S BMXDOB=Y
        /// . ;The data node fields are in the same order as the column header, i.e. NAME^SEX^DOB
        /// . ;and terminated with a $C(30)
        /// . S ^ TMP(BMX,$J,BMXI)=$P(BMXNODE,U)_U_$P(BMXNODE,U,2)_U_BMXDOB_$C(30)
        /// ;
        /// ;After all the data nodes have been set, set the final node to $C(31) to indicate
        /// ;the end of the recordset
        /// S BMXI=BMXI+1
        /// S ^ TMP(BMX,$J,BMXI)=$C(31)
        /// Q
        /// ;
        /// PDERR	;Error trap for PDEMO
        /// ;
        /// S ^ TMP(BMX,$J,BMXI+1)=$C(31)
        /// Q
        /// </code>
        /// Register as an RPC
        /// <para>
        /// NAME: BMX DEMO                          TAG: PDEMO
        /// ROUTINE: BMXRPC6                     RETURN VALUE TYPE: GLOBAL ARRAY
        /// </para>
        /// Call using a RemoteSession
        /// <code>
        /// DataTable demoTable=aRemoteSession.TableFromCommand("BMX DEMO^S^10");
        /// </code>
        /// </example> 
        /// <param name="aCommand">The name of the RPC </param>
        /// <returns>The resulting DataTable</returns>
        DataTable TableFromCommand(String aCommand);


        /// <summary>
        /// Calling a Custom Remote Procedure call (RPC) registered in VA FileMan’s REMOTE PROCEDURE file that results in a DataTable.  You must design your remote procedure’s M routine to build its result its data in the specific format described later in this document.  
        /// </summary>
        /// <param name="aCommand">The co        /// </param>
        /// <remarks>
        /// Normally the AppContext is set once, after logging into the BMX, with a
        /// single AppContext for the current applications or specified in every RPC call.  
        /// </remarks>
        /// <example>
        /// The VEN namespace is for PCC+ and the example below would be used at the beginning
        /// of a PCC+ application.
        /// <code>
        /// aRemoteSession.AppContext = "VEN RPC";
        /// </code>
        /// The M code for a simple remote procedure call (BMX PATIENT DEMO) with two parameters to return a list of patients.  See the following example. Note the inclusion of an error trap in the routine; BMXNet RPC routines must contain a functional error trap.       
        /// <code>
        /// Figure 5 2 shows the M code for a simple remote procedure call (BMX PATIENT DEMO) with two parameters to return a list of patients.  See the following example. Note the inclusion of an error trap in the routine; BMXNet RPC routines must contain a functional error trap.
        /// PDEMO(BMXY,BMXPAT,BMXCOUNT)	;EP
        /// 	;This simple RPC demonstrates how to format data
        /// ;for the BMXNet ADO.NET data provider
        /// ;
        /// ;Returns a maximum of BMXCOUNT records from the
        /// ;VA PATIENT file whose names begin with BMXPAT
        /// ;
        /// N BMXI,BMXD,BMXC,BMXNODE,BMXDOB
        /// ;
        /// ; BMXY is passed in by reference.  Set it to 
        /// ;the value of the variable in which we will return our data:
        /// S BMXY="^TMP(BMX,"_$J_")"
        /// ;
        /// ;The first subnode of the data global contains the column header information
        /// ;in the form "txxxxxCOLUMN1NAME^txxxxxCOLUMN2NAME"_$C(30)
        /// ;where t is the column data type:
        /// ;	T for text
        /// ;	I for integer
        /// ;	N for floating point number
        /// ;	D for date/time.
        /// ;xxxxx is the length of the column in characters.
        /// ;
        /// S BMXI=0,BMXC=0
        /// S ^ TMP(BMX,$J,BMXI)="T00030NAME^T00010SEX^D00020DOB"_$C(30)
        /// ;
        /// ;You MUST set an error trap:
        /// S X="PDERR^BMXRPC6",@^%ZOSF("TRAP")
        /// ;
        /// ;Strip CR, LF, TAB from BMXCOUNT parameter
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(13),"")
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(10),"")
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(9),"")
        /// ;
        /// ;Iterate through the global and set the data nodes:
        /// S:BMXPAT="" BMXPAT="A"
        /// S BMXPAT=$O(^DPT("B",BMXPAT),-1)
        /// S BMXD=0
        /// F  S BMXPAT=$O(^DPT("B",BMXPAT)) Q:BMXPAT=""  S BMXD=$O(^DPT("B",BMXPAT,0)) I +BMXD  S BMXC=BMXC+1 Q:(BMXCOUNT)BMXC BMXCOUNT)  D
        /// . Q:'$D(^DPT(BMXD,0))
        /// . S BMXI=BMXI+1
        /// . S BMXNODE=^DPT(BMXD,0)
        /// . ;Convert the DOB from FM date to external form
        /// . S Y=$P(BMXNODE,U,3)
        /// . I +Y X ^DD("DD")
        /// . S BMXDOB=Y
        /// . ;The data node fields are in the same order as the column header, i.e. NAME^SEX^DOB
        /// . ;and terminated with a $C(30)
        /// . S ^ TMP(BMX,$J,BMXI)=$P(BMXNODE,U)_U_$P(BMXNODE,U,2)_U_BMXDOB_$C(30)
        /// ;
        /// ;After all the data nodes have been set, set the final node to $C(31) to indicate
        /// ;the end of the recordset
        /// S BMXI=BMXI+1
        /// S ^ TMP(BMX,$J,BMXI)=$C(31)
        /// Q
        /// ;
        /// PDERR	;Error trap for PDEMO
        /// ;
        /// S ^ TMP(BMX,$J,BMXI+1)=$C(31)
        /// Q
        /// </code>
        /// Register as an RPC
        /// <para>
        /// NAME: BMX DEMO                          TAG: PDEMO
        /// ROUTINE: BMXRPC6                     RETURN VALUE TYPE: GLOBAL ARRAY
        /// </para>
        /// Call using a RemoteSession
        /// <code>
        /// DataTable demoTable=aRemoteSession.TableFromCommand("BMX DEMO^S^10");
        /// </code>
        /// </example> 
        /// <param name="aCommand">The name of the RPC </param>
        /// <param name="aContext">The AppContext to set prior to the call</param>
        /// <returns>The resulting DataTable</returns>
        DataTable TableFromCommand(String aCommand, String aContext);


        /// <summary>
        /// Calling a Custom Remote Procedure call (RPC) registered in VA FileMan’s REMOTE PROCEDURE file that results in a DataTable.  You must design your remote procedure’s M routine to build its result its data in the specific format described later in this document.  
        /// </summary>
        /// <param name="aCommand">The co        /// </param>
        /// <remarks>
        /// Normally the AppContext is set once, after logging into the BMX, with a
        /// single AppContext for the current applications or specified in every RPC call.  
        /// </remarks>
        /// <example>
        /// The VEN namespace is for PCC+ and the example below would be used at the beginning
        /// of a PCC+ application.
        /// <code>
        /// aRemoteSession.AppContext = "VEN RPC";
        /// </code>
        /// The M code for a simple remote procedure call (BMX PATIENT DEMO) with two parameters to return a list of patients.  See the following example. Note the inclusion of an error trap in the routine; BMXNet RPC routines must contain a functional error trap.       
        /// <code>
        /// Figure 5 2 shows the M code for a simple remote procedure call (BMX PATIENT DEMO) with two parameters to return a list of patients.  See the following example. Note the inclusion of an error trap in the routine; BMXNet RPC routines must contain a functional error trap.
        /// PDEMO(BMXY,BMXPAT,BMXCOUNT)	;EP
        /// 	;This simple RPC demonstrates how to format data
        /// ;for the BMXNet ADO.NET data provider
        /// ;
        /// ;Returns a maximum of BMXCOUNT records from the
        /// ;VA PATIENT file whose names begin with BMXPAT
        /// ;
        /// N BMXI,BMXD,BMXC,BMXNODE,BMXDOB
        /// ;
        /// ; BMXY is passed in by reference.  Set it to 
        /// ;the value of the variable in which we will return our data:
        /// S BMXY="^TMP(BMX,"_$J_")"
        /// ;
        /// ;The first subnode of the data global contains the column header information
        /// ;in the form "txxxxxCOLUMN1NAME^txxxxxCOLUMN2NAME"_$C(30)
        /// ;where t is the column data type:
        /// ;	T for text
        /// ;	I for integer
        /// ;	N for floating point number
        /// ;	D for date/time.
        /// ;xxxxx is the length of the column in characters.
        /// ;
        /// S BMXI=0,BMXC=0
        /// S ^ TMP(BMX,$J,BMXI)="T00030NAME^T00010SEX^D00020DOB"_$C(30)
        /// ;
        /// ;You MUST set an error trap:
        /// S X="PDERR^BMXRPC6",@^%ZOSF("TRAP")
        /// ;
        /// ;Strip CR, LF, TAB from BMXCOUNT parameter
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(13),"")
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(10),"")
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(9),"")
        /// ;
        /// ;Iterate through the global and set the data nodes:
        /// S:BMXPAT="" BMXPAT="A"
        /// S BMXPAT=$O(^DPT("B",BMXPAT),-1)
        /// S BMXD=0
        /// F  S BMXPAT=$O(^DPT("B",BMXPAT)) Q:BMXPAT=""  S BMXD=$O(^DPT("B",BMXPAT,0)) I +BMXD  S BMXC=BMXC+1 Q:(BMXCOUNT)BMXC BMXCOUNT)  D
        /// . Q:'$D(^DPT(BMXD,0))
        /// . S BMXI=BMXI+1
        /// . S BMXNODE=^DPT(BMXD,0)
        /// . ;Convert the DOB from FM date to external form
        /// . S Y=$P(BMXNODE,U,3)
        /// . I +Y X ^DD("DD")
        /// . S BMXDOB=Y
        /// . ;The data node fields are in the same order as the column header, i.e. NAME^SEX^DOB
        /// . ;and terminated with a $C(30)
        /// . S ^ TMP(BMX,$J,BMXI)=$P(BMXNODE,U)_U_$P(BMXNODE,U,2)_U_BMXDOB_$C(30)
        /// ;
        /// ;After all the data nodes have been set, set the final node to $C(31) to indicate
        /// ;the end of the recordset
        /// S BMXI=BMXI+1
        /// S ^ TMP(BMX,$J,BMXI)=$C(31)
        /// Q
        /// ;
        /// PDERR	;Error trap for PDEMO
        /// ;
        /// S ^ TMP(BMX,$J,BMXI+1)=$C(31)
        /// Q
        /// </code>
        /// Register as an RPC
        /// <para>
        /// NAME: BMX DEMO                          TAG: PDEMO
        /// ROUTINE: BMXRPC6                     RETURN VALUE TYPE: GLOBAL ARRAY
        /// </para>
        /// Call using a RemoteSession
        /// <code>
        /// DataTable demoTable=aRemoteSession.TableFromCommand("BMX DEMO^S^10");
        /// </code>
        /// </example> 
        /// <param name="aCommand">The name of the RPC </param>
        /// <param name="aDataSet">The DataSet to be populated with a resulting DataTable named aTableNAme</param>
        /// <param name="aTableName">The name of the DataTable in the DataSet to populate or to create</param>
        /// <returns>The resulting DataTable</returns>
        DataTable TableFromCommand(String aCommand, DataSet aDataSet, String aTableName);


        /// <summary>
        /// Calling a Custom Remote Procedure call (RPC) registered in VA FileMan’s REMOTE PROCEDURE file that results in a DataTable.  You must design your remote procedure’s M routine to build its result its data in the specific format described later in this document.  
        /// </summary>
        /// <param name="aCommand">The co        /// </param>
        /// <remarks>
        /// Normally the AppContext is set once, after logging into the BMX, with a
        /// single AppContext for the current applications or specified in every RPC call.  
        /// </remarks>
        /// <example>
        /// The VEN namespace is for PCC+ and the example below would be used at the beginning
        /// of a PCC+ application.
        /// <code>
        /// aRemoteSession.AppContext = "VEN RPC";
        /// </code>
        /// The M code for a simple remote procedure call (BMX PATIENT DEMO) with two parameters to return a list of patients.  See the following example. Note the inclusion of an error trap in the routine; BMXNet RPC routines must contain a functional error trap.       
        /// <code>
        /// Figure 5 2 shows the M code for a simple remote procedure call (BMX PATIENT DEMO) with two parameters to return a list of patients.  See the following example. Note the inclusion of an error trap in the routine; BMXNet RPC routines must contain a functional error trap.
        /// PDEMO(BMXY,BMXPAT,BMXCOUNT)	;EP
        /// 	;This simple RPC demonstrates how to format data
        /// ;for the BMXNet ADO.NET data provider
        /// ;
        /// ;Returns a maximum of BMXCOUNT records from the
        /// ;VA PATIENT file whose names begin with BMXPAT
        /// ;
        /// N BMXI,BMXD,BMXC,BMXNODE,BMXDOB
        /// ;
        /// ; BMXY is passed in by reference.  Set it to 
        /// ;the value of the variable in which we will return our data:
        /// S BMXY="^TMP(BMX,"_$J_")"
        /// ;
        /// ;The first subnode of the data global contains the column header information
        /// ;in the form "txxxxxCOLUMN1NAME^txxxxxCOLUMN2NAME"_$C(30)
        /// ;where t is the column data type:
        /// ;	T for text
        /// ;	I for integer
        /// ;	N for floating point number
        /// ;	D for date/time.
        /// ;xxxxx is the length of the column in characters.
        /// ;
        /// S BMXI=0,BMXC=0
        /// S ^ TMP(BMX,$J,BMXI)="T00030NAME^T00010SEX^D00020DOB"_$C(30)
        /// ;
        /// ;You MUST set an error trap:
        /// S X="PDERR^BMXRPC6",@^%ZOSF("TRAP")
        /// ;
        /// ;Strip CR, LF, TAB from BMXCOUNT parameter
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(13),"")
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(10),"")
        /// S BMXCOUNT=$TR(BMXCOUNT,$C(9),"")
        /// ;
        /// ;Iterate through the global and set the data nodes:
        /// S:BMXPAT="" BMXPAT="A"
        /// S BMXPAT=$O(^DPT("B",BMXPAT),-1)
        /// S BMXD=0
        /// F  S BMXPAT=$O(^DPT("B",BMXPAT)) Q:BMXPAT=""  S BMXD=$O(^DPT("B",BMXPAT,0)) I +BMXD  S BMXC=BMXC+1 Q:(BMXCOUNT)BMXC BMXCOUNT)  D
        /// . Q:'$D(^DPT(BMXD,0))
        /// . S BMXI=BMXI+1
        /// . S BMXNODE=^DPT(BMXD,0)
        /// . ;Convert the DOB from FM date to external form
        /// . S Y=$P(BMXNODE,U,3)
        /// . I +Y X ^DD("DD")
        /// . S BMXDOB=Y
        /// . ;The data node fields are in the same order as the column header, i.e. NAME^SEX^DOB
        /// . ;and terminated with a $C(30)
        /// . S ^ TMP(BMX,$J,BMXI)=$P(BMXNODE,U)_U_$P(BMXNODE,U,2)_U_BMXDOB_$C(30)
        /// ;
        /// ;After all the data nodes have been set, set the final node to $C(31) to indicate
        /// ;the end of the recordset
        /// S BMXI=BMXI+1
        /// S ^ TMP(BMX,$J,BMXI)=$C(31)
        /// Q
        /// ;
        /// PDERR	;Error trap for PDEMO
        /// ;
        /// S ^ TMP(BMX,$J,BMXI+1)=$C(31)
        /// Q
        /// </code>
        /// Register as an RPC
        /// <para>
        /// NAME: BMX DEMO                          TAG: PDEMO
        /// ROUTINE: BMXRPC6                     RETURN VALUE TYPE: GLOBAL ARRAY
        /// </para>
        /// Call using a RemoteSession
        /// <code>
        /// DataTable demoTable=aRemoteSession.TableFromCommand("BMX DEMO^S^10");
        /// </code>
        /// </example> 
        /// <param name="aCommand">The name of the RPC </param>
        /// <param name="aDataSet">The DataSet to be populated with a resulting DataTable named aTableNAme</param>
        /// <param name="aTableName">The name of the DataTable in the DataSet to populate or to create</param>
        /// <param name="aContext">The AppContext to set prior to the call</param>
        /// <returns>The resulting DataTable</returns>
        DataTable TableFromCommand(String aCommand, DataSet aDataSet, String aTableName, String aContext);



        DataTable TableFromSQL(String anSqlStatement);
        DataTable TableFromSQL(String anSqlStatement, String aContext);
        DataTable TableFromSQL(String anSqlStatement, DataSet aDataSet, String aTableName);

        /// <summary>
        /// SELECT VA_PATIENT.NAME, VA_PATIENT.SSN, PATIENT.CURRENT_COMMUNITY FROM VA_PATIENT, PATIENT WHERE VA_PATIENT.BMXIEN =* INTERNAL[PATIENT.NAME] AND VA_PATIENT.NAME LIKE 'DEMO%' AND VA_PATIENT.AGE BETWEEN 15 AND 24 SHOWPLAN
         /// </summary>
        /// <param name="anSqlStatement"></param>
        /// <param name="aDataSet"></param>
        /// <param name="aTableName"></param>
        /// <param name="aContext"></param>
        /// <returns></returns>
        DataTable TableFromSQL(String anSqlStatement, DataSet aDataSet, String aTableName, String aContext);

        /// <summary>
        /// TabletFromRpc is a double-dispatch method that is used by some developers.  Developers create an RPC
        /// call the returns a properly format BMX command (custom or BMX SS ADO) that is then transmitted back to RPMS to retrieve the Data Table.
        /// </summary>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <returns>The resulting DataTable</returns>
        DataTable TableFromRPC(String rpcCommand, String rpcParameter);

        /// <summary>
        /// TabletFromRpc is a double-dispatch method that is used by some developers.  Developers create an RPC
        /// call the returns a properly format BMX command (custom or BMX SS ADO) that is then transmitted back to RPMS to retrieve the Data Table.
        /// </summary>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <param name="aContext">The AppContext to set prior to the call</param>
        /// <returns>The resulting DataTable</returns>
        DataTable TableFromRPC(String rpcCommand, String rpcParameter, String aContext);
 
        /// <summary>
        /// TabletFromRpc is a double-dispatch method that is used by some developers.  Developers create an RPC
        /// call the returns a properly format BMX command (custom or BMX SS ADO) that is then transmitted back to RPMS to retrieve the Data Table.
        /// </summary>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <param name="aDataSet">The DataSet to be populated with a resulting DataTable named aTableNAme</param>
        /// <param name="aTableName">The name of the DataTable in the DataSet to populate or to create</param>
        /// <returns>The resulting DataTable</returns>
        DataTable TableFromRPC(String rpcCommand, String rpcParameter, DataSet aDataSet, String aTableName);
        
        /// <summary>
        /// TabletFromRpc is a double-dispatch method that is used by some developers.  Developers create an RPC
        /// call the returns a properly format BMX command (custom or BMX SS ADO) that is then transmitted back to RPMS to retrieve the Data Table.
        /// </summary>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <param name="aDataSet">The DataSet to be populated with a resulting DataTable named aTableNAme</param>
        /// <param name="aTableName">The name of the DataTable in the DataSet to populate or to create</param>
        /// <param name="aContext">The AppContext to set prior to the call</param>
        /// <returns>The resulting DataTable</returns>
        DataTable TableFromRPC(String rpcCommand, String rpcParameter, DataSet aDataSet, String aTableName, String context);


        /// <summary>
        /// Same as the corresponding TableFromCommand call except a DataTableFuture is returned.  See <see cref="DataTableFuture "/> on how to use a 'Future
        /// </summary>
        /// <param name="aCommand">The name of the RPC </param>
        /// <returns>A DataTableFuture</returns>
        DataTableFuture AsyncTableFromCommand(String aCommand);
  
        /// <summary>
        /// Same as the corresponding TableFromCommand call except a DataTableFuture is returned.  See <see cref="DataTableFuture "/> on how to use a 'Future
        /// </summary>
        /// <param name="aCommand">The name of the RPC </param>
        /// <param name="aContext">The AppContext to set prior to the call</param>
        /// <returns>A DataTableFuture</returns>
        DataTableFuture AsyncTableFromCommand(String aCommand, String aContext);

        /// <summary>
        /// Same as the corresponding TableFromCommand call except a DataTableFuture is returned.  See <see cref="DataTableFuture "/> on how to use a 'Future
        /// </summary>
        /// <param name="aCommand">The name of the RPC </param>
        /// <param name="aDataSet">The DataSet to be populated with a resulting DataTable named aTableNAme</param>
        /// <param name="aTableName">The name of the DataTable in the DataSet to populate or to create</param>
        /// <returns>A DataTableFuture</returns>
        DataTableFuture AsyncTableFromCommand(String aCommand, DataSet aDataSet, String aTableName);

        /// <summary>
        /// Same as the corresponding TableFromCommand call except a DataTableFuture is returned.  See <see cref="DataTableFuture "/> on how to use a 'Future
        /// </summary>
        /// <param name="aCommand">The name of the RPC </param>
        /// <param name="aDataSet">The DataSet to be populated with a resulting DataTable named aTableNAme</param>
        /// <param name="aTableName">The name of the DataTable in the DataSet to populate or to create</param>
        /// <param name="aContext">The AppContext to set prior to the call</param>
        /// <returns>A DataTableFuture</returns>
        DataTableFuture AsyncTableFromCommand(String aCommand, DataSet aDataSet, String aTableName, String aContext);

        DataTableFuture AsyncTableFromSQL(String sql);
        DataTableFuture AsyncTableFromSQL(String sql, String aContext);
        DataTableFuture AsyncTableFromSQL(String sql, DataSet aDataSet, String aTableName);
        DataTableFuture AsyncTableFromSQL(String sql, DataSet aDataSet, String aTableName, String aContext);

        /// <summary>
        /// Same as the corresponding TableFromRPC call except a DataTableFuture is returned.  See <see cref="DataTableFuture "/> on how to use a 'Future
        /// </summary>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <returns>A DataTableFuture</returns>
        DataTableFuture AsyncTableFromRPC(String rpcCommand, String rpcParameter);
  
        /// <summary>
        /// Same as the corresponding TableFromRPC call except a DataTableFuture is returned.  See <see cref="DataTableFuture "/> on how to use a 'Future
        /// </summary>
        /// <param name="rpcCommand"></param>
        /// <param name="rpcParameter"></param>
        /// <param name="aContext"></param>
        /// <returns>A DataTableFuture</returns>
        DataTableFuture AsyncTableFromRPC(String rpcCommand, String rpcParameter, String context);
        
        /// <summary>
        /// Same as the corresponding TableFromRPC call except a DataTableFuture is returned.  See <see cref="DataTableFuture "/> on how to use a 'Future
        /// </summary>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <param name="aDataSet">The DataSet to be populated with a resulting DataTable named aTableNAme</param>
        /// <param name="aTableName">The name of the DataTable in the DataSet to populate or to create</param>
        /// <returns>A DataTableFuture</returns>
        DataTableFuture AsyncTableFromRPC(String rpcCommand, String rpcParameter, DataSet aDataSet, String aTableName);

        /// <summary>
        /// Same as the corresponding TableFromRPC call except a DataTableFuture is returned.  See <see cref="DataTableFuture "/> on how to use a 'Future
        /// </summary>
        /// <param name="rpcCommand">The remote procedure call name </param>
        /// <param name="rpcParameter">A carrot ^ delimited string of input parameters</param>
        /// <param name="aDataSet">The DataSet to be populated with a resulting DataTable named aTableNAme</param>
        /// <param name="aTableName">The name of the DataTable in the DataSet to populate or to create</param>
        /// <param name="aContext">The AppContext to set prior to the call</param>
        /// <returns>A DataTableFuture</returns>
        DataTableFuture AsyncTableFromRPC(String rpcCommand, String rpcParameter, DataSet aDataSet, String aTableName, String aContext);

        /// <summary>
        /// Answer True if aString is a standard BMX ADO SS command that uses the BMX ADO SCHEMA files
        /// </summary>
        /// <remarks>
        /// This is mostly used by the framework but exposed for potential use.
        /// </remarks>
        /// <param name="aString">The command to be examined</param>
        /// <returns>True if it complied, otherwise false</returns>
        bool IsBmxAdoCommand(String aString); 
        #endregion

  
        #region Event Services

        /// <summary>
        /// Access the session's RemoteEventServices service provider to configure receiving
        /// remote events and to source new events.
        /// </summary>
        RemoteEventService EventServices { get; }

        #endregion


        #region Debugging
        /// <summary>
        /// Job number of server-side Cache/MDB process.  Very useful for debugging.
        /// </summary>
        String Job { get; }

        /// <summary>
        /// String describing RPC call and input parameters of last non-DataTable RPC call
        /// </summary>
        String DebugLastRpcSignature { get; }
        
        /// <summary>
        /// String value of last successful non-DataTable RPC call
        /// </summary>
        String RpcResult { get; }
        
        /// <summary>
        /// String value of last successful non-DataTable RPC call
        /// </summary>
        String DebugLastRpcResult { get; }

        /// <summary>
        /// Last DataTable retrieved by non-async calls
        /// </summary>
        DataTable DebugLastTableResult { get; }

        Log Log { get; } 

        #endregion
        
        #region Lifecycle
        
        /// <summary>
        /// The networking data receive timeout (in milliseconds).  This value can be changed if the developer finds it neccessary
        /// to extend the time after login.
        /// </summary>
        /// <remarks>
        /// Only applicable for the WinFramework
        /// </remarks>
        int ReceiveTimeout { get; set; }

        /// <summary>
        /// The networking data send timeout (in milliseconds).  This value can be changed if the developer finds it neccessary
        /// to extend the time after login but normally the send timeout should be kept short unless network conditions are poor.
        /// </summary>
        /// <remarks>
        /// Only applicable for the WinFramework
        /// </remarks>
        int SendTimeout { get; set; }

        /// <summary>
        /// The primary session has the unique in that it holds the authenication privileges for all sessions.  If you close the primary session, then all will close.
        /// </summary>
        bool IsPrimary { get; }

        /// <summary>
        /// When done with session it should be closed.  Once closed it is unusable.
        /// </summary>
        /// <remarks>Internally the session is a lightweight object and when using multiple sessions internal RPMS connections are pooled .  Close sessions when finished</remarks>
        /// <remarks>Closing the primary session closes all sessions and shuts down the RPMS connection</remarks>
        void Close(); 
        #endregion
    }
   
}
