Imports System.Data.SqlClient
Imports NLog

Public Class DB
    Private _connstring
    Private _db
    Private _logger As Logger

    Public FormId
    Public ControlId
    Public RecordId
    Public Username As String = "DPMA Importer"


    Public Sub New(connectionString As String, dbname As String)
        _logger = LogManager.GetLogger("DB")
        _connstring = connectionString
        _db = dbname
    End Sub

#Region "=== HELPERS ==="
    Public Function formatTable(table As String) As String
        Return String.Format("[{0}].[dbo].[{1}]", _db, table)
    End Function

    Public Function GetFormIdFor(entityName As String) As Integer
        Dim sql = String.Format("SELECT GUID FROM {0} WHERE NAME = '{1}'", Me.formatTable("TBPMO_FORM"), entityName)
        Return Me.Scalar(sql)
    End Function

    Public Function GetControlId(formId As Integer, Optional name As String = "ApplicationNumber") As Integer
        Dim sql = String.Format("SELECT GUID FROM {0} WHERE NAME = '{1}' AND FORM_ID = {2}", Me.formatTable("TBPMO_CONTROL"), name, formId)
        Return Me.Scalar(sql)
    End Function

    Public Function GetPropertyMark(m As Mark, propertyName As String) As Object
        _logger.Debug("Reading property: {0}, Mark? {1}", propertyName, IsNothing(m))
        Dim value = CallByName(m, propertyName, CallType.Get)
        If (value = Nothing) Then
            value = DBNull.Value
        End If

        Return value
    End Function

    Public Function GetPropertyPatent(p As Patent, propertyName As String) As Object
        _logger.Debug("Reading property: {0}, Patent? {1}", propertyName, IsNothing(p))
        Dim value = CallByName(p, propertyName, CallType.Get)
        If (value = Nothing) Then
            value = DBNull.Value
        End If

        Return value
    End Function

    Public Function IsEqual(controlId As Integer, recordId As Integer, valueToCompare As Object)
        Dim table = Me.formatTable("TBPMO_CONTROL_VALUE")
        Dim sql = String.Format("SELECT VALUE FROM {0} WHERE CONTROL_ID = {1} AND RECORD_ID = {2}", table, controlId, recordId)
        Dim value = Me.Scalar(sql)

        If (IsDBNull(valueToCompare) Xor IsDBNull(value)) Then
            Return False
        End If

        Return value = valueToCompare
    End Function
#End Region
    
#Region "=== RECORD ID ==="
    Public Function GetRecordId(controlId As Integer, applicationNumber As String) As Integer
        Dim sql = String.Format("SELECT RECORD_ID FROM {0} WHERE CONTROL_ID = {1} AND VALUE = '{2}'", Me.formatTable("TBPMO_CONTROL_VALUE"), controlId, applicationNumber)
        Return Me.Scalar(sql)
    End Function

    Public Function InsertRecord(formId As Integer)
        Dim sql = String.Format("INSERT INTO {0} (FORM_ID, ADDED_WHO, RECORD_ENTITY_ID, PARENT_RECORD) VALUES ({1}, '{2}', {1}, 0)", Me.formatTable("TBPMO_RECORD"), formId, Username)
        Me.NonQuery(sql)
        Return Me.Scalar("SELECT MAX(GUID) FROM TBPMO_RECORD")
    End Function
#End Region

#Region "=== VALUES ==="
    Public Function InsertValue(controlId As Integer, recordId As Integer, value As Object)
        Dim table = Me.formatTable("TBPMO_CONTROL_VALUE")
        Dim sql = String.Format("INSERT INTO {0} (CONTROL_ID, RECORD_ID, VALUE, ADDED_WHO) VALUES ({1}, {2}, '{3}', '{4}')", table, controlId, recordId, value, Username)
        Me.NonQuery(sql)
        Return Me.Scalar(String.Format("SELECT MAX(GUID) FROM {0} WHERE CONTROL_ID = {1}", table, controlId))
    End Function

    Public Sub UpdateValue(controlId As Integer, recordId As Integer, value As Object)
        Dim table = Me.formatTable("TBPMO_CONTROL_VALUE")
        Dim sql = String.Format("UPDATE {0} SET VALUE = '{1}', CHANGED_WHO = '{4}' WHERE CONTROL_ID = {2} AND RECORD_ID = {3} ", table, value, controlId, recordId, Username)
        Me.NonQuery(sql)
    End Sub
