Function Service_Manager_Events(CtrlEntId, Event, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)
/***********************************************************************************************************************

    This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
    permission from Infineon.

    Name        :   Service_Manager_Events

    Description :   This function acts as a commuter module for all events related to this window.

    Notes       :   Commuter Modules are automatically called from the Promoted_Events function which is called by the
                    application-specific promoted event handler. This makes it possible to add QuickEvents that need to
                    execute Basic+ logic without having use the Form Designer to make the association, although this is
                    limited to the events which are currently promoted.

                    If the form needs to call the commuter module directly then the QuickEvent parameters should be
                    formatted like this:

                        '@SELF','@EVENT',['@PARAM1','@PARAMx']

    Parameters  :
        CtrlEntId   [in] -- The fully qualified name of the control calling the promoted event
        Event       [in] -- The event being executed. See the Notes section regarding "PRE" events
        Param1-15   [in] -- Additional event parameter holders
        EventFlow  [out] -- Set to 1 or 0 so the calling event knows whether or not to chain forward. See comments in
                            EVENT_SETUP insert

    History     :   (Date, Initials, Notes)
        07/26/17    dmb     Created initial commuter module.
        07/13/18    dmb     Change protocol from calling service code directly to calling MCP.
        05/27/20    djs     Updated commuter module to read and write the last run datetime to the service record.

***********************************************************************************************************************/

#pragma precomp SRP_PreCompiler
#Window SERVICE_MANAGER

$insert APP_INSERTS
$insert EVENT_SETUP
$insert SERVICES_EQUATES
$insert MSG_EQUATES

Equate ActiveColor$     to 'Vertical(Gradient(Green L=70, Green L=30), Border(3DS))'
Equate DeactiveColor$   to 'Vertical(Gradient(Red L=70, Red L=30), Border(3DS))'

Common /ServiceManager/ TCPServerSettings@

Declare subroutine  SRP_TcpClient, Yield, Database_Services
Declare function    SRP_TcpClient, Database_Services, Environment_Services, Service_Services

SubclassInfo    = Form_Services('FindSubclassControl')
Subclass        = SubclassInfo<1>

// Update the arguments so that the OpenInsight OLE event will treate the ActiveX event as a native event handler.
If Event EQ 'OLE' then
    Transfer Event to OIEvent
    Transfer Param1 to Event
    Transfer Param2 to Param1
    Transfer Param3 to Param2
    Transfer Param4 to Param3
    Transfer Param5 to Param4
    Transfer Param6 to Param5
    Transfer Param7 to Param6
    Transfer Param8 to Param7
end

GoToEvent Event for CtrlEntID

Return EventFlow else EVENT_CONTINUE$


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Events
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Event WINDOW.CREATE(CreateParam)

    Server      = Environment_Services('GetServer')
    Text        = Get_Property(@Window, 'TEXT')
    Text       := ' - ' : Server
    Set_Property(@Window, 'TEXT', Text)

    GoSub Setup_OLE_Controls

    // Kick of the first TIMER event. Allow it to be self-triggering so TIMER events don't stack on top of each other.
    Set_Property(@Window, 'TIMER', 0 : @FM : 1000)

    SRP_Show_Window(@Window, '', 'R', 'B', 1, '', False$, False$)

end event


Event WINDOW.CLOSE(CancelFlag)

    // Turn off the TIMER event in case it is still triggered.
    Set_Property(@Window, 'TIMER', 0)
    Set_Property('SYSTEM','IDLEPROC','ADIOS')

end event


