Imports System.ServiceModel
Imports System.ServiceProcess
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Database
Imports DigitalData.Modules
Imports System.ServiceModel.Description
Imports DigitalData.Modules.Config
Imports System.ServiceModel.Channels

Public Class WindowsService
    Inherits ServiceBase

    Private _ServiceHost As ServiceHost(Of EDMIService)
    Private _LogConfig As LogConfig
    Private _Logger As Logger

    Private _Firebird As Firebird
    Private _MSSQL_ECM As MSSQLServer
    Private _MSSQL_IDB As MSSQLServer

    Private _ConfigManager As ConfigManager(Of Config)
    Private _Config As Config
    Private _Path As EDMI.File.Path
    Private _Archive As EDMI.File.Archive
    Private _Filesystem As Filesystem.File
    Private _Global As GlobalState
    Private _Scheduler As Scheduler

    Public Sub New()
        ServiceName = SERVICE_NAME
    End Sub

    Public Shared Sub Main()
        Run(New WindowsService())
    End Sub

    Protected Overrides Sub OnStart(ByVal args As String())
        Try
            Dim oServicePath As String = AppDomain.CurrentDomain.BaseDirectory

            _LogConfig = New LogConfig(LogConfig.PathType.CustomPath, IO.Path.Combine(oServicePath, "Log"))
            _Logger = _LogConfig.GetLogger()

            Try
                Dim directory As New IO.DirectoryInfo(_LogConfig.LogDirectory)

                For Each file As IO.FileInfo In directory.GetFiles
                    If (Now - file.CreationTime).Days > 29 Then
                        file.Delete()
                    Else
                        Exit For
                    End If
                Next
            Catch ex As Exception
                _Logger.Error(ex)
            End Try

            _Logger.Info("Service {0} is starting...", SERVICE_DISPLAY_NAME)
            _Logger.Info("ServiceDirectory: {0}", oServicePath)

            _Logger.Info("Loading Config")
            _ConfigManager = New ConfigManager(Of Config)(_LogConfig, oServicePath)
            _Config = _ConfigManager.Config
            _LogConfig.Debug = _ConfigManager.Config.Debug

            'UpdateTraceLogging()

            Dim oTimer As New Timers.Timer(60000)
            AddHandler oTimer.Elapsed, Sub()
                                           _Logger.Debug("Reloading config..")
                                           _ConfigManager.Reload()
                                           _Config = _ConfigManager.Config
                                           _LogConfig.Debug = _ConfigManager.Config.Debug

                                           'UpdateTraceLogging()
                                       End Sub
            oTimer.Start()

            _Logger.Debug("Connecting to Databases")

            _Firebird = StartFirebird()
            _MSSQL_ECM = StartMSSQL_ECM()
            _MSSQL_IDB = StartMSSQL_IDB()

            _Logger.Debug("Initializing EDMI Functions")

            _Archive = New EDMI.File.Archive(_LogConfig)
            _Filesystem = New Filesystem.File(_LogConfig)
            _Global = New GlobalState(_LogConfig, _MSSQL_IDB, _MSSQL_ECM)
            _Scheduler = New Scheduler(_LogConfig, _MSSQL_ECM, _Global.TableStore)

            _Logger.Debug("Loading Objectstores")
            _Global.LoadObjectStores()

            _Logger.Debug("Starting Scheduler")
            _Scheduler.Start()

            _Logger.Debug("Preparing WCF ServiceHost")
            EDMIService.MSSQL_ECM = _MSSQL_ECM
            EDMIService.MSSQL_IDB = _MSSQL_IDB
            EDMIService.Firebird = _Firebird
            EDMIService.LogConfig = _LogConfig
            EDMIService.AppConfig = _Config
            EDMIService.EDMIArchive = _Archive
            EDMIService.Filesystem = _Filesystem
            EDMIService.GlobalState = _Global
            EDMIService.Scheduler = _Scheduler

            _Logger.Debug("Starting WCF ServiceHost")

            Dim oBaseAddresses() As Uri = {New Uri("net.tcp://localhost:9000/DigitalData/Services/Main")}
            _ServiceHost = New ServiceHost(Of EDMIService)(oBaseAddresses)
            _ServiceHost.EnableMetadataExchange(False)

            _Logger.Debug("Listing Endpoints:")
            For Each oEndpoint In _ServiceHost.Description.Endpoints
                _Logger.Debug("Name: {0}", oEndpoint.Name)
                _Logger.Debug("Address: {0}", oEndpoint.Address.ToString)
                _Logger.Debug("Listen Uri: {0}", oEndpoint.ListenUri.AbsoluteUri)
                _Logger.Debug("Binding: {0}", oEndpoint.Binding.Name)
                _Logger.Debug("Contract: {0}", oEndpoint.Contract.Name)
            Next

            _ServiceHost.Open()

            _Logger.Info("WCF ServiceHost started")
            _Logger.Info("Service {0} successfully started", SERVICE_DISPLAY_NAME)
        Catch ex As Exception
            _Logger.Warn("Unexpected Error while starting the service: {0}", ex.Message)
            _Logger.Error(ex)
            GracefullyStop()
        End Try
    End Sub

    Private Sub UpdateTraceLogging()
        Try
            ' Changing Tracelevels programmatically,
            ' See: https://wcfpro.wordpress.com/2010/11/21/how-to-add-wcf-traces-programmatically/
            _Logger.Debug("UpdateTraceLogging running..")
            _Logger.Debug("SourceLevels is off by default")

            Dim oTraceLevel = SourceLevels.Off

            _Logger.Debug("Debug is currently set to {0}", _ConfigManager.Config.Debug)
            If _ConfigManager.Config.Debug Then
                oTraceLevel = SourceLevels.Warning
            End If

            _Logger.Debug("Setting TraceLevel to {0}", oTraceLevel)
            WcfTracesController.Instance.LevelController(oTraceLevel)
        Catch ex As Exception
            _Logger.Warn("TraceLogging could not be updated!")
            _Logger.Error(ex)
        End Try
    End Sub

    Private Function StartFirebird() As Firebird
        _Logger.Debug("Connecting to Firebird")

        If _Config.Firebird_Datasource = String.Empty Then
            _Logger.Info("Firebird database not configured. Skipping.")
            Return Nothing
        End If

        Try
            Dim oFirebird = New Firebird(
                _LogConfig,
                _Config.Firebird_Datasource,
                _Config.Firebird_DatabaseName,
                _Config.Firebird_DatabaseUser,
                _Config.Firebird_DatabasePassword
            )

            _Logger.Info("Database connection established.")
            Return oFirebird
        Catch ex As Exception
            _Logger.Warn("StartFirebird: Could not connect to firebird database.")
            _Logger.Error(ex)
            Return Nothing
        End Try
    End Function

    Private Function StartMSSQL_ECM() As MSSQLServer
        _Logger.Debug("Connecting to ECM MSSQL")
        Dim oMSSQL = New MSSQLServer(_LogConfig, _Config.ConnectionString_ECM)
        _Logger.Info("Database connection to ECM Database established.")
        Return oMSSQL
    End Function

    Private Function StartMSSQL_IDB() As MSSQLServer
        _Logger.Debug("Connecting to IDB MSSQL")
        Dim oMSSQL = New MSSQLServer(_LogConfig, _Config.ConnectionString_IDB)
        _Logger.Info("Database connection to IDB Database established.")
        Return oMSSQL
    End Function

    Protected Overrides Sub OnStop()
        GracefullyStop()
    End Sub

    Private Sub GracefullyStop()
        _Logger.Info("Service {0} is stopping!", SERVICE_DISPLAY_NAME)
        If _ServiceHost IsNot Nothing Then
            _ServiceHost.Close()
            _ServiceHost = Nothing
        End If

        _Scheduler.Stop()
    End Sub
End Class

