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 LogConfigScheduler 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 Archive As EDMI.File.Archive
    Private Filesystem As Filesystem.File
    Private GlobalState 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
            ' Init
            Dim oServicePath As String = AppDomain.CurrentDomain.BaseDirectory
            Dim oServiceVersion As String = My.Application.Info.Version.ToString()

            ' Initializing Logger
            LogConfig = New LogConfig(LogConfig.PathType.CustomPath, IO.Path.Combine(oServicePath, "Log"), FileKeepRangeInDays:=3)
            LogConfigScheduler = New LogConfig(LogConfig.PathType.CustomPath, IO.Path.Combine(oServicePath, "Log"), Suffix:="Scheduler", FileKeepRangeInDays:=3)
            Logger = LogConfig.GetLogger()

            ' Log Initial
            Logger.Info("Service [{0}] is starting...", SERVICE_DISPLAY_NAME)
            Logger.Info("ServiceDirectory: [{0}]", oServicePath)
            Logger.Info("Version: [{0}]", oServiceVersion)

            ' Initializing Config
            Logger.Info("Loading Config")
            ConfigManager = New ConfigManager(Of Config)(LogConfig, oServicePath)
            Config = ConfigManager.Config

            ' Setup Reload-timer for config
            Dim oTimer As New Timers.Timer(60000)
            AddHandler oTimer.Elapsed, AddressOf ReloadTimer_Tick
            oTimer.Start()

            ' Setting Debug Flag
            Logger.Info("Setting DEBUG Flag to [{0}]", ConfigManager.Config.Debug)
            LogConfig.Debug = ConfigManager.Config.Debug
            LogConfigScheduler.Debug = ConfigManager.Config.Debug

            Logger.Debug("Connecting to Databases")

            Firebird = StartFirebird()
            MSSQL_ECM = GetMSSQL_ECM(LogConfig)
            MSSQL_IDB = GetMSSQL_IDB(LogConfig)

            Logger.Debug("Initializing EDMI Functions")
            Archive = New EDMI.File.Archive(LogConfig)
            Filesystem = New Filesystem.File(LogConfig)
            GlobalState = New GlobalState(LogConfig, MSSQL_IDB, MSSQL_ECM)

            Dim oMSSQLServer = GetMSSQL_ECM(LogConfigScheduler)
            Scheduler = New Scheduler(LogConfigScheduler, oMSSQLServer, GlobalState.TableStore)

            Logger.Debug("Loading Global Data")
            GlobalState.LoadObjectStores()
            GlobalState.LoadConnections()

            Logger.Debug("Loading Client Config")
            Logger.Debug("ForceDirectDatabaseAccess: {0}", Config.ClientConfig.ForceDirectDatabaseAccess)
            GlobalState.ClientConfig = Config.ClientConfig

            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 = GlobalState
            EDMIService.Scheduler = Scheduler

            Logger.Debug("Starting WCF ServiceHost")

            Dim oBaseAddresses() As Uri = {New Uri(SERVICE_BASE_ADDRESS)}
            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 ReloadTimer_Tick()
        If ConfigManager.Reload() = False Then
            Logger.Warn("Could not reload config, check the service and config file.")
        End If

        Config = ConfigManager.Config
        LogConfig.Debug = ConfigManager.Config.Debug
    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 GetMSSQL_ECM(pLogConfig As LogConfig) As MSSQLServer
        Logger.Debug("Connecting to ECM MSSQL")
        Dim oMSSQL = New MSSQLServer(pLogConfig, Config.ConnectionString_ECM)
        Logger.Info("Database connection to ECM Database established.")
        Return oMSSQL
    End Function

    Private Function GetMSSQL_IDB(pLogConfig As LogConfig) As MSSQLServer
        Logger.Debug("Connecting to IDB MSSQL")
        Dim oMSSQL = New MSSQLServer(pLogConfig, 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