Event WINDOW.TIMER()
    
    ServiceList = Get_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.ColumnData[1]')
    If ServiceList NE '' then
        For Each Service in ServiceList using @VM setting vPos
            ServiceDetail   = Service_Services('GetService', Service)
            Procedures      = ServiceDetail<SERVICES.PROCEDURES$>
            Arguments       = ServiceDetail<SERVICES.ARGUMENTS$>
            For Each Procedure in Procedures using @VM setting procPos
                If Procedure[-9, 9] _EQC '_SERVICES' then Procedure[-9, 9] = ''
                Command     = 'RUN MCP ' : Quote(Procedure)
                Arguments   = Arguments<0, procPos>
                If Arguments NE '' then
                    For Each Argument in Arguments using ','
                        Argument    = Trim(Argument)
                        If IndexC(Argument, '%Date%', 1) then
                            // Using the Date token. Convert to current date and apply an date modifiers
                            Modifier    = Argument
                            Convert @Upper_Case to @Lower_Case in Modifier
                            Swap '%date%' with '' in Modifier
                            Modifier    = Trim(Modifier)
                            If Index(Modifier, '-', 1) then
                                Convert '- ' to '' in Modifier
                                Modifier    = Neg(Modifier)
                            end else
                                Convert '+ ' to '' in Modifier
                                Modifier    = Neg(Modifier)
                            end
                            If Not(Num(Modifier)) then Modifier = ''
                            Argument    = Date() + Modifier
                        end
                        Command    := ', ' : Quote(Argument)
                    Next Argument
                end
            Next Procedure

            // Check to see if this service is active. Use the color of the active button to verify.
            CellType    = Get_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellType[7;' : vPos : ']')
            Active      = CellType<3> EQ ActiveColor$

            // If the service is active and this service has a command, check to see if it is time to call it.
            If (Active EQ True$) AND (Command NE '') then
                Cycle           = Get_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[2;' : vPos : ']')
                LastRun         = OConv(ServiceDetail<SERVICES.LAST_RUN_DTM$>, 'DT2/^HS')
                LastDate        = Iconv(LastRun[1, ' '], 'D')
                LastTime        = Iconv(LastRun[Col2() + 1, ' '], 'MT')
                LastSeconds     = (LastDate * (24 * 60 * 60)) + LastTime
                CurrentSeconds  = (Date() * (24 * 60 * 60)) + Time()
                Difference      = CurrentSeconds - LastSeconds
                If Num(Cycle) then
                    // Cycle contains the number of seconds this service runs in a loop.
                    If Difference GE Cycle then
                        // It has been long enough since the last time this service was called. Send the command to the SRP Engine Server.
                        GoSub SendCommand
                        DateTime    = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTHS')
                        FirstRun    = Get_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[3;' : vPos : ']')
                        If FirstRun EQ '' then
                            Set_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[3;' : vPos : ']', DateTime)
                            FirstRun    = DateTime
                        end
                        Set_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[4;' : vPos : ']', DateTime)
                        ServiceDetail<SERVICES.LAST_RUN_DTM$> = IConv(DateTime, 'DT')
                        Database_Services('WriteDataRow', 'SERVICES', Service, ServiceDetail)
                        LastDate        = Iconv(DateTime[1, ' '], 'D')
                        LastTime        = Iconv(DateTime[Col2() + 1, ' '], 'MT')
                        LastSeconds     = (LastDate * (24 * 60 * 60)) + LastTime
                        FirstDate       = Iconv(FirstRun[1, ' '], 'D')
                        FirstTime       = Iconv(FirstRun[Col2() + 1, ' '], 'MT')
                        FirstSeconds    = (FirstDate * (24 * 60 * 60)) + FirstTime
                        Uptime          = ((LastSeconds - FirstSeconds) / (24 * 60 * 60))
                        Set_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[5;' : vPos : ']', Oconv(Iconv(Uptime, 'MD1'), 'MD1'))
                        RunCount        = Get_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[6;' : vPos : ']')
                        RunCount       += 1
                        Set_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[6;' : vPos : ']', RunCount)
                    end
                end else
                    // Cycle contains the trigger time that this service runs.
                    TriggerTime = Iconv(Cycle, 'MT')
                    // Make sure this service hasn't already been run on this date.
                    If LastDate LT Date() then
                        // Make sure the trigger time is close (within 30 seconds) to the actual time to avoid being
                        // triggered if the service manager is restarted.
                        If (TriggerTime GE Time()) AND (TriggerTime LE (Time() + 30)) then
                            GoSub SendCommand
                            DateTime    = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTHS')
                            FirstRun    = Get_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[3;' : vPos : ']')
                            If FirstRun EQ '' then
                                Set_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[3;' : vPos : ']', DateTime)
                                FirstRun    = DateTime
                            end
                            Set_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[4;' : vPos : ']', DateTime)
                            ServiceDetail<SERVICES.LAST_RUN_DTM$> = IConv(DateTime, 'DT')
                            Database_Services('WriteDataRow', 'SERVICES', Service, ServiceDetail)
                            LastDate        = Iconv(DateTime[1, ' '], 'D')
                            LastTime        = Iconv(DateTime[Col2() + 1, ' '], 'MT')
                            LastSeconds     = (LastDate * (24 * 60 * 60)) + LastTime
                            FirstDate       = Iconv(FirstRun[1, ' '], 'D')
                            FirstTime       = Iconv(FirstRun[Col2() + 1, ' '], 'MT')
                            FirstSeconds    = (FirstDate * (24 * 60 * 60)) + FirstTime
                            Uptime          = ((LastSeconds - FirstSeconds) / (24 * 60 * 60))
                            Set_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[5;' : vPos : ']', Oconv(Iconv(Uptime, 'MD1'), 'MD1'))
                            RunCount        = Get_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[6;' : vPos : ']')
                            RunCount       += 1
                            Set_Property(@Window : '.OLE_EDT_SERVICES', 'OLE.CellText[6;' : vPos : ']', RunCount)
                        end
                    end
                end
            end

            If (Active EQ True$) AND (Command EQ '') then
                // Automatically turn off this service is there is no command.
                Send_Event(@Window : '.OLE_EDT_SERVICES', 'OLE', 'OnButtonClick', '7;' : vPos)
            end

        Next Service
    end

    // Call Yield() several times to allow for responsiveness with other events.
    Yield(); Yield(); Yield(); Yield(); Yield(); Yield(); Yield(); Yield(); Yield(); Yield(); Yield(); Yield(); Yield()

    // Trigger the next TIMER event 1 second from now.
    Set_Property(@Window, 'TIMER', 0 : @FM : 1000)

end event


