Imports System.Configuration
Imports System.Globalization
Imports Spring.Context
Imports GPSConnector.Common
Imports Spring.Context.Support

Public Class GPSConnectorStatusService
    Implements IGPSConnectorStatusService
    Private ReadOnly _gpsConnectorServiceSetting As GPSConnectorServiceSetting
    Public Sub New()
        Dim ctx As IApplicationContext = ContextRegistry.GetContext()
        _gpsConnectorServiceSetting = CType(ctx.GetObject("GPSConnectorServiceSetting"), GPSConnectorServiceSetting)
        End Sub
    Public Function GetDeviceData(ownerKey As String) As List(Of GPSDeviceData) Implements IGPSConnectorStatusService.GetDeviceData
        Try
            Dim owner As Owner = _gpsConnectorServiceSetting.Database.GetOwner(ownerKey)
            If owner Is Nothing Then Return Nothing

            Dim data = _gpsConnectorServiceSetting.LatestGPSDeviceData()
            If owner.IsAdmin Then
                Return data
            Else
                Return data.Where(Function(d) _gpsConnectorServiceSetting.Database.IsDeviceOwnedBy(d.Id, owner.ID)).ToList()
            End If
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:GetDeviceData", False)
        End Try
        Return Nothing
    End Function

    Public Function GetCustomServices() As List(Of CustomService) Implements IGPSConnectorStatusService.GetCustomServices
        Try
            Dim cservices As List(Of CustomService) = (From customService In _gpsConnectorServiceSetting.CustomServices Select New CustomService() With {.CanRestart = customService.CanRestart, .Description = customService.Description, .ServiceName = customService.ServiceName, .State = customService.GetState()}).ToList()
            Return cservices
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:GetDeviceData", False)
        End Try
        Return Nothing
    End Function

    Public Function GetCustomServiceStatus(customServiceName As String) As List(Of CustomServiceStatus) Implements IGPSConnectorStatusService.GetCustomServiceStatus
        Try
            For Each customService As ICustomService In _gpsConnectorServiceSetting.CustomServices
                If customService.ServiceName.ToLower() = customServiceName Then
                    Return customService.GetStatus()
                End If
            Next
            Return Nothing
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:GetCustomServiceStatus", False)
        End Try
        Return Nothing
    End Function

    Public Function GetDevices(ownerkey As String) As List(Of GPSDevice) Implements IGPSConnectorStatusService.GetDevices
        Try
            Return _gpsConnectorServiceSetting.Database.GetDeviceList(ownerkey)
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:GetDevices", False)
            Return Nothing
        End Try

    End Function

    Public Function GetDeviceTypeComponentInfo() As List(Of DeviceTypeComponentInfo) Implements IGPSConnectorStatusService.GetDeviceTypeComponentInfo
        Try
            Dim infos As List(Of DeviceTypeComponentInfo) = (From component In _gpsConnectorServiceSetting.Components Select New DeviceTypeComponentInfo() With {.ActiveConnectionCount = component.ActiveConnectionCount, .DeviceTypeName = component.DeviceTypeName, .ListenIp = If(String.IsNullOrEmpty(component.Ip), "Any", component.Ip), .ListenPort = component.Port}).ToList()
            Return infos
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:GetDeviceTypeComponentInfo", False)
            Return Nothing
        End Try
    End Function

    Public Function GetLogInfo() As List(Of LogInfo) Implements IGPSConnectorStatusService.GetLogInfo
        Try
            Return _gpsConnectorServiceSetting.Logger.GetImmediateLogInfo(EnLogInfoType.Information)
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:GetLogInfo", False)
            Return Nothing
        End Try

    End Function

    Public Function GetLogError() As List(Of LogInfo) Implements IGPSConnectorStatusService.GetLogError
        Try
            Return _gpsConnectorServiceSetting.Logger.GetImmediateLogInfo(EnLogInfoType.[Error])
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:GetLogError", False)
            Return Nothing
        End Try

    End Function

    Public Function Subscribe(ownerkey As String) As Boolean Implements IGPSConnectorStatusService.Subscribe
        Try
            Dim callback As IGPSConnectorStatusServiceCallBack = OperationContext.Current.GetCallbackChannel(Of IGPSConnectorStatusServiceCallBack)()
            If Not callback Is Nothing AndAlso Not Subscribers.Exists(Function(c) c.GPSConnectorStatusServiceCallBack Is callback) Then
                Subscribers.Add(New Subscriber() With {.GPSConnectorStatusServiceCallBack = callback, .OwnerKey = ownerkey})
            End If
            Return True
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:Subscribe", True)
            Return False
        End Try
    End Function

    Public Function Unsubscribe() As Boolean Implements IGPSConnectorStatusService.Unsubscribe
        Try
            Dim callback As IGPSConnectorStatusServiceCallBack = OperationContext.Current.GetCallbackChannel(Of IGPSConnectorStatusServiceCallBack)()
            Dim subscriber As Subscriber = Nothing
            Try
                subscriber = Subscribers.SingleOrDefault(Function(c) c.GPSConnectorStatusServiceCallBack Is callback)
            Catch ex As Exception

            End Try

            If Not subscriber Is Nothing Then
                Subscribers.Remove(subscriber)
            End If
            Return True
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:Unsubscribe", True)
            Return False
        End Try
    End Function

    Public Function GetOwnerInfo(ByVal ownerKey As String) As Owner Implements IGPSConnectorStatusService.GetOwnerInfo
        Try
            Dim owner As Owner = _gpsConnectorServiceSetting.Database.GetOwner(ownerKey)
            _gpsConnectorServiceSetting.Database.GetOwnerCalcDistributors(owner)
            Return owner
        Catch ex As Exception
            _gpsConnectorServiceSetting.Logger.LogException(ex, "GPSConnectorStatusService:Unsubscribe", True)
        End Try
        Return Nothing
    End Function

    Public Function Calculate(ByVal ownerKey As String, distributorId As Integer, ByVal dataDate As Date) As CalculationResult Implements IGPSConnectorStatusService.Calculate
        Dim result As New CalculationResult
        Try
            Dim owner As Owner = GetOwnerInfo(ownerKey)
            If owner Is Nothing OrElse owner.CalcDistributors.Count = 0 OrElse owner.CalcDistributors.SingleOrDefault(Function(d) d.Id = distributorId) Is Nothing Then
                result.Success = False
                result.Log = "Invalid owner key or no calc distributors or distributorId not belong to this owner"
            Else
                Dim calcApp As String = ConfigurationManager.AppSettings("SegwayCalculationConsole")
                Dim calcArgument As String = String.Format(ConfigurationManager.AppSettings("SegwayCalculationConsoleArgument"), distributorId, dataDate.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture))
                Dim startInfo As New ProcessStartInfo With {
                    .Arguments = calcArgument,
                    .CreateNoWindow = True,
                    .FileName = calcApp,
                    .RedirectStandardError = True,
                    .RedirectStandardOutput = True,
                    .UseShellExecute = False
                    }
                Dim process As New Process()

                process.StartInfo = startInfo
                process.Start()
                process.WaitForExit()

                If process.ExitCode = 0 Then
                    result.Success = True
                Else
                    result.Success = False
                End If

                If process.StandardOutput IsNot Nothing Then
                    result.Log = process.StandardOutput.ReadToEnd()
                End If

                If process.StandardError IsNot Nothing Then

                    result.Log += Environment.NewLine + process.StandardError.ReadToEnd()
                End If
            End If

            Return result
        Catch ex As Exception
            result.Success = False
            result.Log = String.Format("Message = {0}, {1}, StackTrace = {2}", ex.Message, Environment.NewLine, ex.StackTrace)
            Return result
       End Try

    End Function

    Public Sub HeartBeatTest() Implements IGPSConnectorStatusService.HeartBeatTest
        Return
    End Sub
End Class
