
Imports WINDREAMLib
Imports WINDREAMLib.WMCOMEvent
Imports WINDREAMLib.WMEntity
Imports WINDREAMLib.WMObjectEditMode
Imports WINDREAMLib.WMSearchOperator
Imports WINDREAMLib.WMSearchRelation
Imports WMOBRWSLib
Imports WMOSRCHLib
Imports System.IO
Imports DigitalData.Modules.Logging

Public Class ClsWindream_allgemein
    Dim Logger As Logger
#Region "+++++ Konstanten +++++"
    Const DEBUG = AUS
    Const AUS = 0
    Const WINDREAM = 1
    Const VARIABLEN = 2
#End Region

#Region "+++++ Variablen +++++"
    Public Shared oConnect ' der Typ darf nicht festgelegt werden (warum auch immer... geht sonst nicht)
    Public Shared oWMSession 'As WINDREAMLib.WMSession ' der Typ darf nicht festgelegt werden (warum auch immer... geht sonst nicht)
    Public Shared oBrowser As New WMOBRWSLib.ServerBrowser
    Public Shared oDokumentTypen As WINDREAMLib.WMObjects
    Private Shared oController As New WMOSearchController
#End Region

#Region "+++++ Allgemeine Methoden und Funktionen +++++"

    ''' <summary>
    ''' Konstruktor für die windream-Klasse
    ''' </summary>
    ''' <remarks></remarks>
    Sub New(MyLogger As LogConfig)
        Try
            Logger = MyLogger.GetLogger()
        Catch ex As Exception

        End Try

        ' wenn ein Fehler bei der Initialisierung auftrat
        If Not Init() Then
            ' Nachricht ausgeben
            Logger.Warn("Error while initializing Logger WM-Class!!")
            ' das Programm "abschießen"
            Process.GetCurrentProcess.Kill()
        End If
    End Sub


    ''' <summary>
    ''' Initialisiert die statische Klasse (Login, Session starten, usw.)
    ''' </summary>
    ''' <returns>Liefert True wenn das Anmelden erfolgreich war, sonst False</returns>
    ''' <remarks></remarks>
    Public Function Init() As Boolean
        Try
            Dim oHourDifference As Integer
            oHourDifference = CInt(DateDiff(DateInterval.Hour, CURRENToWMSession_Created, Now))

            If Not IsNothing(CURRENToWMSession) AndAlso CURRENToWMSession.aLoggedin AndAlso oHourDifference < 2 Then
                Logger.Debug("oWMSession already created!")
                oWMSession = CURRENToWMSession
                Return True
            End If

            Try
                'Session-Objekt instanziieren und mit dem im Client ausgewählten Server belegen
                oWMSession = CreateObject("Windream.WMSession", GetCurrentServer)
                ' Connection-Objekt instanziieren
                oConnect = CreateObject("Windream.WMConnect")

            Catch ex As Exception
                Logger.Warn("Could not create WMObjects Session or Connect: " & ex.Message)
                Return False
            End Try
            'wenn windream nicht angemeldet ist
            If Not IsLoggedIn() Then
                'Art der Anmeldung an windream festlegen
                '0x0L (also 0)                   = Standard windream Benutzer
                'WM_MODULE_ID_DOCTYPEEDITOR_LIC  = ermöglicht Zugriff auf die windream Management Funktionen (Z.B. zur Verwaltung der windream Dokumententypen, Auswahllisten, etc.)
                'WM_MODULE_ID_INDEXSERVICE       = ermöglicht der Session die Indexierungs-Events vom windream DMS-Service zu empfangen
                oConnect.ModuleID = 0
                'setzt die minimal erwartete windream-Version 
                oConnect.MinReqVersion = "3"
                ' Verbindung mit Session-Objekt (und dem ausgewählten Server) aufbauen
                oConnect.LoginSession(oWMSession)
                Logger.Debug("windream-UserName: '" & oConnect.UserName & "'")
                If oWMSession.aLoggedin = False Then
                    Logger.Warn("Es konnte keine Verbindung mit dem windream-Server hergestellt werden")
                    Return False
                End If

                Try
                    If Not IsNothing(oWMSession) Then
                        oWMSession.SwitchEvents(WMCOMEventWMSessionNeedIndex, False)
                        ' der Parameter WMEntityDocument definiert, dass nur Dokumenttypen und keine 
                        ' Ordnertypen ausgelesen werden
                        oDokumentTypen = oWMSession.GetWMObjectTypes(WINDREAMLib.WMEntity.WMEntityDocument)
                    Else
                        Logger.Warn("Unexpected...but the WMSession is nothing...")
                        Return False
                    End If

                Catch ex As Exception
                    Logger.Warn("Problem beim Auslesen der Objekttypen: " & ex.Message)
                    Return False
                End Try
            End If
            Logger.Debug("Alles OK - Erfolgreich angemeldet und Session aufgebaut")
            CURRENToWMSession = oWMSession
            CURRENToWMSession_Created = Now
            Return True
            'Else
            '    Logger.Debug("oWMSession already created!")
            '    oWMSession = CURRENToWMSession
            '    Return True
            'End If




        Catch ex As Exception
            Logger.Error(ex)
            Return False
        End Try
    End Function

#End Region



#Region "+++++ Funktionen die für den Objekttyp relevate Informationen zurückliefern +++++"

    ''' <summary>
    ''' Liefert alle Objekttypen des aktuellen Servers als windream-Objekte.
    ''' </summary>
    ''' <returns>Alle Objekttypen als WMObjects-Objekt</returns>
    ''' <remarks></remarks>
    Public Function GetObjecttypesAsObjects() As WMObjects
        Try

            Return oDokumentTypen

        Catch ex As Exception
            Logger.Warn("Fehler beim Auslesen der Objekttypen: " & ex.Message)
            'clsLogger.AddError("Fehler beim Auslesen der Objekttypen: " & ex.Message, "clswindream.GetObjecttypesAsObjects")
            Return Nothing
        End Try
    End Function

    ''' <summary>
    ''' Liefert alle Objekttypen des aktuellen Servers als Array aus Strings.
    ''' </summary>
    ''' <returns>Array mit allen Objekttypen als Strings</returns>
    ''' <remarks></remarks>
    Public Function GetObjecttypesAsStrings() As String()

        Try
            Dim objektTypenStr(oDokumentTypen.Count) As String

            For i As Integer = 0 To oDokumentTypen.Count
                objektTypenStr(i) = oDokumentTypen.Item(i).aName
            Next

            Return objektTypenStr

        Catch ex As Exception
            Logger.Error(ex)
            '
            Return Nothing
        End Try

    End Function

    ''' <summary>
    ''' Liefert alle Indexe eines Objekttypen.
    ''' </summary>
    ''' <param name="name">Name des Objekttyps</param>
    ''' <returns>Array mit allen Objekttyp zugeordneten Indexen als String</returns>
    ''' <remarks></remarks>
    Public Function GetIndicesByObjecttype(ByVal name As String) As String()
        Try
            Dim oObjectType As WMObject
            Dim oIndexAttributes As WMObjectRelation
            Dim oIndexAttribute As WMObject
            Dim oIndex As WMObject
            Dim oRelProperties As WMObjectRelationClass

            ' den Objekttyp laden
            oObjectType = oWMSession.GetWMObjectByName(WMEntityObjectType, name)

            ' Beziehung zu Indizes des Objekttyp auslesen
            oIndexAttributes = oObjectType.GetWMObjectRelationByName("TypeAttributes")

            ' Array für Indizes vorbereiten
            Dim aIndexNames(oIndexAttributes.Count - 1) As String

            ' alle Indizes durchlaufen
            For j As Integer = 0 To oIndexAttributes.Count - 1

                ' aktuellen Index auslesen
                oIndexAttribute = oIndexAttributes.Item(j)

                ' Eigenschaften des Index auslesen
                oRelProperties = oIndexAttribute.GetWMObjectRelationByName("Attribute")

                ' Index aus den Eigenschaften auslesen
                oIndex = oRelProperties.Item(0)

                ' Indexname speichern
                aIndexNames(j) = oIndex.aName
            Next

            ' Indexarray zurückgeben
            Return aIndexNames

        Catch ex As Exception
            Logger.Error(ex)

            Return Nothing
        End Try
    End Function
    ''' <summary>
    ''' Liefert einen Objekttyp als WMObject an Hand dessen Name.
    ''' </summary>
    ''' <param name="objekttypName">Name des Objekttyps</param>
    ''' <returns>Objekttyp als WMObject</returns>
    ''' <remarks></remarks>
    Public Function GetObjecttypeByName(ByVal objekttypName As String) As WMObject
        Try
            ' alle Objekttypen auslesen
            Dim oObjectTypes As WMObjects = oWMSession.GetWMObjectTypes(WINDREAMLib.WMEntity.WMEntityDocument)

            ' alle Objekttypen durchlaufen und nach dem mit dem angegebenen Namen suchen
            For Each oObjectType As WMObject In oObjectTypes
                If oObjectType.aName = objekttypName Then
                    Return oObjectType
                End If
            Next

            Return Nothing

        Catch ex As Exception
            Logger.Error(ex)

            Return Nothing
        End Try
    End Function

    ''' <summary>
    ''' Überprüft ob der angegebene Index im Objekttyp existiert
    ''' </summary>
    ''' <param name="objekttyp">Name des zu durchsuchenden Objekttyps</param>
    ''' <param name="indexname">Name des zu suchenden Indexes</param>
    ''' <returns>Liefert True wenn der Index im Objekttyp existiert, sonst False</returns>
    ''' <remarks></remarks>
    Public Function ExistIndexInObjekttyp(ByVal objekttyp As String, ByVal indexname As String) As Boolean
        Try
            Dim indexnamen() As String = GetIndicesByObjecttype(objekttyp)

            If indexnamen Is Nothing Then Return False

            For Each index As String In indexnamen
                If index = indexname Then Return True
            Next
            Logger.Warn($"Index '{indexname}' does not exist in Objecttype '{objekttyp}'")
            Return False
        Catch ex As Exception
            Logger.Error(ex)

            Return False
        End Try
    End Function

