Imports System.Threading
Imports System.Xml.Serialization
Imports UTS_Core.Database
Imports UTS_Core.UTSModule
Imports UTS_Core.UTSModule.Service


''' <summary>
''' 数据库同步类
''' </summary>
<XmlInclude(GetType(DbSyncServiceTask))>
Public Class DbSyncServiceTask
    Inherits ServiceTask

    Sub New()
        TaskType = ServiceTaskTypeEnum.DbSync
        TaskStatus = ServiceTaskStatusEnum.Stop
        TaskName = "DbSync_Default"

        Interval = 5


        LocalDbType = UtsDb.LocalDbType
        LocalConnString = UtsDb.LocalConnString

        RemoteDbType = UtsDb.RemoteDbType
        RemoteConnString = UtsDb.RemoteConnString
        RemotePublicDb = UtsDb.RemotePublicDb
        RemotePrivateDb = UtsDb.RemotePrivateDb
    End Sub

    Sub New(name As String, param As Dictionary(Of String, String))
        TaskType = ServiceTaskTypeEnum.DbSync
        TaskStatus = ServiceTaskStatusEnum.Stop
        TaskName = name

        LocalDbType = UtsDb.LocalDbType
        LocalConnString = UtsDb.LocalConnString

        RemoteDbType = UtsDb.RemoteDbType
        RemoteConnString = UtsDb.RemoteConnString
        RemotePublicDb = UtsDb.RemotePublicDb
        RemotePrivateDb = UtsDb.RemotePrivateDb

        SetParams(param)
    End Sub


    Private Sub StartCallback(stat As Object)
        While TaskStatus = ServiceTaskStatusEnum.Start

            '同步任务
            Try
                Dim syncParam As DbSynchronizer.SyncParam
                syncParam.LocalConnString = LocalConnString
                syncParam.LocalType = LocalDbType
                syncParam.RemoteType = RemoteDbType
                syncParam.RemoteConnString = RemoteConnString
                syncParam.PublicDb = RemotePublicDb
                syncParam.PrivateDb = RemotePrivateDb

                '开始数据库同步
                Dim sync As DbSynchronizer
                sync = New DbSynchronizer(syncParam)
                sync.SyncDatabase()
                ServiceLog.WriteInfoLog($"DbSynchronizer Succeeded!")

                '更新数据库更新时间
                LastUpdateTime = $"{Now:yyyy-MM-dd HH:mm:ss}"
            Catch ex As Exception
                ServiceLog.WriteErrorLog($"TaskName:{TaskName},SyncDatabase Error:{ex.Message}")
            End Try

            '等待任务
            Dim lastTime As Date = Now
            While (Now - lastTime).TotalMinutes < Interval
                If TaskStatus = ServiceTaskStatusEnum.Stop Then
                    Return
                End If

                Thread.Sleep(1000)
            End While

        End While
    End Sub


    Public Overrides Sub Start()
        TaskStatus = ServiceTaskStatusEnum.Start

        If _syncThread IsNot Nothing AndAlso _syncThread.IsAlive Then
            ServiceLog.WriteDebugLog($"SyncThread IsAlive!")
            Return
        End If

        _syncThread = New Thread(AddressOf StartCallback)
        _syncThread.IsBackground = True
        _syncThread.Start()

        ServiceLog.WriteDebugLog($"DbSync Start!")
    End Sub


    Public Overrides Sub [Stop]()
        TaskStatus = ServiceTaskStatusEnum.Stop

        Dim lastTime As Date = Now
        While _syncThread IsNot Nothing AndAlso _syncThread.IsAlive
            If (Now - lastTime).TotalMilliseconds > 10000 Then
                _syncThread.Abort()
            End If

            Thread.Sleep(100)
        End While
        ServiceLog.WriteInfoLog($"DbSync Stop!")
    End Sub


    Public Overrides Sub Restart()
        If _syncThread IsNot Nothing AndAlso _syncThread.IsAlive Then
            [Stop]()
        End If


        Start()
        ServiceLog.WriteInfoLog($"DbSync Restart!")
    End Sub


    Public Overrides Sub SetParams(params As Dictionary(Of String, String))
        Dim tmpStatus As ServiceTaskStatusEnum = TaskStatus
        Dim tmpInterval As Integer = Interval

        '将转换后的数据填充至临时缓存,一遍设置失败时可以保留上一次数据
        For Each param As KeyValuePair(Of String, String) In params
            Select Case param.Key
                Case "Interval"
                    If Integer.TryParse(param.Value, tmpInterval) = False Then
                        Throw New Exception($"Error Interval :{param.Value}")
                    End If
                Case "LocalDbType"
                    'If [Enum].TryParse(param.Value, tmpLocalType) = False Then
                    '    Throw New Exception($"Error LocalDbType :{param.Value}")
                    'End If
                Case "LocalConnString"
                    'tmpLocalConnString = UTS_Core.Security.Aes128.DecryptStr(param.Value, UTS_Core.Security.Aes128.ServerAesKey)
                Case "Status", "Type", "Name" '不处理的字段


                Case Else
                    ServiceLog.WriteWarningLog($"DbSync Unknown param name :{param.Key}")
            End Select
        Next

        TaskStatus = tmpStatus
        Interval = tmpInterval
    End Sub


    Public Overrides Function GetParams() As Dictionary(Of String, String)
        Dim params As New Dictionary(Of String, String)
        params.Add("Type", TaskType.ToString())
        params.Add("Name", TaskName)
        params.Add("Status", TaskStatus.ToString())
        params.Add("Interval", Interval.ToString())
        params.Add("LocalDbType", LocalDbType.ToString())
        params.Add("LocalConnString", UTS_Core.Security.Aes128.EncryptStr(LocalConnString, UTS_Core.Security.Aes128.ServerAesKey))

        Return params
    End Function



    ''' <summary>
    ''' 远程数据库的类型
    ''' </summary>
    Private RemoteDbType As DbExecutor.DbTypeEnum


    ''' <summary>
    ''' 远程数据库的连接字符串
    ''' </summary>
    Private RemoteConnString As String

    ''' <summary>
    ''' 远端公共数据库名
    ''' </summary>
    Private RemotePublicDb As String

    ''' <summary>
    ''' 远端私有库名
    ''' </summary>
    Private RemotePrivateDb As String


    ''' <summary>
    ''' 本地数据库的类型
    ''' </summary>
    Private LocalDbType As DbExecutor.DbTypeEnum


    ''' <summary>
    ''' 本地数据库的连接字符串
    ''' </summary>
    Private LocalConnString As String

    ''' <summary>
    ''' 同步间隔,单位分钟,默认5分钟,最小值为1分钟
    ''' </summary>
    ''' <returns></returns>
    Public Property Interval() As Integer

    Private _syncThread As Thread

    ''' <summary>
    ''' 最后一次更新的时间字符串
    ''' </summary>
    Public Shared LastUpdateTime As String = ""
End Class