#End Region
    
#Region "=== DATABASE ==="
    Public Function Scalar(queryString As String)
        Dim conn As New SqlConnection(_connstring)
        Dim cmd As New SqlCommand(queryString, conn)
        Dim result

        Try
            conn.Open()

            result = cmd.ExecuteScalar()
            conn.Dispose()
            conn.Close()

            Return result
        Catch ex As Exception
            Throw New Exception(String.Format("Error while executing SQL Scalar-Query ({0}): {1}", queryString, ex.Message))
        End Try
    End Function


    Public Function NonQuery(queryString As String)
        Dim conn As New SqlConnection(_connstring)
        Dim cmd As New SqlCommand(queryString, conn)

        Try
            conn.Open()

            cmd.ExecuteNonQuery()
            conn.Dispose()
            conn.Close()

            Return True
        Catch ex As Exception
            Throw New Exception(String.Format("Error while executing SQL Non-Query ({0}): {1}", queryString, ex.Message))
        End Try
    End Function

    Public Function QueryTable(queryString As String) As DataTable
        Try
            Dim conn As New SqlConnection(_connstring)
            Dim cmd As New SqlCommand(queryString, conn)
            Dim adapter As New SqlDataAdapter(cmd)
            Dim dt As New DataTable()

            conn.Open()
            adapter.Fill(dt)
            conn.Dispose()
            conn.Close()

            Return dt
        Catch ex As Exception
            Throw New Exception(String.Format("Error while executing SQL Query ({0}): {1}", queryString, ex.Message))
        End Try
    End Function
#End Region

#Region "=== IMAGES ==="
    Public Sub InsertImage(bimage As Byte(), ControlId As Integer, RecordId As Integer)
        Dim table = Me.formatTable("TBPMO_CONTROL_IMAGE")
        Dim sql = String.Format("INSERT INTO {0} (CONTROL_ID, RECORD_ID, IMG) VALUES (@CONTROL_ID, @RECORD_ID, @IMG)", table)
        Dim conn As New SqlClient.SqlConnection(_connstring)
        Dim cmd As New SqlClient.SqlCommand(sql, conn)

        cmd.Parameters.Add("@IMG", SqlDbType.Binary).Value = bimage
        cmd.Parameters.Add("@CONTROL_ID", SqlDbType.Int).Value = ControlId
        cmd.Parameters.Add("@RECORD_ID", SqlDbType.Int).Value = RecordId

        conn.Open()
        cmd.ExecuteNonQuery()
        conn.Close()
    End Sub

    Public Sub UpdateImage(bimage As Byte(), ControlId As Integer, RecordId As Integer)
        Dim table = Me.formatTable("TBPMO_CONTROL_IMAGE")
        Dim sql = String.Format("UPDATE {0} SET IMG = @IMG WHERE CONTROL_ID = @CONTROL_ID AND RECORD_ID = @RECORD_ID", table)
        Dim conn As New SqlClient.SqlConnection(_connstring)
        Dim cmd As New SqlClient.SqlCommand(sql, conn)

        cmd.Parameters.Add("@IMG", SqlDbType.Binary).Value = bimage
        cmd.Parameters.Add("@CONTROL_ID", SqlDbType.Int).Value = ControlId
        cmd.Parameters.Add("@RECORD_ID", SqlDbType.Int).Value = RecordId

        conn.Open()
        cmd.ExecuteNonQuery()
        conn.Close()
    End Sub
#End Region
End Class
