Imports System.IO
Imports System.Guid
Imports System.Text.RegularExpressions
Imports Limilabs.Mail
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Logging

Public Class ClassFileHandler
    Inherits BaseClass

    Public Sub New(pLogConfig As LogConfig)
        MyBase.New(pLogConfig)
    End Sub

    Public Property TempFiles As New List(Of String)

    Private Function GetTempPath(pSourceFilePath As String, pNewFileName As String, pSubfolder As String) As String
        Try
            Dim oTempDirectory = Path.GetTempPath()
            Dim oTempSubDirectory As String = Path.Combine(oTempDirectory, pSubfolder)

            ' Try to create a subdirectory for all temp files so it will be easier to clean up 
            ' these files by just deleting the whole fucking folder. 🤬
            If Not Directory.Exists(oTempSubDirectory) Then
                Try
                    Directory.CreateDirectory(oTempSubDirectory)
                Catch ex As Exception
                    Logger.Error(ex)
                    ' We could not create a subfolder
                    ' Set the final directory to the default temp
                    oTempSubDirectory = oTempDirectory
                End Try
            End If

            ' Copy the file to the new location
            Dim oNewPath = Path.Combine(oTempSubDirectory, pNewFileName)
            File.Copy(pSourceFilePath, oNewPath)

            Return oNewPath
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

    Public Sub Clear_Tempfiles()
        For Each oFile In TempFiles
            Try
                System.IO.File.Delete(oFile)
            Catch ex As Exception
                Logger.Error(ex)
            End Try
        Next

        TempFiles.Clear()
    End Sub


    Public Function Decide_FileHandle(pFilepath As String, pHandletype As String) As Boolean
        Try
            Logger.Info($"Decide_FileHandle - pFilepath: {pFilepath} - pHandletype: {pHandletype}")
            ''TODO: Before doing anything, clean the filename
            'Dim oFilename = IO.Path.GetFileName(pFilepath)
            'Dim oCleanFileName = Utils.RemoveInvalidCharacters(oFilename)
            'Dim oTempDirectory = IO.Path.GetTempPath()
            'Dim oTempFilePath = IO.Path.Combine(oTempDirectory, oCleanFileName)

            'Try
            '    TEMP_FILES.Add(oTempFilePath)
            '    LOGGER.Debug("Copying file")
            '    LOGGER.Debug(pFilepath)
            '    LOGGER.Debug(oTempFilePath)
            '    IO.File.Copy(pFilepath, oTempFilePath, True)
            'Catch ex As Exception
            '    LOGGER.Error(ex)
            '    Throw ex
            'End Try

            Dim oTempFilePath = pFilepath

            Dim oInboxRegex As New Regex("\.INBOX\d+$")

            If oInboxRegex.IsMatch(oTempFilePath) Then
                Logger.Info("Renaming INBOX file to EML")

                Try
                    Dim oInfo As New FileInfo(oTempFilePath)
                    Logger.Info("Old Name: {0}", oInfo.Name)
                    Dim oNewName = $"{oInfo.Name}.eml"
                    Logger.Info("New Name: {0}", oNewName)
                    Dim oTempDirectory = IO.Path.GetTempPath()
                    Dim oNewPath = IO.Path.Combine(oTempDirectory, oNewName)

                    IO.File.Copy(oInfo.FullName, oNewPath)

                    'TEMP_FILES.Add(oNewPath)
                    TempFiles.Add(oNewPath)

                    oTempFilePath = oNewPath
                Catch ex As Exception
                    Logger.Error(ex)
                End Try
            End If

            If oTempFilePath.ToUpper.EndsWith(".MSG") Or oTempFilePath.ToUpper.EndsWith(".EML") Then
                CURRENT_MESSAGEID = ""
                Dim oMail As IMail = EMAIL.Load_Email(oTempFilePath)
                If oMail.Attachments.Count > 0 Then
                    Dim oTitle As String
                    Dim oMessage As String

                    If USER_LANGUAGE = "de-DE" Then
                        oTitle = "Nachfrage zur Indexierung:"
                        oMessage = "Achtung: Die Email enthält Anhänge!" & vbNewLine & "Wollen Sie die Anhänge separat indexieren und herauslösen?"
                    Else
                        oTitle = "Question about Indexing:"
                        oMessage = "Attention: This Email contains Attachments!" & vbNewLine & "Do you want to extract the attachments and index them seperately?"
                    End If
                    Dim oResult As DialogResult

                    ' Weird hack to force messagebox to be topmost
                    ' https://stackoverflow.com/questions/1220882/keep-messagebox-show-on-top-of-other-application-using-c-sharp
                    oResult = MessageBox.Show(oMessage, oTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly)


                    If oResult = MsgBoxResult.Yes Then
                        Dim oIsFolderWatch = pHandletype.StartsWith("|FW")
                        Return Save_EmailAndAttachmentsToDisk(oTempFilePath, oIsFolderWatch)
                    End If
                End If
            End If

            If oTempFilePath.ToUpper.EndsWith(".LNK") Then
                If USER_LANGUAGE = "de-DE" Then
                    MsgBox("Verknüpfungen können nicht abgelegt werden!", MsgBoxStyle.Critical, "fileFLOW")
                Else
                    MsgBox("Shortcuts cannot be droppped!", MsgBoxStyle.Critical, "fileFLOW")
                End If
                Return False
            End If

            Return Insert_GI_File(oTempFilePath, pHandletype)
        Catch ex As Exception
            MsgBox("Unexpected Error in Decide_FileHandle: " & ex.Message, MsgBoxStyle.Critical)
            Return False
        End Try
    End Function

    Private Function Save_EmailAndAttachmentsToDisk(pEmailFilePath As String, Optional pFolderWatch As Boolean = False) As Boolean
        Try
            Dim oMessageOnlyMarker As String = "|MSGONLY|"
            Dim oExtractedAttachmentMarker As String = "|ATTMNTEXTRACTED|"
            If pFolderWatch = True Then
                oMessageOnlyMarker = "|FW_MSGONLY|"
                oExtractedAttachmentMarker = "|FW_ATTMNTEXTRACTED|"
            End If
            Dim oSuccess As Boolean = False

            Logger.Info("Converting file to Eml if needed: [{0}]", pEmailFilePath)
            Dim oEmail As IMail = EMAIL.Load_Email(pEmailFilePath)

            If oEmail.MessageID IsNot Nothing Then
                CURRENT_MESSAGEID = oEmail.MessageID
            Else
                Logger.Info("Es konnte keine Message-ID gelesen werden. Eine GUID wird erzeugt!")
                CURRENT_MESSAGEID = NewGuid.ToString()
            End If

            Dim oEmailFilePathWithoutAttachments = EMAIL.Remove_AttachmentsFromEmail(pEmailFilePath, "_excl_attachments")

            TempFiles.Add(oEmailFilePathWithoutAttachments)
            'TEMP_FILES.Add(oEmailFilePathWithoutAttachments)

            If Insert_GI_File(oEmailFilePathWithoutAttachments, oMessageOnlyMarker) = True Then
                oSuccess = True

                Dim oAttachments As List(Of String) = EMAIL.Save_AttachmentsToDisk(pEmailFilePath)

                Logger.Debug("Saved [{0}] attachments to disk.", oAttachments.Count)

                For Each oAttachment In oAttachments
                    'TEMP_FILES.Add(oAttachment)
                    TempFiles.Add(oAttachment)

                    Logger.Debug("Saved attachment [{0}].", oAttachment)
                    oSuccess = Insert_GI_File(oAttachment, oExtractedAttachmentMarker)

                    If oSuccess = False Then
                        Logger.Warn("Saving attachment to disk failed: [{0}]", oAttachment)
                        Exit For
                    End If
                Next
            End If

            Return oSuccess
        Catch ex As Exception
            Logger.Warn("Saving email to disk failed (Email_Decay)")
            Logger.Error(ex)

            Return False
        End Try
    End Function

    'Private Shared Function Email_Decay(msgname As String, Optional FW As Boolean = False)
    '    Try
    '        Dim msgonly As String = "|MSGONLY|"
    '        Dim ATT_EXTR As String = "|ATTMNTEXTRACTED|"
    '        If FW = True Then
    '            msgonly = "|FW_MSGONLY|"
    '            ATT_EXTR = "|FW_ATTMNTEXTRACTED|"
    '        End If
    '        Dim erfolgreich As Boolean = False
    '        Dim msg As New MSG.Message(msgname)

    '        If msg.InternetMessageId IsNot Nothing Then
    '            CURRENT_MESSAGEID = msg.InternetMessageId
    '        Else
    '            LOGGER.Info("Es konnte keine Message-ID gelesen werden. Eine GUID wird erzeugt!")
    '            Dim sGUID As String
    '            sGUID = System.Guid.NewGuid.ToString()
    '            CURRENT_MESSAGEID = sGUID
    '        End If

    '        'Nur die MSGDatei ablegen
    '        Dim tempfile As String = Path.Combine(Path.GetTempPath, Path.GetFileNameWithoutExtension(msgname) & "_excl_att.msg")

    '        If File.Exists(tempfile) Then
    '            File.Delete(tempfile)
    '        End If
    '        Dim _msgEXAtt As New Msg.Message(msgname)
    '        _msgEXAtt.Attachments.Clear()
    '        _msgEXAtt.Save(tempfile)
    '        'Datei in Array zum Templöschen speichern
    '        TEMP_FILES.Add(tempfile)

    '        If Insert_GI_File(tempfile, msgonly) = True Then
    '            erfolgreich = True
    '            'Hier nun die Anhänge herauslösen
    '            Dim _msg As New Msg.Message(msgname)
    '            Dim i1 As Integer = 1

    '            LOGGER.Info(">> Anzahl der Attachments: " & _msg.Attachments.Count)
    '            For Each attachment As Independentsoft.Msg.Attachment In _msg.Attachments
    '                If erfolgreich = False Then
    '                    Exit For
    '                End If
    '                Dim attachment_name As String
    '                If attachment.LongFileName Is Nothing Then
    '                    attachment_name = attachment.DisplayName
    '                Else
    '                    attachment_name = attachment.LongFileName
    '                End If
    '                If attachment.EmbeddedMessage IsNot Nothing Then
    '                    attachment_name = Utils.RemoveInvalidCharacters(attachment_name)
    '                    tempfile = Path.Combine(Path.GetTempPath, attachment_name & ".msg")
    '                    tempfile = ClassFilehandle.Versionierung_Datei(tempfile)

    '                    If tempfile <> String.Empty Then
    '                        Dim oMessage = attachment.EmbeddedMessage
    '                        oMessage.IsEmbedded = False
    '                        oMessage.Save(tempfile)
    '                        TEMP_FILES.Add(tempfile)
    '                        LOGGER.Info(">> Attachment (" & i1 & "):" & tempfile)
    '                        erfolgreich = Insert_GI_File(tempfile, ATT_EXTR)
    '                        i1 += 1
    '                    End If
    '                ElseIf Not attachment_name.Contains("inline") Then
    '                    'Sonderzeichen entfernen
    '                    attachment_name = Utils.RemoveInvalidCharacters(attachment_name)
    '                    tempfile = Path.Combine(Path.GetTempPath, attachment_name)
    '                    tempfile = ClassFilehandle.Versionierung_Datei(tempfile)
    '                    If tempfile <> "" Then
    '                        attachment.Save(tempfile)
    '                        'Datei in Array zum Templöschen speichern
    '                        TEMP_FILES.Add(tempfile)
    '                        LOGGER.Info(">> Attachment (" & i1 & "):" & tempfile)
    '                        'nun der Insert des Anhanges
    '                        erfolgreich = Insert_GI_File(tempfile, ATT_EXTR)
    '                        i1 += 1
    '                    End If
    '                End If
    '            Next
    '        End If
    '        Return erfolgreich
    '    Catch ex As Exception
    '        MsgBox("Error in Email_Decay: " & ex.Message, MsgBoxStyle.Critical)
    '    End Try
    'End Function

    Private Function Insert_GI_File(filename As String, handleType As String)
        Try
            filename = filename.Replace("'", "''")

            Dim oHash As String = String.Empty

            If File.Exists(filename) Then
                If (filename.ToUpper.EndsWith(".MSG") Or filename.ToUpper.EndsWith(".EML")) And (handleType = "|OUTLOOK_MESSAGE|" Or handleType = "|MSGONLY|") Then
                    oHash = FILESYSTEM.GetChecksumFromString(filename)
                Else
                    oHash = FILESYSTEM.GetChecksum(filename)
                End If
            End If

            Dim filename_only As String = Path.GetFileName(filename)
            Dim ins As String = $"INSERT INTO TBGI_FILES_USER (FILENAME2WORK, USER@WORK, HANDLE_TYPE, FILENAME_ONLY, FILE_HASH) VALUES ('{filename}','{Environment.UserName}','{handleType}','{filename_only}', '{oHash}')"
            Return DATABASE_ECM.ExecuteNonQuery(ins)

        Catch ex As Exception
            Return False
        End Try
    End Function
    Public Function IsFileInUse(ByVal fullFilePath As String) As Boolean
        ' Gibt zurück, ob die übergebene Datei momentan exklusiv zu haben ist.
        ' Prüft, ob die angegeben Datei aktuell durch eine
        ' andere Anwendung in Benutzung ist
        Dim ff As Integer = FreeFile()
        If File.Exists(fullFilePath) Then
            Try
                ' Versuchen, die Datei mit *exklusiven* Lese- und
                ' Schreibrechten zu öffnen
                FileOpen(ff, fullFilePath, OpenMode.Binary, OpenAccess.ReadWrite, OpenShare.LockReadWrite)
            Catch ex As Exception
                ' Ist ein Fehler aufgetreten, so wird nach außen hin generell
                ' davon ausgegangen, dass die Datei in Benutzung ist (obwohl
                ' auch andere Ursachen, etwa Rechteprobleme, möglich sind).
                Logger.Info(">> FileInUse Message: " & ex.Message)
                IsFileInUse = True
            Finally
                ' Die eventuell geöffnete Datei schließen
                FileClose(ff)
            End Try
            Return False
        End If

    End Function
    Public Function Versionierung_Datei(Dateiname As String)
        Dim extension
        Dim _NewFileString
        Try
            Dim version As Integer = 1

            Dim Stammname As String = Path.GetDirectoryName(Dateiname) & "\" & Path.GetFileNameWithoutExtension(Dateiname).Trim()
            extension = Path.GetExtension(Dateiname)

            Dim _neuername As String = Stammname
            'Dim MoveFilename As String = DATEINAME.Replace(element.Value, "")
            'Überprüfen ob File existiert
            If File.Exists(_neuername & extension) = False Then
                _NewFileString = _neuername
            Else
                Do While File.Exists(_neuername & extension)
                    version += 1
                    _neuername = Stammname & "~" & version
                    _NewFileString = _neuername
                Loop
            End If
            Return _NewFileString & extension
        Catch ex As Exception
            Logger.Info(" - Error in versioning file - error: " & vbNewLine & ex.Message)
            Logger.Error(ex)
            MsgBox(ex.Message, MsgBoxStyle.Critical, "Error in versioning file:")
            Return ""
        End Try

    End Function
    '' <summary>
    ''' Ersetzt alle nicht zulässigen Zeichen im angegebenen Dateinamen
    ''' </summary>
    ''' <param name="sFilename">Dateiname ohne Pfadangabe</param>
    ''' <param name="sChar">Ersatzzeichen für alle unzulässigen Zeichen 
    ''' im Dateinamen</param>
    Public Function CleanFilename(ByVal sFilename As String, Optional ByVal REPLACEChar As String = "") As String
        Logger.Info(" >> Filename before CleanFilename: '" & sFilename & "'")
        If sFilename.Contains(".\") Then
            sFilename = sFilename.Replace(".\", "\")
        End If
        'If sFilename.Contains("'") Then
        '    sFilename = sFilename.Replace("'", "")
        'End If
        'If sFilename.Contains("..") Then
        '    sFilename = sFilename.Replace("..", ".")
        'End If
        ' alle nicht zulässigen Zeichen ersetzen
        sFilename = System.Text.RegularExpressions.Regex.Replace(sFilename, REGEX_CLEAN_FILENAME, REPLACEChar)
        sFilename = System.Text.RegularExpressions.Regex.Replace(sFilename, "[\\/:*?""<>|\r\n]", "", System.Text.RegularExpressions.RegexOptions.Singleline)
        'Dim oCleanFileName As String = String.Join(REPLACEChar, sFilename.Split(Path.GetInvalidFileNameChars()))
        Dim oCleanFileName As New System.IO.FileInfo(System.Text.RegularExpressions.Regex.Replace(sFilename, String.Format("[{0}]", String.Join(String.Empty, Path.GetInvalidFileNameChars)), REPLACEChar))
        Logger.Info(" >> Filename after CleanFilename: '" & sFilename & "'")
        Return sFilename
    End Function
End Class
