Imports System.Net
Imports System.Net.Mail
Imports System.Drawing
Imports System.Windows.Forms
Imports System.IO
Imports System.Drawing.Imaging
Imports System.Net.Mime

<CLSCompliant(True)> _
Public Class ErrorLogger

    Public Const GOOGLEMAIL As String = "smtp.gmail.com"
    Public Const YAHOOMAIL As String = "smtp.mail.yahoo.com"
    Public Const HOTMAIL As String = "smtp.live.com"
    Public Const MSNMAIL As String = "smtp.email.msn.com"
    Public Const AOLMAIL As String = "smtp.aol.com"

    Dim _errorLogDirectoryName As String = "\ErrorLogs\"                    'Directory name to error log
    Dim _errorLogName As String = "RecipeHolderErrorLog.txt"                'File name of the error log
    Dim _applicationName As String = Application.ProductName                'Application name
    Dim _attachmentPathToDelete As String                                   'Attachment path of the e-mail that is to be deleted

    Sub New()

    End Sub

    Public Overloads Sub sendEMail(ByVal from As String, ByVal recipient As String, _
                          ByVal subject As String, ByVal body As String, ByVal bodyHTMLFormat As Boolean, _
                           ByVal smtpClientName As String)

        Dim smtpMailClient As New SmtpClient(smtpClientName)                                'E-Mail client that setups up and sends e-mail
        Dim fromAddress As New System.Net.Mail.MailAddress(from)                            'E-Mail is from....
        Dim message As MailMessage = New MailMessage()                                      'E-mail to be sent
        Dim userState As Object                                                             'Mail message to pass to smtpMailClient.SendCompleted

        Try
            'setup the e-mail message
            With message
                .IsBodyHtml = bodyHTMLFormat
                .From = fromAddress
                .To.Add(recipient)
                .Subject = subject
                .Body = body
            End With

            'Wire the Complete method of the smtp client to custom method, add the message to userstate
            AddHandler smtpMailClient.SendCompleted, AddressOf sendMailCompleted
            userState = message

            'setup Credentials, method of delivery and send the e-mail, delete file on hard drive
            smtpMailClient.Credentials = New Net.NetworkCredential("applicationtester80@gmail.com", "mar238060123")
            smtpMailClient.DeliveryMethod = SmtpDeliveryMethod.Network
            smtpMailClient.SendAsync(message, userState)

        Catch ex As Net.Mail.SmtpException
            MessageBox.Show(ex.Message)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        Finally
            fromAddress = Nothing
            smtpMailClient = Nothing
        End Try
    End Sub

    ''' <summary>
    ''' Sends an e-mail with a jpeg attachment of the screen shot. Used for any errors that would occur in the program.
    ''' </summary>
    ''' <param name="screenToCapture">The screen to capture into a jpeg to send along with the e-mail</param>
    ''' <param name="from">The person sending the e-mail applicationtester80@gmail.com</param>
    ''' <param name="recipient">The person receiving the e-mail boss80pv@yahoo.com</param>
    ''' <param name="subject">The subject of the e-mail</param>
    ''' <param name="body">The body of the e-mail</param>
    ''' <param name="bodyHTMLFormat">True if the body of the e-mail can be in HTML format</param>
    ''' <param name="smtpClientName">The host name where the e-mail is being sent out(smtp.gmail.com)</param>
    ''' <remarks></remarks>
    Public Overloads Sub sendEMail(ByVal screenToCapture As Screen, ByVal from As String, ByVal recipient As String, _
                          ByVal subject As String, ByVal body As String, ByVal bodyHTMLFormat As Boolean, _
                           ByVal smtpClientName As String)

        Dim smtpMailClient As New SmtpClient(smtpClientName)                                'E-Mail client that setups up and sends e-mail
        Dim fromAddress As New System.Net.Mail.MailAddress(from)                            'E-Mail is from....
        Dim message As MailMessage = New MailMessage()                                      'E-mail to be sent
        Dim userState As Object                                                             'Mail message to pass to smtpMailClient.SendCompleted
        Dim attachmentFilePath As String = snapScreenShot(screenToCapture)                  'Take snapshot of the screen for the error message
        Dim fileStr As New FileStream(attachmentFilePath, FileMode.Open, FileAccess.Read)   'Holds the file to attach

        'Setup the attachment to be deleted in the smtpMailClient.SendCompleted method
        _attachmentPathToDelete = attachmentFilePath

        Try
            'setup the e-mail message
            With message
                .IsBodyHtml = bodyHTMLFormat
                .From = fromAddress
                .To.Add(recipient)
                .Subject = subject
                .Body = body
            End With

            'Wire the Complete method of the smtp client to custom method, add the message to userstate
            'add attachment to the e-mail message
            AddHandler smtpMailClient.SendCompleted, AddressOf sendMailCompleted
            userState = message
            message.Attachments.Add(New Attachment(fileStr, "", MediaTypeNames.Image.Jpeg))

            'setup Credentials, method of delivery and send the e-mail, delete file on hard drive
            smtpMailClient.Credentials = New Net.NetworkCredential("applicationtester80@gmail.com", "mar238060123")
            smtpMailClient.DeliveryMethod = SmtpDeliveryMethod.Network
            smtpMailClient.SendAsync(message, userState)

        Catch ex As Net.Mail.SmtpException

        Catch ex As Exception
            MessageBox.Show(ex.Message)
        Finally
            fromAddress = Nothing
            smtpMailClient = Nothing
        End Try

    End Sub

    ''' <summary>
    ''' Lets user know that the e-mail was sent, error occured or the e-mail was cancelled
    ''' </summary>
    ''' <param name="sender">Object that sent the event</param>
    ''' <param name="e">Data to the event</param>
    ''' <remarks></remarks>
    Private Sub sendMailCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
        'Get the Original MailMessage object
        Dim mail As MailMessage = CType(e.UserState, MailMessage)

        'write out the subject
        Dim subject As String = mail.Subject

        If e.Cancelled Then
            Console.WriteLine("Send canceled for mail with subject [{0}].", subject)
        End If
        If Not (e.Error Is Nothing) Then
            Console.WriteLine("Error {1} occurred when sending mail [{0}] ", subject, e.Error.ToString())
        Else
            Console.WriteLine("Message [{0}] sent.", subject)
        End If

        'dispose of the mail message and delete the attachment if there is one
        mail.Dispose()
        deleteAttachment()

    End Sub

    ''' <summary>
    ''' Takes a screen shot of the passed form
    ''' </summary>
    ''' <param name="formToCapture">The form to be made into a picture</param>
    ''' <returns>A file path to the attachment</returns>
    ''' <remarks></remarks>
    Private Function snapScreenShot(ByVal formToCapture As Screen) As String

        Dim screenToCapture As Screen = formToCapture
        Dim rt As New Rectangle(0, 0, screenToCapture.Bounds.Width, screenToCapture.Bounds.Height)
        Dim pt As New Point(0, 0)
        Dim filePath As String = Application.StartupPath & "\Form" & Guid.NewGuid.ToString & ".jpeg"
        Dim bmp As New Bitmap(screenToCapture.Bounds.Width, screenToCapture.Bounds.Height)


        Dim g As Graphics = Graphics.FromImage(bmp)
        g.CopyFromScreen(rt.Location.X, rt.Location.Y, rt.Width, rt.Height, bmp.Size)
        g.CopyFromScreen(0, 0, 0, 0, bmp.Size)

        bmp.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg)

        g.Dispose()
        bmp.Dispose()
        Return filePath
    End Function

    ''' <summary>
    ''' Creates an error log if it doesn't exist. Write an entry into a customized error log
    ''' </summary>
    ''' <param name="title">Title of the error</param>
    ''' <param name="message">Error Message</param>
    ''' <param name="stackTrace">Error stack trace</param>
    ''' <remarks></remarks>
    Public Sub writeToErrorLog(ByVal title As String, ByVal message As String, ByVal stackTrace As String)

        'if the ErrorLogs directory doesnt exist then create it
        'if the error log file doesnt exist create it

        If Not System.IO.Directory.Exists(Application.StartupPath & _errorLogDirectoryName) Then

            Directory.CreateDirectory(Application.StartupPath & _errorLogDirectoryName)
            Dim file1 As New FileStream(Application.StartupPath & _errorLogDirectoryName & _errorLogName, FileMode.Create)
            file1.Close()
        End If

        If Not File.Exists(Application.StartupPath & _errorLogDirectoryName & _errorLogName) Then

            Dim file1 As New FileStream(Application.StartupPath & _errorLogDirectoryName & _errorLogName, FileMode.Create)
            file1.Close()

        End If
        'log error
        Dim fs1 As FileStream = New FileStream(Application.StartupPath & _errorLogDirectoryName & _errorLogName, _
                                               FileMode.Append, FileAccess.Write)
        Dim s1 As StreamWriter = New StreamWriter(fs1)
        s1.Write("Title: " & title & Environment.NewLine)
        s1.Write("Message: " & message & Environment.NewLine)
        s1.Write("StackTrace: " & stackTrace & Environment.NewLine)
        s1.Write("Date/Time: " & DateTime.Now.ToString() & Environment.NewLine)
        s1.Write("--------------------------------------------------------" & Environment.NewLine)
        s1.Close()
        fs1.Close()


    End Sub

    ''' <summary>
    ''' Registers an event if it doesn't exist. Method writes an entry into the Windows Event Log
    ''' </summary>
    ''' <param name="entry">Value to write to the event log</param>
    ''' <param name="eventType">Enum>>>>>Error, FailureAudit,Information,SuccessAudit, and Warning</param>
    ''' <returns>Boolean value indicating if the method suceeded. True = Succeed, False = Fail</returns>
    ''' <remarks></remarks>
    Public Function writeToEventLog(ByVal entry As String, ByVal eventType As EventLogEntryType) As Boolean

        Dim eventLog As New EventLog

        Try

            'Register the Application as an Event Source
            If Not eventLog.SourceExists(_applicationName) Then
                eventLog.CreateEventSource(_applicationName, _errorLogName)
            End If

            'log the entry
            eventLog.Source = _applicationName
            eventLog.WriteEntry(entry, eventType)

            Return writeToEventLog = True

        Catch Ex As Exception

            Return False

        Finally
            eventLog = Nothing
        End Try

    End Function

    ''' <summary>
    ''' Deletes the attachment that was saved on disk
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub deleteAttachment()
        Try
            If File.Exists(_attachmentPathToDelete) Then
                File.Delete(_attachmentPathToDelete)
            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

    End Sub
End Class
