Imports System.IO
Imports System.Net
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports DigitalData.Modules.Logging
Imports Newtonsoft.Json

Public Class GraphQLInterface
    Private _logConfig As LogConfig
    Private _logger As Logger
    Private _baseUrl As String
    Private _userEmail As String
    Private _userPassword As String
    Private _certificate As X509Certificate
    Private _cookieJar As CookieContainer

    Private _Encoding As New UTF8Encoding

    Public Sub New(LogConfig As LogConfig, BaseUrl As String, Email As String, Password As String, CertificateFile As String, CertificatePassword As String)
        Try
            _logConfig = LogConfig
            _logger = LogConfig.GetLogger()
            _baseUrl = BaseUrl
            _userEmail = Email
            _userPassword = Password

            _certificate = New X509Certificate(CertificateFile, CertificatePassword)
        Catch ex As Exception
            _logger.Error(ex)
        End Try
    End Sub

    Public Sub SaveCookies(Cookie As Cookie)
        GetCookies().Add(Cookie)
    End Sub

    Public Function Login() As HttpWebResponse
        Try
            Dim oLoginData As New LoginData() With {.email = _userEmail, .token = _userPassword}
            Dim oBytes As Byte() = ToBytes(JsonConvert.SerializeObject(oLoginData))
            Dim oRequest As HttpWebRequest = GetRequest("/login", oBytes)

            Using oStream = oRequest.GetRequestStream()
                oStream.Write(oBytes, 0, oBytes.Length)
            End Using

            Return oRequest.GetResponse()
        Catch ex As Exception
            _logger.Error(ex)
            Throw ex
        End Try
    End Function

    Public Function Logout() As HttpWebResponse
        Try
            Dim oLogoutData As New LogoutData() With {.email = _userEmail}
            Dim oBytes As Byte() = ToBytes(JsonConvert.SerializeObject(oLogoutData))
            Dim oRequest As HttpWebRequest = GetRequest("/logout", oBytes)

            Using stream = oRequest.GetRequestStream()
                stream.Write(oBytes, 0, oBytes.Length)
            End Using

            Return oRequest.GetResponse()
        Catch ex As Exception
            _logger.Error(ex)
            Throw ex
        End Try
    End Function

    Public Function GetData(Query As String, OperationName As String) As HttpWebResponse
        Try
            Dim oQueryData As New QueryData() With {
                       .OperationName = OperationName,
                       .Query = Query,
                       .Variables = New Object
                   }
            Dim oBytes = ToBytes(JsonConvert.SerializeObject(oQueryData))
            Dim oRequest = GetRequest("/graphql", oBytes)

            Using stream = oRequest.GetRequestStream()
                stream.Write(oBytes, 0, oBytes.Length)
            End Using

            Return oRequest.GetResponse()
        Catch ex As Exception
            _logger.Error(ex)
            Throw ex
        End Try
    End Function

    Private Function GetRequest(Url As String, PostData As Byte()) As HttpWebRequest
        Try
            Dim oRequest As HttpWebRequest = WebRequest.Create($"{_baseUrl}{Url}")
            oRequest.Method = "POST"
            oRequest.ContentType = "application/json"
            oRequest.ContentLength = PostData.Length
            oRequest.ClientCertificates.Add(_certificate)
            oRequest.CookieContainer = GetCookies()

            Return oRequest
        Catch ex As Exception
            _logger.Error(ex)
            Throw ex
        End Try
    End Function

    Private Function GetCookies() As CookieContainer
        If _cookieJar Is Nothing Then
            _cookieJar = New CookieContainer()
        End If

        Return _cookieJar
    End Function

    Private Function ToBytes(Str As String) As Byte()
        Return _Encoding.GetBytes(Str)
    End Function
End Class