Event OLE_EDT_SERVICES.OnButtonClick(Cell, Point, Button, Shift, Ctrl)

    Column      = Cell[1, ';']
    Row         = Cell[Col2() + 1, ';']
    CellType    = Get_Property(CtrlEntId, 'OLE.CellType[' : Cell : ']')
    Color       = CellType<3>
    If Color EQ ActiveColor$ then
        Color   = DeactiveColor$
        Text    = 'Off'
    end else
        Color   = ActiveColor$
        Text    = 'On'
    end
    CellType<3> = Color
    Set_Property(CtrlEntId, 'OLE.CellType[' : Cell : ']', CellType)
    Set_Property(CtrlEntId, 'OLE.CellText[' : Cell : ']', Text)
    If Text EQ 'On' then
        Set_Property(CtrlEntId, 'OLE.CellText[3;' : Row : ']', '')  ; // Clear the first run date/time.
        Set_Property(CtrlEntId, 'OLE.CellText[5;' : Row : ']', 0)   ; // Reset the uptime.
        Set_Property(CtrlEntId, 'OLE.CellText[6;' : Row : ']', 0)   ; // Reset the run count.
    end

end event


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Setup_OLE_Controls:

    Ctrl    = @Window : '.OLE_EDT_SERVICES'
    Set_Property(Ctrl, 'OLE.Dimension', 7 : @FM : 1)
    TitleList   = 'Service Name' : @VM : 'Cycle (secs) or Run Time' : @VM : 'First Run' : @VM : 'Last Run' : @VM: 'Uptime (days)' : @VM : 'Run Count' : @VM : 'Active'
    Set_Property(Ctrl, 'OLE.TitleList', TitleList)
    Set_Property(Ctrl, 'OLE.HeaderColumn[1]', @FM : False$)
    Set_Property(Ctrl, 'OLE.HeaderFont[All; 1]', '' : @SVM : @SVM : '700')
    Set_Property(Ctrl, 'OLE.DataColumn[1]', 100 : @FM : True$ : @FM : False$ : @FM : True$)
    Set_Property(Ctrl, 'OLE.DataColumn[2]', 150 : @FM : True$ : @FM : False$ : @FM : False$)
    Set_Property(Ctrl, 'OLE.DataColumn[3]', 140 : @FM : True$ : @FM : False$ : @FM : False$)
    Set_Property(Ctrl, 'OLE.DataColumn[4]', 140 : @FM : True$ : @FM : False$ : @FM : False$)
    Set_Property(Ctrl, 'OLE.DataColumn[5]', 80  : @FM : True$ : @FM : False$ : @FM : False$)
    Set_Property(Ctrl, 'OLE.DataColumn[6]', 80  : @FM : True$ : @FM : False$ : @FM : False$)
    Set_Property(Ctrl, 'OLE.DataColumn[7]', 50  : @FM : True$ : @FM : False$ : @FM : False$)
    Set_Property(Ctrl, 'OLE.CellType[7; All]', 'Push Button' : @FM : @FM : ActiveColor$)
    Set_Property(Ctrl, 'OLE.CellAlignment[2; All]', '' : @FM : 'Center')
    Set_Property(Ctrl, 'OLE.CellAlignment[3; All]', '' : @FM : 'Center')
    Set_Property(Ctrl, 'OLE.CellAlignment[4; All]', '' : @FM : 'Center')
    Set_Property(Ctrl, 'OLE.CellAlignment[5; All]', '' : @FM : 'Right')
    Set_Property(Ctrl, 'OLE.CellAlignment[6; All]', '' : @FM : 'Right')
    Set_Property(Ctrl, 'OLE.CellAlignment[7; All]', '' : @FM : 'Center')
    Services    = Service_Services('GetServices', Server)
    List        = ''
    For Each Service in Services using @FM
        List   := Service<0, 1> : @VM
        If Service<0, 2> NE '' then
            List   := Service<0, 2> : @VM
        end else
            List   := Oconv(Service<0, 3>, 'MTH') : @VM
        end
        List   := @VM : @VM : 0 : @VM : 0 : @VM : 'On' : @FM
    Next Service
    List[-1, 1] = ''
    Set_Property(Ctrl, 'OLE.List', List)
 	Qualify     = ''
 	Qualify<1>  = 1
    Qualify<4>  = 0
 	Send_Message(Ctrl, 'QUALIFY_EVENT', 'OLE.OnButtonClick', 1)

return


SendCommand:

    // Call the SRPEngineService and pass it the command
    Server                = Environment_Services('GetServer')
    TCPServerSettings@    = Environment_Services('GetApplicationRootIP')
    Convert '\\' to '' in TCPServerSettings@
    TCPServerSettings@<2> = Environment_Services('GetServiceManagerPort')
    TcpClientHandle     = 0
    If SRP_TcpClient(TcpClientHandle, 'CONNECT', TCPServerSettings@<1>, TCPServerSettings@<2>) then
        SRP_TcpClient(TcpClientHandle, 'SEND_SES', Command)
        SRP_TcpClient(TcpClientHandle, 'CLOSE_SES')
    end

return

