Imports UTS_Core.Database
Imports UTS_Core.UTSModule
Imports UTS_Core.UTSModule.DbConnect
Imports UTS_Core.UTSModule.DbTableModel.Manage

Public Class ServiceLog

    Private Shared ReadOnly LogLock As New Object()

    Private Shared ReadOnly LogQueue As New List(Of Dictionary(Of String, String))

    ''' <summary>厂商名</summary>
    Public Shared VendorName As String

    ''' <summary>公网IP</summary>
    Public Shared PublicIp As String

    ''' <summary>本地IP</summary>
    Public Shared PrivateIp As String

    ''' <summary>本地MAC地址</summary>
    Public Shared MAC As String

    ''' <summary>服务索引</summary>
    Public Shared DsIndex As Integer

    ''' <summary>数据服务版本</summary>
    Public Shared DsVersion As String

    ''' <summary>更新服务版本</summary>
    Public Shared UsVersion As String

    ''' <summary>存入数据库日志类型</summary>
    Public Shared DbLogType As Byte

    ''' <summary>日志文件夹路径</summary>
    Public Shared Property LogDirPath As String
        Get
            Return UTS_Core.DebugLog.ApplicationLog.LogDirPath
        End Get
        Set(value As String)
            UTS_Core.DebugLog.ApplicationLog.LogDirPath = value
        End Set
    End Property


    ''' <summary>日志文件前缀</summary>
    Public Shared Property LogFilePrefix As String
        Get
            Return UTS_Core.DebugLog.ApplicationLog.LogFilePrefix
        End Get
        Set(value As String)
            UTS_Core.DebugLog.ApplicationLog.LogFilePrefix = value
        End Set
    End Property


    Public Shared ReadOnly Property LogFilePath() As String
        Get
            Return UTS_Core.DebugLog.ApplicationLog.LogFilePath
        End Get
    End Property


    ''' <summary>在线状态</summary>
    Public Shared Online As Boolean

    ''' <summary>将日志写入到本地文件</summary>
    Public Shared Sub WriteErrorLogToFile(logText As String)
        UTS_Core.DebugLog.ApplicationLog.WriteErrorLog(logText)
    End Sub


    ''' <summary>
    ''' 写入致命错误至本地与云端数据库
    ''' </summary>
    ''' <param name="logText">日志内容</param>
    Public Shared Sub WriteFatalLog(logText As String)
        WriteLogToLogQueue(UTS_Core.DebugLog.ApplicationLog.LogTypes.Fatal, logText)
    End Sub


    Public Shared Sub WriteErrorLog(logText As String)
        WriteLogToLogQueue(UTS_Core.DebugLog.ApplicationLog.LogTypes.Error, logText)
    End Sub

    Public Shared Sub WriteWarningLog(logText As String)
        WriteLogToLogQueue(UTS_Core.DebugLog.ApplicationLog.LogTypes.Warn, logText)
    End Sub

    Public Shared Sub WriteInfoLog(logText As String)
        WriteLogToLogQueue(UTS_Core.DebugLog.ApplicationLog.LogTypes.Info, logText)
    End Sub

    Public Shared Sub WriteDebugLog(logText As String)
        WriteLogToLogQueue(UTS_Core.DebugLog.ApplicationLog.LogTypes.Debug, logText)
    End Sub



    ''' <summary>
    ''' 添加日志内容至缓存的日志队列中
    ''' 调用SaveLogQueueToDb将队列中的数据写入到数据库
    ''' 
    ''' Tip:缓存队列仅记录每条日志不同的内容,例如写入时间，日志类型，日志内容等
    ''' </summary>
    ''' <param name="logType"></param>
    ''' <param name="logText"></param>
    Public Shared Sub WriteLogToLogQueue(logType As UTS_Core.DebugLog.ApplicationLog.LogTypes, logText As String)
        UTS_Core.DebugLog.ApplicationLog.WriteLog($"{logType}", logText) '写入本地文本日志
        If ((DbLogType >> logType) And 1) = 0 Then Return '过滤不入库的信息

        Dim dicFiled As New Dictionary(Of String, String)

        dicFiled.Add($"{DataServiceLogTable.ColNames.DateTime}", $"{Now:yyyy-MM-dd HH:mm:ss}")

        dicFiled.Add($"{DataServiceLogTable.ColNames.LogType}", $"{logType}")
        dicFiled.Add($"{DataServiceLogTable.ColNames.LogText}", $"{logText.Replace("'"c, """"c).Replace("`", """"c)}")

        SyncLock LogLock
            LogQueue.Add(dicFiled) '将日志信息放入缓冲队列
        End SyncLock
    End Sub

    Private Shared Sub SaveLogToLocalDb(count As Integer, Optional saveCache As Boolean = False)
        Dim tableName As String = DataServiceLogTable.TableName
        Using db As New DbExecutor(UtsDb.LocalDbType, UtsDb.LocalConnString)
            db.Open()

            db.BeginTransaction()

            Dim dicFiled As Dictionary(Of String, String)
            Dim cmdText As String
            Dim cmdHelper As DbCmdHelper = DbCmdHelper.CreateCmdHelper(UtsDb.RemoteDbType)

            SyncLock LogLock
                For i As Integer = 0 To count - 1
                    dicFiled = LogQueue.Item(i)

                    '修改上传方式为插值方式
                    Dim colName As String
                    Dim colNames As New List(Of String)
                    Dim remoteFileds As New Dictionary(Of String, String)
                    Try
                        colName = $"{DataServiceLogTable.ColNames.ServiceID}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.Int32, colName, DsIndex)
                        remoteFileds.Add(colName, DsIndex.ToString)

                        colName = $"{DataServiceLogTable.ColNames.ServiceVersion}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.AnsiString, colName, DsVersion)
                        remoteFileds.Add(colName, DsVersion)

                        colName = $"{DataServiceLogTable.ColNames.UpdateServiceVersion}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.AnsiString, colName, UsVersion)
                        remoteFileds.Add(colName, UsVersion)

                        colName = $"{DataServiceLogTable.ColNames.VendorName}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.AnsiString, colName, VendorName)
                        remoteFileds.Add(colName, VendorName)

                        colName = $"{DataServiceLogTable.ColNames.DateTime}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.DateTime, colName, dicFiled(colName))
                        remoteFileds.Add(colName, dicFiled(colName))

                        colName = $"{DataServiceLogTable.ColNames.PublicIp}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.AnsiString, colName, PublicIp)
                        remoteFileds.Add(colName, PublicIp)

                        colName = $"{DataServiceLogTable.ColNames.PrivateIp}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.AnsiString, colName, PrivateIp)
                        remoteFileds.Add(colName, PrivateIp)

                        colName = $"{DataServiceLogTable.ColNames.LogType}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.AnsiString, colName, dicFiled(colName))
                        remoteFileds.Add(colName, dicFiled(colName))

                        colName = $"{DataServiceLogTable.ColNames.LogText}"
                        colNames.Add(colName)
                        db.AddDbParameter(DbType.AnsiString, colName, dicFiled(colName))
                        remoteFileds.Add(colName, dicFiled(colName).Replace("'", " ").Replace("’", " "))

                        cmdText = db.CmdHelper.InsertParam(tableName, colNames)

                        db.ExecuteNonQuery(cmdText) '执行语句
                    Catch ex As Exception
                        WriteErrorLogToFile($"Write LogQueue To Local DB Error: {ex.Message}")
                        Continue For
                    End Try


                    If saveCache Then
                        Try
                            cmdText = cmdHelper.DbInsert(UtsDb.RemotePublicDb, tableName, remoteFileds)
                            DbConnector.SaveCmdStringToCacheTable(db, cmdText) '执行命令入缓存库
                        Catch ex As Exception
                            WriteErrorLogToFile($"Write LogQueue To Chche DB Error: {ex.Message}")
                            Continue For
                        End Try
                    End If
                Next
            End SyncLock

            db.CommitTransaction()
            db.Close()
        End Using
    End Sub

    Private Shared Function SaveLogToRemoteDb(count As Integer) As Boolean
        Dim tableName As String = DataServiceLogTable.TableName
        Using db As New DbExecutor(UtsDb.RemoteDbType, UtsDb.RemoteConnString)
            db.Open()

            db.BeginTransaction()

            Dim dicFiled As Dictionary(Of String, String)
            Dim cmdText As String
            Dim colName As String
            Dim colNames As New List(Of String)

            For i As Integer = 0 To count - 1
                colNames.Clear()
                dicFiled = LogQueue.Item(i)

                Try
                    colName = $"{DataServiceLogTable.ColNames.ServiceID}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.Int32, colName, DsIndex)

                    colName = $"{DataServiceLogTable.ColNames.ServiceVersion}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.AnsiString, colName, DsVersion)

                    colName = $"{DataServiceLogTable.ColNames.UpdateServiceVersion}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.AnsiString, colName, UsVersion)

                    colName = $"{DataServiceLogTable.ColNames.VendorName}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.AnsiString, colName, VendorName)

                    colName = $"{DataServiceLogTable.ColNames.DateTime}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.DateTime, colName, dicFiled(colName))

                    colName = $"{DataServiceLogTable.ColNames.PublicIp}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.AnsiString, colName, PublicIp)

                    colName = $"{DataServiceLogTable.ColNames.PrivateIp}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.AnsiString, colName, PrivateIp)

                    colName = $"{DataServiceLogTable.ColNames.Mac}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.AnsiString, colName, MAC)

                    colName = $"{DataServiceLogTable.ColNames.LogType}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.AnsiString, colName, dicFiled(colName))

                    colName = $"{DataServiceLogTable.ColNames.LogText}"
                    colNames.Add(colName)
                    db.AddDbParameter(DbType.AnsiString, colName, dicFiled(colName))

                    cmdText = db.CmdHelper.DbInsertParam(UtsDb.RemotePublicDb, tableName, colNames)

                    db.ExecuteNonQuery(cmdText) '执行语句

                    db.ClearDbParameter()
                Catch ex As Exception
                    WriteErrorLogToFile($"[{i}]Write LogQueue To Remote DB Error: {ex.Message}")

                    Try
                        db.RollbackTransaction()
                        db.Close()
                    Catch ex2 As Exception
                        WriteErrorLogToFile($"Write LogQueue To Remote DB Rollback Transaction Error: {ex.Message}")
                    End Try

                    Return False
                End Try
            Next

            db.CommitTransaction()
            db.Close()
        End Using

        Return True
    End Function


    Public Shared Sub SaveLogQueueToDb()
        If LogQueue.Count <= 0 Then Return

        Dim count As Integer = LogQueue.Count
        Dim saveCache As Boolean
        SyncLock LogLock
            '执行
            saveCache = SaveLogToRemoteDb(count) = False
            SaveLogToLocalDb(count, saveCache)

            '删除
            For i As Integer = 0 To count - 1
                LogQueue.RemoveAt(0)
            Next
        End SyncLock
    End Sub

    ''' <summary>
    ''' 创建数据服务日志表,数据服务独有
    ''' </summary>
    Public Shared Sub CreateServiceLogTable()

        Using db As New DbExecutor(UtsDb.LocalDbType, UtsDb.LocalConnString)
            db.Open()

            Dim cmdText As String = DataServiceLogTable.CreateTableString("", DbExecutor.DbTypeEnum.Sqlite)

            db.ExecuteNonQuery(cmdText)

            db.Close()
        End Using

    End Sub

End Class
