Imports ComponentPro.Net.Mail
Imports System.IO

Namespace ImapClient
	Partial Public Class MessageViewer
		Inherits Form
		Private ReadOnly _client As Imap
		Private ReadOnly _uniqueId As String
		Private _msg As MailMessage
		Private _abort As Boolean

		Public Sub New()
			InitializeComponent()
		End Sub

		Public Sub New(ByVal client As Imap, ByVal uniqueId As String)
			InitializeComponent()

			_client = client
			_uniqueId = uniqueId
		End Sub

		''' <summary>
		''' Handles the form's Load event.
		''' </summary>
		''' <param name="e"></param>
		Protected Overrides Sub OnLoad(ByVal e As EventArgs)
			MyBase.OnLoad(e)

			' Disable the X button.
			Util.EnableCloseButton(Me, False)
		End Sub

		''' <summary>
		''' Handles the form's Shown event.
		''' </summary>
		''' <param name="e">The even arguments.</param>
		Protected Overrides Sub OnShown(ByVal e As EventArgs)
			MyBase.OnShown(e)

			Try
				AddHandler _client.Progress, AddressOf _client_Progress

				' Create a new memory stream to store the downloaded message.
				Dim mem As New MemoryStream()
				' Get message data to the newly created memory stream.
				_client.DownloadMessage(_uniqueId, mem)
				' Create a new message from the memory stream.
				mem.Seek(0, SeekOrigin.Begin)
				' Get raw data;
				Dim rawData() As Byte = mem.ToArray()

				_msg = New MailMessage(mem)

				' Fill from, to, cc.
				txtFrom.Text = _msg.From.ToString()
				txtTo.Text = _msg.To.ToString()
				txtCc.Text = _msg.Cc.ToString()

				' Fill subject.
				txtSubject.Text = _msg.Subject

				saveAsToolStripMenuItem.Enabled = True
				copyToolStripMenuItem.Enabled = True
				selectAllToolStripMenuItem.Enabled = True
				Util.EnableCloseButton(Me, True)

				' Fill the attachment list.
				If _msg.Attachments.Count > 0 Then
					For Each at As Attachment In _msg.Attachments
						cbxAttachment.Items.Add(at.FileName)
					Next at
				End If

				If cbxAttachment.Items.Count > 0 Then
					cbxAttachment.SelectedIndex = 0
					saveAttachmentsToolStripMenuItem.Enabled = True
				Else
					cbxAttachment.Enabled = False
					saveAttachmentsToolStripMenuItem.Enabled = False
				End If

				' Fill body plain text version.
				txtBody.Text = _msg.BodyText.Replace(vbLf, vbCrLf)
				' Fill body HTML version.
				txtHtml.Text = _msg.BodyHtml.Replace(vbLf, vbCrLf)

				Dim headers As HeaderCollection = _msg.Headers

				' Show all message header
				For i As Integer = 0 To headers.Count - 1
					Dim header As Header = headers(i)

					' add name column
					Dim item As New ListViewItem(header.Name)

					' add header raw content column
					item.SubItems.Add(header.Raw)

					' show unparsed (corrupted) headers in red				
					If header.Unparsable Then
						item.ForeColor = System.Drawing.Color.Red
					End If

					' add row to the ListView				
					lvwHeaders.Items.Add(item)
				Next i

				' Fill raw message.
				Dim rawtext As String = System.Text.Encoding.Default.GetString(rawData, 0, Math.Min(rawData.Length, 500000))
				txtRawText.Text = rawtext
			Catch exc As Exception
				If Not _abort Then
					Util.ShowError(exc)
				Else
					Me.DialogResult = System.Windows.Forms.DialogResult.Abort
				End If

				Me.Close()
			Finally
				' Unregister the Progress event handler.
				RemoveHandler _client.Progress, AddressOf _client_Progress
				toolStripProgressLabel.Visible = False
				toolStripProgressBar.Visible = False
				toolStripProgressCancelButton.Visible = False
				toolStripStatusLabel.Visible = True
			End Try
		End Sub

		''' <summary>
		''' Handles the client's Progress event.
		''' </summary>
		''' <param name="sender">The imap client object.</param>
		''' <param name="e">The event arguments.</param>
		Private Sub _client_Progress(ByVal sender As Object, ByVal e As ImapProgressEventArgs)
			If e.Length > 0 AndAlso (e.State = MailClientTransferState.Downloading OrElse e.State = MailClientTransferState.Uploading) Then
				toolStripProgressLabel.Text = String.Format("{0}/{1} downloaded", Util.FormatSize(e.BytesTransferred), Util.FormatSize(e.Length))
				toolStripProgressBar.Value = CInt(Fix(e.Percentage))
				Application.DoEvents()
			End If
		End Sub

		''' <summary>
		''' Shows Save as dialog and save the message to the specified file.
		''' </summary>
		Private Sub SaveMessageAs()
			Dim dlg As New SaveFileDialog()
			Try
				dlg.OverwritePrompt = True
				dlg.Filter = "Email files (*.eml)|*.eml|All files (*.*)|*.*"
				dlg.FilterIndex = 1
				dlg.Title = "Save the mail as"
				' Show the Save File As dialog.
				If dlg.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
					Return
				End If
			Catch
				MessageBox.Show(dlg.FileName & " is not an email file", "Error")
			End Try

			SaveMessageAs(dlg.FileName)
		End Sub

		''' <summary>
		''' Saves the current message as a file.
		''' </summary>
		''' <param name="fileName"></param>
		Private Sub SaveMessageAs(ByVal fileName As String)
			Try
				_msg.Save(fileName)
			Catch exc As Exception
				Util.ShowError(exc)
			End Try
		End Sub

		''' <summary>
		''' Saves attachments to a specific folder.
		''' </summary>
		Private Sub SaveAttachmentAs(ByVal folder As String)
			Try
				For Each att As Attachment In _msg.Attachments
					att.Save(Path.Combine(folder, att.FileName))
				Next att
			Catch exc As Exception
				Util.ShowError(exc)
			End Try
		End Sub

		''' <summary>
		''' Saves attachments to a specific folder. A browing folder dialog will be shown.
		''' </summary>
		Private Sub SaveAttachmentAs()
			Dim folderBrowserDialog As New FolderBrowserDialog()
			If folderBrowserDialog.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
				Return
			End If

			Dim path As String = folderBrowserDialog.SelectedPath
			SaveAttachmentAs(path)
		End Sub

		Private Sub selectAllToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles selectAllToolStripMenuItem.Click
			txtBody.SelectAll()
		End Sub

		Private Sub saveAsToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles saveAsToolStripMenuItem.Click
			SaveMessageAs()
		End Sub

		Private Sub saveAttachmentsToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles saveAttachmentsToolStripMenuItem.Click
			SaveAttachmentAs()
		End Sub

		Private Sub exitToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs)
			Me.Close()
		End Sub

		Private Sub copyToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles copyToolStripMenuItem.Click
			txtBody.Copy()
		End Sub

		Private Sub toolStripProgressCancelButton_ButtonClick(ByVal sender As Object, ByVal e As EventArgs) Handles toolStripProgressCancelButton.ButtonClick
			' Cancel the operation.
			_abort = True
			_client.Cancel()
		End Sub
	End Class
End Namespace