#End Region

#Region "+++++ Allgemeine Funktionen die Informationen zurückliefern +++++"

    ''' <summary>
    ''' Liefert True wenn die windream-Session angemeldet ist und False für den Fall, dass die Session nicht eingeloggt ist.
    ''' </summary>
    ''' <returns>Anmeldestatus als Boolean</returns>
    ''' <remarks></remarks>
    Public Function IsLoggedIn() As Boolean
        Try
            Return oWMSession.aLoggedin
        Catch ex As Exception
            Logger.Error(ex)
        End Try

        Return False
    End Function

    ''' <summary>
    ''' Liefert den Servernamen an dem windream aktuell angemeldet ist.
    ''' </summary>
    ''' <returns>Servername als String</returns>
    ''' <remarks></remarks>
    Public Function GetCurrentServer() As String
        Try
            Logger.Debug(oBrowser.GetCurrentServer.ToString)
            Return oBrowser.GetCurrentServer
        Catch ex As Exception
            Logger.Error(ex)
        End Try

        Return ""
    End Function

    'Public Function GetSharedCurrentServer() As String
    '    Try
    '        Return ClassWindream.oBrowser.GetCurrentServer
    '    Catch ex As Exception
    '        MsgBox("Der aktuell gewählte windream-Server konnte nicht ausgelesen werden." & vbNewLine & vbNewLine & "Fehlernachricht:" & vbNewLine & ex.Message, MsgBoxStyle.Critical, "Fehler beim Auslesen des windream-Servers")
    '    End Try

    '    Return ""
    'End Function


    'Liefert das Windream-Laufwerk des windream-Servers, in Form '[Laufwerksbuchstabe]:'. (z.B. 'W:')
    'Laufwerksbuchstabe mit Doppelpunkt als String</returns>
    '
    'Public Function GetWindreamDriveLetter() As String

    '    Try
    '        Dim oControl As AISCONTROLDATACOMLib.AISControlData
    '        Dim sDrive As String = ""

    '        '        oControl = New AISCONTROLDATACOMLib.AISControlData

    '        '        sDrive = oControl.GetStringValue(&H10040003)

    '        '        Return sDrive & ":"

    '    Catch ex As Exception

    '    End Try

    '    Return ""
    'End Function

    ''' <summary>
    ''' Liefert den Typen eines Indexes als Integer.
    ''' </summary>
    ''' <param name="indexname">Name des zu überprüfenden Indexfeldes</param>
    ''' <returns>Liefert eine Zahl, die einen Typen beschreibt</returns>
    ''' <remarks></remarks>
    Public Shared Function GetTypeOfIndexAsIntByName(ByVal indexname As String) As Integer
        Try
            Dim oAttribute = oWMSession.GetWMObjectByName(WINDREAMLib.WMEntity.WMEntityAttribute, indexname)
            Dim vType = oAttribute.getVariableValue("dwAttrType")
            Return vType
        Catch ex As Exception
            Return Nothing
        End Try
    End Function
    Public Function GetValuesfromAuswahlliste(ByVal indexname As String) As Object
        Try
            'Dim oAttribute = oSession.GetWMObjectByName(WINDREAMLib.WMEntity.WMEntityAttribute, indexname)
            'Dim vType = oAttribute.getVariableValue("vItems")
            'Return vType
            Dim oChoiceList = oWMSession.GetWMObjectByName(WMEntityChoiceList, indexname)
            If Err.Number = 0 And TypeName(oChoiceList) <> "Nothing" Then
                Dim Values = oChoiceList
                Values = oChoiceList.GetVariableValue("vItems")
                Dim anz As Integer = 0

                For Each CLItem In Values
                    If oChoiceList.aName IsNot Nothing Then
                        anz += 1
                    End If
                Next
                Dim strListe(anz - 1)
                Dim zahl As Integer = 0
                For Each CLItem In Values
                    If oChoiceList.aName IsNot Nothing Then
                        strListe(zahl) = CLItem
                        zahl += 1
                    End If
                Next
                Return strListe
            Else
                Logger.Warn("Auswahlliste: " & indexname & " nicht gefunden.")
                Return Nothing
            End If

        Catch ex As Exception
            Logger.Error(ex)
            Return Nothing
        End Try
    End Function
    Public Function WDObject_exists(wdobj_location As String)
        Dim WDObject As WMObject
        Try
            WDObject = oWMSession.GetWMObjectByPath(WINDREAMLib.WMEntity.WMEntityDocument, wdobj_location.Substring(2))
            If WDObject Is Nothing Then
                Return False
            Else
                Logger.Debug("WDObject exists")
                Return True

            End If
        Catch ex As Exception
            ' bei einem Fehler einen Eintrag in der Logdatei machen
            Logger.Error(ex)
            Return False
        End Try
    End Function
    Public Function GetSearchDocuments(ByVal wdfLocation As String)
        'wdfLocation = 'W:\System\Suchen\WDRH\TestPDF.wdf'
        Try
            If IsNothing(CURRENToWMSession) Then
                Logger.Warn("oWMSession is unexpected nothing...Try to create it")
                If Init() = False Then
                    Logger.Warn("Could not recreate oWMSession...EXIT")
                    Return Nothing
                End If
            End If
            Dim SearchName = wdfLocation.Substring(wdfLocation.LastIndexOf("\") + 1)
            Dim SearchPath = wdfLocation.Substring(0, wdfLocation.Length - SearchName.Length)
            Logger.Debug("WMSearch: " & wdfLocation.ToLower)
            If System.IO.File.Exists(wdfLocation.ToLower) Then
                Logger.Debug("Search exists")
            End If
            oController.CheckSearchProfile(wdfLocation.ToLower) 'wdfLocation.ToLower)
            Logger.Debug("oController erzeugt")
            Dim suchTyp = oController.SearchProfileTargetProgID
            Dim ExSettings As Object
            Dim oSearch As Object
            ExSettings = oController.SearchProfileExSettings
            If ExSettings = 0 Then ExSettings = 7

            Dim srchQuick As WMOSRCHLib.WMQuickSearch = CreateObject("WMOSrch.WMQuickSearch")
            Dim srchIndex As WMOSRCHLib.WMIndexSearch = CreateObject("WMOSrch.WMIndexSearch")
            Dim srchObjectType As WMOSRCHLib.WMObjectTypeSearch = CreateObject("WMOSrch.WMObjectTypeSearch")
            Logger.Debug("WD Objekte in GetSearchDocuments erzeugt")
            Logger.Debug(suchTyp.ToString.ToUpper)
            ''  Der öffentliche Member CheckSearchProfile für den Typ IWMQuickSearch7 wurde nicht gefunden. [Microsoft.VisualBasic] => GetSearchDocuments()
            Select Case suchTyp.ToString.ToUpper
                Case "WMOSRCH.WMQUICKSEARCH"
                    srchQuick.WMSession = CURRENToWMSession
                    srchQuick.ClearSearch()
                    srchQuick.SearchProfilePath = SearchPath
                    srchQuick.LoadSearchProfile(SearchName)
                    oSearch = srchQuick.GetSearch()

                Case "WMOSRCH.WMINDEXSEARCH"
                    srchIndex.WMSession = CURRENToWMSession
                    srchIndex.ClearSearch()
                    srchIndex.SearchProfilePath = SearchPath
                    srchIndex.LoadSearchProfile(SearchName)
                    oSearch = srchIndex.GetSearch()

                Case "WMOSRCH.WMOBJECTTYPESEARCH"
                    srchObjectType.WMSession = CURRENToWMSession
                    srchObjectType.ClearSearch()
                    srchObjectType.SearchProfilePath = SearchPath
                    srchObjectType.LoadSearchProfile(SearchName)
                Case Else
                    Logger.Warn("KEIN GÜLTIGER WINDREAM-SUCHTYP")
                    Return Nothing
            End Select
            Dim WMObjects As Object
            WMObjects = oSearch.Execute
            Logger.Debug("WD Objekte werden zurückgegeben")
            Return oSearch.execute
        Catch ex As Exception
            Logger.Error(ex)
            Logger.Warn($"WM-SEARCH in Exception ({wdfLocation})")
            Return Nothing
        End Try

    End Function
    Public Function GetSearchDocumentsDT(ByVal wdfLocation As String, NameIndexDocID As String, NameIndexCreated As String, WMSearchLocal As Boolean) As DataTable
        Dim dtresult As New DataTable
        dtresult.Columns.Add("DOC_ID", GetType(Integer))
        dtresult.Columns.Add("PATH", GetType(String))
        dtresult.Columns.Add("CREATED", GetType(String))
        Logger.Debug($"Executing WMSearch: {wdfLocation}...")
        Try
            Dim SearchName = wdfLocation.Substring(wdfLocation.LastIndexOf("\") + 1)
            Dim SearchPath = wdfLocation.Substring(0, wdfLocation.Length - SearchName.Length)
            Dim oWMSZPath
            If WMSearchLocal = False Then
                oWMSZPath = wdfLocation.Substring(2).ToLower
            Else
                oWMSZPath = wdfLocation.ToLower
            End If

            Logger.Debug("oWMSZPath: " & oWMSZPath)
            Try
                oController.CheckSearchProfile(oWMSZPath) 'wdfLocation.ToLower)
            Catch ex As Exception
                Dim msg As String = ex.Message
                Try
                    If WMSearchLocal = True Then
                        Logger.Error(ex)
                        Return dtresult
                    End If

                    Logger.Debug("Unexpected Error in Creating oController: " & msg)
                    Logger.Debug("...NOW trying to implement \\windream\Objects ...")
                    Dim WmSearch_wmobject = "\\windream\Objects" & oWMSZPath
                    WmSearch_wmobject = WmSearch_wmobject.ToLower
                    oController.CheckSearchProfile(WmSearch_wmobject) 'wdfLocation.ToLower)
                Catch ex1 As Exception
                    Logger.Warn("UnexpectedError im CreateController: " & msg)
                    Logger.Error(ex1)
                    Return dtresult
                End Try

            End Try

            Logger.Debug("oController erzeugt")
            Dim suchTyp = oController.SearchProfileTargetProgID
            Dim ExSettings As Object
            Dim oSearch As Object
            ExSettings = oController.SearchProfileExSettings
            If ExSettings = 0 Then ExSettings = 7

            Dim srchQuick As WMOSRCHLib.WMQuickSearch = CreateObject("WMOSrch.WMQuickSearch")
            Dim srchIndex As WMOSRCHLib.WMIndexSearch = CreateObject("WMOSrch.WMIndexSearch")
            Dim srchObjectType As WMOSRCHLib.WMObjectTypeSearch = CreateObject("WMOSrch.WMObjectTypeSearch")
            Logger.Debug("WMObjekte in GetSearchDocumentsDT erzeugt")
            Logger.Debug(suchTyp.ToString.ToUpper)

            Select Case suchTyp.ToString.ToUpper
                Case "WMOSRCH.WMQUICKSEARCH"
                    srchQuick.WMSession = CURRENToWMSession
                    srchQuick.ClearSearch()
                    srchQuick.SearchProfilePath = SearchPath
                    srchQuick.LoadSearchProfile(SearchName)
                    oSearch = srchQuick.GetSearch()

                Case "WMOSRCH.WMINDEXSEARCH"
                    srchIndex.WMSession = CURRENToWMSession
                    srchIndex.ClearSearch()
                    srchIndex.SearchProfilePath = SearchPath
                    srchIndex.LoadSearchProfile(SearchName)
                    oSearch = srchIndex.GetSearch()

                Case "WMOSRCH.WMOBJECTTYPESEARCH"
                    srchObjectType.WMSession = CURRENToWMSession
                    srchObjectType.ClearSearch()
                    srchObjectType.SearchProfilePath = SearchPath
                    srchObjectType.LoadSearchProfile(SearchName)
                Case Else
                    Logger.Warn("KEIN GÜLTIGER WINDREAM-SUCHTYP")
                    Return Nothing
            End Select
            Dim WMObjects As Object
            WMObjects = oSearch.Execute
            'If returnDT = True Then
            If WMObjects.Count > 0 Then

                For Each dok As WMObject In WMObjects
                    Dim oDOC_ID = dok.GetVariableValue(NameIndexDocID)
                    Dim oCreated = dok.GetVariableValue(NameIndexCreated)
                    Logger.Debug($"Adding DocInfo {oDOC_ID.ToString}|{dok.aPath}|{oCreated}")
                    Dim oPath As String
                    If dok.aPath.StartsWith("\") Then
                        oPath = dok.aPath.Substring(1, dok.aPath.Length - 1)
                    Else
                        oPath = dok.aPath
                    End If


                    dtresult.Rows.Add(oDOC_ID, oPath, oCreated)
                Next
                dtresult.AcceptChanges()
            End If
            Return dtresult
        Catch ex As Exception
            Logger.Error(ex)
            Logger.Warn($"WM-SEARCH from GetSearchDocumentsDT ({wdfLocation})")
            Return dtresult
        End Try
    End Function
    Public Function TestFileExists(Path As String) As Boolean
        Return TestObjectExists(GetNormalizedPath(Path), WMEntityDocument)
    End Function
    Private Function TestObjectExists(ObjectName As String, ObjectType As WMEntity) As Boolean
        Try
            Dim oObjectId = 0
            Dim oObjectDbId = 0

            Return CURRENToWMSession.WMObjectExists(ObjectType, ObjectName, oObjectId, oObjectDbId)
        Catch ex As Exception
            Logger.Error(ex, "Error while checking existence of WMObject {0} of type {1}", ObjectName, ObjectType.ToString)
            Return False
        End Try
    End Function
    Private Function GetNormalizedPath(Path As String) As String
        Dim oNormalizedPath = Path

        If Not Path.StartsWith("\") And Path.ToUpper().StartsWith(CURRENT_WMDriveLetter.ToUpper) Then
            oNormalizedPath = Path.Substring(2)
        End If

        Return oNormalizedPath
    End Function
#End Region

End Class

