Imports System.Timers
Imports DigitalData.GUIs.ClientSuite.Base
Imports DigitalData.Modules.Logging

Namespace Workers
    Public Class WorkerManager
        Inherits BaseClass

        ''' <summary>
        ''' Holds information about a worker
        ''' </summary>
        Class WorkerState
            Public Worker As IWorker
            Public Timer As Timer
        End Class

        ''' <summary>
        ''' List of workers that will be started.
        ''' </summary>
        Private WorkerTypes As New List(Of Type) From {
            GetType(HeartbeatWorker),
            GetType(WorkflowOverviewWorker)
        }
        Private Workers As New List(Of WorkerState)

        Public Sub New(LogConfig As LogConfig, SyncronizingObject As frmMain)
            MyBase.New(LogConfig)

            Workers = CreateWorkers(SyncronizingObject)
        End Sub

        Public Function GetWorker(Of T)() As T
            For Each oWorkerState As WorkerState In Workers
                If TypeOf oWorkerState.Worker Is T Then
                    Return oWorkerState.Worker
                End If
            Next

            Return Nothing
        End Function

        Public Sub StopWorkers()
            Logger.Debug("Stopping all workers..")
            For Each oWorkerState In Workers
                oWorkerState.Timer.Stop()

                Try
                    oWorkerState.Worker.Teardown()
                Catch ex As Exception
                    Logger.Warn("Worker {0} threw an error during teardown.", oWorkerState.Worker.Name)
                End Try
            Next
            Logger.Debug("All workers stopped.")
        End Sub

        Private Function CreateTimer(Worker As IWorker, SyncronizingObject As frmMain)
            Dim oTimer = New Timer(Worker.Interval) With {
                .SynchronizingObject = SyncronizingObject,
                .Enabled = True
            }

            AddHandler oTimer.Elapsed, Sub(sender As Object, e As ElapsedEventArgs)
                                           Try
                                               Worker.Callback(Me, e)
                                           Catch ex As Exception
                                               Logger.Warn("Worker {0} threw an error in callback.", Worker.Name)
                                               Logger.Error(ex)
                                           End Try
                                       End Sub

            Return oTimer
        End Function

        Private Function CreateWorkers(SyncronizingObject As frmMain) As List(Of WorkerState)
            Dim oWorkers As New List(Of WorkerState)

            For Each oWorkerType In WorkerTypes
                Dim oWorker As IWorker = Activator.CreateInstance(oWorkerType, New Object() {LogConfig})

                Try
                    oWorker.Setup()

                    Dim oWorkerState As New WorkerState() With {
                        .Worker = oWorker,
                        .Timer = CreateTimer(oWorker, SyncronizingObject)
                    }

                    oWorkers.Add(oWorkerState)
                Catch ex As Exception
                    Logger.Warn("Worker {0} threw an error during setup. Skipping.", oWorker.Name)
                    Logger.Error(ex)
                    Continue For
                End Try
            Next

            Return oWorkers
        End Function
    End Class
End Namespace

