Imports System.IO
Imports DigitalData.Modules.EDMI.API
Imports DigitalData.Modules.EDMI.API.Client
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Base.IDB
Imports DigitalData.Modules.ZooFlow.Constants
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.ZooFlow

Namespace DocumentResultList

    Public Class Loader
        Inherits BaseClass

        Private ReadOnly Client As Client
        Private ReadOnly Mode As OperationMode
        Private ReadOnly User As State.UserState

        Private ReadOnly Cache As Cache

        Public Sub New(pLogConfig As LogConfig, pMode As OperationMode, pClient As Client, pUser As State.UserState)
            MyBase.New(pLogConfig)
            Client = pClient
            Mode = pMode
            User = pUser

            ' Set up cache with capacity of 100 MB
            Cache = New Cache(pLogConfig, 104_900_000)
        End Sub

        ''' <summary>
        ''' Removes a Document from the cache
        ''' </summary>
        Public Sub Invalidate(pDocument As Document)
            Cache.Remove(pDocument)
        End Sub

        ''' <summary>
        ''' Clears the cache completely
        ''' </summary>
        Public Sub ClearCache()
            Cache.Clear()
        End Sub

        Public Function Load(pObjectId As Long, pFullPath As String, Optional pForce As Boolean = False) As Document
            Dim oDocument As Document = Nothing

            If Cache.Contains(pObjectId) And pForce = False Then
                Return Cache.Where(Function(doc) doc.Id = pObjectId).Single()
            End If

            Select Case Mode
                Case OperationMode.NoAppServer
                    oDocument = Load_FromWindream(pObjectId, pFullPath)

                Case OperationMode.WithAppServer
                    oDocument = Load_FromIDB(pObjectId)

                Case OperationMode.ZooFlow
                    oDocument = Load_FromZooflow(pObjectId)

                Case Else
                    oDocument = Nothing
            End Select

            If oDocument IsNot Nothing Then
                Cache.Add(oDocument)
            End If

            Return oDocument
        End Function

        Private Function Load_FromWindream(pObjectId As Long, pFullPath As String) As Document
            Dim oFileInfo As New FileInfo(pFullPath)
            Dim oResultDocumentInfo = New Document(pObjectId) With {
                .Contents = Load_FromDisk(pFullPath),
                .AccessRight = Rights.AccessRight.FULL,
                .FullPath = pFullPath,
                .Extension = oFileInfo.Extension.Substring(1)
            }

            Return oResultDocumentInfo
        End Function

        Private Function Load_FromIDB(pObjectId As Long) As Document
            Try
                Dim oDocumentInfo As DocumentInfo = Client.GetDocumentInfo(User.UserId, pObjectId)
                Dim oFileInfo As New FileInfo(oDocumentInfo.FullPath)

                ' Load System Attributes
                Dim oDoctype As VariableValue = Client.GetVariableValue(pObjectId, Attributes.ATTRIBUTE_DOCTYPE)
                Dim oDisplayFileName As VariableValue = Client.GetVariableValue(pObjectId, Attributes.ATTRIBUTE_DISPLAY_FILENAME)

                Dim oResultDocumentInfo As New Document(pObjectId) With {
                    .Contents = Load_FromDisk(oDocumentInfo.FullPath),
                    .AccessRight = oDocumentInfo.AccessRight,
                    .FullPath = oDocumentInfo.FullPath,
                    .Extension = oFileInfo.Extension.Substring(1),
                    .DocumentType = oDoctype.Value,
                    .DisplayFileName = oDisplayFileName.Value
                }

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

        Private Function Load_FromZooflow(pObjectId As Long) As Document
            Dim oFileObject As FileObject = Client.Zooflow_GetFileObject(pObjectId, pLoadFileContents:=True)

            If oFileObject Is Nothing Then
                Return Nothing
            End If

            ' Load System Attributes
            Dim oDoctype As VariableValue = Client.GetVariableValue(pObjectId, Attributes.ATTRIBUTE_DOCTYPE)
            Dim oDisplayFileName As VariableValue = Client.GetVariableValue(pObjectId, Attributes.ATTRIBUTE_DISPLAY_FILENAME)

            Dim oResultDocumentInfo As New Document(pObjectId) With {
                .Contents = oFileObject._FileContents,
                .Extension = oFileObject._FileExtension,
                .AccessRight = Rights.AccessRight.FULL,
                .FileHash = oFileObject._FileHash,
                .FullPath = Nothing,
                .DocumentType = oDoctype.Value,
                .DisplayFileName = oDisplayFileName.Value
            }

            Return oResultDocumentInfo
        End Function

        Private Function Load_FromDisk(pFullPath) As Byte()
            Try
                Logger.Debug("Loading file [{0}]", pFullPath)
                Using oStream = File.OpenRead(pFullPath)
                    Using oMemoryStream = New MemoryStream()
                        oStream.CopyTo(oMemoryStream)
                        Logger.Debug("Loaded file [{0}] successfully.", pFullPath)
                        Return oMemoryStream.ToArray()
                    End Using
                End Using
            Catch ex As Exception
                Logger.Warn("Loading file [{0}] failed.", pFullPath)
                Logger.Error(ex)
                Return Nothing
            End Try
        End Function
    End Class
End Namespace
