using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Net;

using smtp_client_app.Resources;
using LumiSoft.Net.Mime;
using LumiSoft.Net.MIME;
using LumiSoft.Net.Mail;
using LumiSoft.Net.SMTP.Client;

namespace smtp_client_app
{
    /// <summary>
    /// Application main window.
    /// </summary>
    public class wfrm_Main : Form
    {
        private Label       mt_SendType     = null;
        private ComboBox    m_pSendType     = null;
        private Label       mt_SmartHost    = null;
        private TextBox     m_pSmartHost    = null;
        private Label       mt_Dns          = null;
        private TextBox     m_pDns          = null;
        private GroupBox    m_pSeparator    = null;
        private Label       mt_From         = null;
        private TextBox     m_pFrom         = null;
        private Label       mt_To           = null;
        private TextBox     m_pTo           = null;
        private Label       mt_Subject      = null;
        private TextBox     m_pSubject      = null;
        private ToolStrip   m_pAttachToobar = null;
        private Label       mt_Attachments  = null;
        private ListView    m_pAttachments  = null;
        private WRichEditEx m_pText         = null;
        private Button      m_pCancel       = null;
        private Button      m_pSend         = null;

        /// <summary>
        /// Default constructor.
        /// </summary>
        public wfrm_Main()
        {
            InitUI();

            m_pSendType.SelectedIndex = 0;
        }

        #region method InitUI

        /// <summary>
        /// Creates and initializes.
        /// </summary>
        private void InitUI()
        {
            this.ClientSize = new Size(500,400);
            this.StartPosition = FormStartPosition.CenterScreen;
            this.Text = "SMTP client demo";
            this.Icon = ResManager.GetIcon("app.ico");

            mt_SendType = new Label();
            mt_SendType.Size = new Size(100,20);
            mt_SendType.Location = new Point(0,20);
            mt_SendType.TextAlign = ContentAlignment.MiddleRight;
            mt_SendType.Text = "Send Type:";

            m_pSendType = new ComboBox();
            m_pSendType.Size = new Size(200,20);
            m_pSendType.Location = new Point(105,20);
            m_pSendType.DropDownStyle = ComboBoxStyle.DropDownList;
            m_pSendType.Items.Add("Smart Host");
            m_pSendType.Items.Add("Direct with DNS");            
            m_pSendType.SelectedIndexChanged += new EventHandler(m_pSendType_SelectedIndexChanged);

            mt_SmartHost = new Label();
            mt_SmartHost.Size = new Size(100,20);
            mt_SmartHost.Location = new Point(0,45);
            mt_SmartHost.TextAlign = ContentAlignment.MiddleRight;
            mt_SmartHost.Text = "Smart Host:";
            mt_SmartHost.Visible = false;

            m_pSmartHost = new TextBox();
            m_pSmartHost.Size = new Size(200,20);
            m_pSmartHost.Location = new Point(105,45);
            m_pSmartHost.Visible = false;

            mt_Dns = new Label();
            mt_Dns.Size = new Size(100,20);
            mt_Dns.Location = new Point(0,45);
            mt_Dns.TextAlign = ContentAlignment.MiddleRight;
            mt_Dns.Text = "Dns server:";
            mt_Dns.Visible = false;

            m_pDns = new TextBox();
            m_pDns.Size = new Size(200,20);
            m_pDns.Location = new Point(105,45);
            m_pDns.Visible = false;

            m_pSeparator = new GroupBox();
            m_pSeparator.Size = new Size(490,3);
            m_pSeparator.Location = new Point(5,75);

            mt_From = new Label();
            mt_From.Size = new Size(100,20);
            mt_From.Location = new Point(0,85);
            mt_From.TextAlign = ContentAlignment.MiddleRight;
            mt_From.Text = "From:";

            m_pFrom = new TextBox();
            m_pFrom.Size = new Size(385,20);
            m_pFrom.Location = new Point(105,85);

            mt_To = new Label();
            mt_To.Size = new Size(100,20);
            mt_To.Location = new Point(0,110);
            mt_To.TextAlign = ContentAlignment.MiddleRight;
            mt_To.Text = "To:";

            m_pTo = new TextBox();
            m_pTo.Size = new Size(385,20);
            m_pTo.Location = new Point(105,110);

            mt_Subject = new Label();
            mt_Subject.Size = new Size(100,20);
            mt_Subject.Location = new Point(0,135);
            mt_Subject.TextAlign = ContentAlignment.MiddleRight;
            mt_Subject.Text = "Subject:";

            m_pSubject = new TextBox();
            m_pSubject.Size = new Size(385,20);
            m_pSubject.Location = new Point(105,135);
                        
            m_pAttachToobar = new ToolStrip();
            m_pAttachToobar.Size = new Size(60,25);
            m_pAttachToobar.Location = new Point(445,155);
            m_pAttachToobar.Dock = DockStyle.None;
            m_pAttachToobar.AutoSize = false;
            m_pAttachToobar.GripStyle = ToolStripGripStyle.Hidden;
            m_pAttachToobar.BackColor = this.BackColor;
            m_pAttachToobar.Renderer = new ToolBarRendererEx();
            m_pAttachToobar.ItemClicked += new ToolStripItemClickedEventHandler(m_pAttachToobar_ItemClicked);
            //
            // Add button
            ToolStripButton button_Add = new ToolStripButton();
            button_Add.Image = ResManager.GetIcon("add.ico").ToBitmap();
            button_Add.Tag = "add";
            button_Add.ToolTipText = "Add";
            m_pAttachToobar.Items.Add(button_Add);
            // Delete button
            ToolStripButton button_Delete = new ToolStripButton();
            button_Delete.Enabled = false;
            button_Delete.Image = ResManager.GetIcon("delete.ico").ToBitmap();
            button_Delete.Tag = "delete";
            button_Delete.ToolTipText = "Delete";
            m_pAttachToobar.Items.Add(button_Delete);
                        
            mt_Attachments = new Label();
            mt_Attachments.Size = new Size(100,20);
            mt_Attachments.Location = new Point(0,175);
            mt_Attachments.TextAlign = ContentAlignment.MiddleRight;
            mt_Attachments.Text = "Attachments:";

            ImageList m_pAttachments_ImgList = new ImageList();
            m_pAttachments_ImgList.Images.Add(ResManager.GetIcon("attachment.ico"));
            //
            m_pAttachments = new ListView();
            m_pAttachments.Size = new Size(385,40);
            m_pAttachments.Location = new Point(105,180);
            m_pAttachments.View = View.SmallIcon;
            m_pAttachments.HideSelection = false;
            m_pAttachments.SmallImageList = m_pAttachments_ImgList;
            m_pAttachments.SelectedIndexChanged += new EventHandler(m_pAttachments_SelectedIndexChanged);

            m_pText = new WRichEditEx();
            m_pText.Size = new Size(480,135);
            m_pText.Location = new Point(10,225);

            m_pCancel = new Button();
            m_pCancel.Size = new Size(70,20);
            m_pCancel.Location = new Point(345,370);
            m_pCancel.Text = "Cancel";
            m_pCancel.Click += new EventHandler(m_pCancel_Click);

            m_pSend = new Button();
            m_pSend.Size = new Size(70,20);
            m_pSend.Location = new Point(420,370);
            m_pSend.Text = "Send";
            m_pSend.Click += new EventHandler(m_pSend_Click);
            
            this.Controls.Add(mt_SendType);
            this.Controls.Add(m_pSendType);
            this.Controls.Add(mt_SmartHost);
            this.Controls.Add(m_pSmartHost);
            this.Controls.Add(mt_Dns);
            this.Controls.Add(m_pDns);
            this.Controls.Add(m_pSeparator);
            this.Controls.Add(mt_From);
            this.Controls.Add(m_pFrom);
            this.Controls.Add(mt_To);
            this.Controls.Add(m_pTo);
            this.Controls.Add(mt_Subject);
            this.Controls.Add(m_pSubject);
            this.Controls.Add(m_pAttachToobar);
            this.Controls.Add(mt_Attachments);
            this.Controls.Add(m_pAttachments);
            this.Controls.Add(m_pText);
            this.Controls.Add(m_pCancel);
            this.Controls.Add(m_pSend);
        }
                                                                                
        #endregion


        #region Events Handlign

        #region method m_pSendType_SelectedIndexChanged

        public void m_pSendType_SelectedIndexChanged(object sender,EventArgs e)
        {
            if(m_pSendType.SelectedItem.ToString() == "Smart Host"){
                mt_SmartHost.Visible = true;
                m_pSmartHost.Visible = true;
                mt_Dns.Visible = false;
                m_pDns.Visible = false;
            }
            else if(m_pSendType.SelectedItem.ToString() == "Direct with DNS"){
                mt_SmartHost.Visible = false;
                m_pSmartHost.Visible = false;
                mt_Dns.Visible = true;
                m_pDns.Visible = true;
            }
        }

        #endregion

        #region method m_pAttachToobar_ItemClicked

        private void m_pAttachToobar_ItemClicked(object sender,ToolStripItemClickedEventArgs e)
        {
            if(e.ClickedItem.Tag == null){
                return;
            }
            else if(e.ClickedItem.Tag.ToString() == "add"){
                OpenFileDialog dlg = new OpenFileDialog();
                if(dlg.ShowDialog() == DialogResult.OK){
                    ListViewItem it = new ListViewItem(
                        Path.GetFileName(dlg.FileName) + " (" + ((double)(new FileInfo(dlg.FileName).Length / 1000)).ToString("f2") + " kb)"
                    );
                    it.ImageIndex = 0;
                    it.Tag = dlg.FileName;
                    m_pAttachments.Items.Add(it);
                }
            }
            else if(e.ClickedItem.Tag.ToString() == "delete"){
                m_pAttachments.SelectedItems[0].Remove();
            }
        }

        #endregion

        #region method m_pAttachments_SelectedIndexChanged

        private void m_pAttachments_SelectedIndexChanged(object sender,EventArgs e)
        {
            if(m_pAttachments.SelectedItems.Count > 0){
                m_pAttachToobar.Items[1].Enabled = true;
            }
            else{
                m_pAttachToobar.Items[1].Enabled = false;
            }
        }

        #endregion


        #region method m_pCancel_Click

        private void m_pCancel_Click(object sender,EventArgs e)
        {
            this.Close();
        }

        #endregion

        #region method m_pSend_Click

        private void m_pSend_Click(object sender,EventArgs e)
        {
            #region Validate

            if(m_pSendType.SelectedItem.ToString() == "Smart Host"){
               if(m_pSmartHost.Text == ""){
                   MessageBox.Show(this,"Please specify smart host !","Error:",MessageBoxButtons.OK,MessageBoxIcon.Error);
                   return;
               }
            }
            else if(m_pSendType.SelectedItem.ToString() == "Direct with DNS"){
               if(m_pDns.Text == ""){
                   MessageBox.Show(this,"Please specify dns server !","Error:",MessageBoxButtons.OK,MessageBoxIcon.Error);
                   return;
               }
            }

            if(m_pFrom.Text == ""){
                MessageBox.Show(this,"Please specify From: !","Error:",MessageBoxButtons.OK,MessageBoxIcon.Error);
                return;
            }
            if(m_pTo.Text == ""){
                MessageBox.Show(this,"Please specify To: !","Error:",MessageBoxButtons.OK,MessageBoxIcon.Error);
                return;
            }

            #endregion

            this.Cursor = Cursors.WaitCursor;
            try{
                Mail_Message message = CreateMessage();

                if(m_pSendType.SelectedItem.ToString() == "Smart Host"){
                    SMTP_Client.QuickSendSmartHost(m_pSmartHost.Text,25,false,message);
                }
                else if(m_pSendType.SelectedItem.ToString() == "Direct with DNS"){
                    SMTP_Client.QuickSend(message);                    
                }

                MessageBox.Show(this,"Message sent sucessfully !","Info:",MessageBoxButtons.OK,MessageBoxIcon.Information);
            }
            catch(Exception x){
                MessageBox.Show(this,"Error: " + x.Message + ".","Error:",MessageBoxButtons.OK,MessageBoxIcon.Error);
            }
            this.Cursor = Cursors.Default;
        }

        #endregion

        #endregion


        #region method CreateMessage

        /// <summary>
        /// Creates Mime message based on UI data.
        /// </summary>
        private Mail_Message CreateMessage()
        {    
            Mail_Message m = new Mail_Message();
            m.MimeVersion = "1.0";
            m.Date = DateTime.Now;
            m.MessageID = MIME_Utils.CreateMessageID();
            m.From = Mail_t_MailboxList.Parse(m_pFrom.Text);       
            m.To = Mail_t_AddressList.Parse(m_pTo.Text);
            m.Subject = m_pSubject.Text;
            //if(m_pRequestRead.Checked && m_pFrom.Text.Length > 0){
            //   m.DispositionNotificationTo = m_pFrom.Text;
            //}

            if(m_pAttachments.Items.Count > 0){
                //--- multipart/mixed -------------------------------------------------------------------------------------------------
                MIME_h_ContentType contentType_multipartMixed = new MIME_h_ContentType(MIME_MediaTypes.Multipart.mixed);
                contentType_multipartMixed.Param_Boundary = Guid.NewGuid().ToString().Replace('-','.');
                MIME_b_MultipartMixed multipartMixed = new MIME_b_MultipartMixed(contentType_multipartMixed);
                m.Body = multipartMixed;

                    //--- multipart/alternative -----------------------------------------------------------------------------------------
                    MIME_Entity entity_mulipart_alternative = new MIME_Entity();
                    MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);
                    contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-','.');
                    MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);
                    entity_mulipart_alternative.Body = multipartAlternative;
                    multipartMixed.BodyParts.Add(entity_mulipart_alternative);

                        //--- text/plain ----------------------------------------------------------------------------------------------------
                        MIME_Entity entity_text_plain = new MIME_Entity();
                        MIME_b_Text text_plain = new MIME_b_Text(MIME_MediaTypes.Text.plain);
                        entity_text_plain.Body = text_plain;
                        text_plain.SetText(MIME_TransferEncodings.QuotedPrintable,Encoding.UTF8,m_pText.Text);
                        multipartAlternative.BodyParts.Add(entity_text_plain);

                        //--- text/html ------------------------------------------------------------------------------------------------------
                        MIME_Entity entity_text_html = new MIME_Entity();
                        MIME_b_Text text_html = new MIME_b_Text(MIME_MediaTypes.Text.html);
                        entity_text_html.Body = text_html;
                        text_html.SetText(MIME_TransferEncodings.QuotedPrintable,Encoding.UTF8,RtfToHtml());
                        multipartAlternative.BodyParts.Add(entity_text_html);

                    // Create attachment etities: --- applactation/octet-stream -------------------------
                    foreach(ListViewItem item in m_pAttachments.Items){
                        multipartMixed.BodyParts.Add(Mail_Message.CreateAttachment(item.Tag.ToString()));
                    }                
            }
            else{
                //--- multipart/alternative -----------------------------------------------------------------------------------------
                MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);
                contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-','.');
                MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);
                m.Body = multipartAlternative;

                    //--- text/plain ----------------------------------------------------------------------------------------------------
                    MIME_Entity entity_text_plain = new MIME_Entity();
                    MIME_b_Text text_plain = new MIME_b_Text(MIME_MediaTypes.Text.plain);
                    entity_text_plain.Body = text_plain;
                    text_plain.SetText(MIME_TransferEncodings.QuotedPrintable,Encoding.UTF8,m_pText.Text);
                    multipartAlternative.BodyParts.Add(entity_text_plain);

                    //--- text/html ------------------------------------------------------------------------------------------------------
                    MIME_Entity entity_text_html = new MIME_Entity();
                    MIME_b_Text text_html = new MIME_b_Text(MIME_MediaTypes.Text.html);
                    entity_text_html.Body = text_html;
                    text_html.SetText(MIME_TransferEncodings.QuotedPrintable,Encoding.UTF8,RtfToHtml());
                    multipartAlternative.BodyParts.Add(entity_text_html);
            }           

            return m;
        }

        #endregion

        #region method RtfToHtml

        /// <summary>
        /// Converts RTF text to HTML text.
        /// </summary>
        /// <returns></returns>
        private string RtfToHtml()
        {
            StringBuilder retVal = new StringBuilder();
            retVal.Append("<html>\r\n");

            m_pText.SuspendPaint = true;
            // Go to text start.
            m_pText.RichTextBox.SelectionStart  = 0;
            m_pText.RichTextBox.SelectionLength = 1;

            Font  currentFont           = m_pText.RichTextBox.SelectionFont;
            Color currentSelectionColor = m_pText.RichTextBox.SelectionColor;
            Color currentBackColor      = m_pText.RichTextBox.SelectionBackColor;

            int numberOfSpans = 0;
            int startPos = 0;
            while(m_pText.RichTextBox.Text.Length > m_pText.RichTextBox.SelectionStart){  
                m_pText.RichTextBox.SelectionStart++;
                m_pText.RichTextBox.SelectionLength = 1;
                                
                // Font style or size or color or back color changed
                if(m_pText.RichTextBox.Text.Length == m_pText.RichTextBox.SelectionStart || (currentFont.Name != m_pText.RichTextBox.SelectionFont.Name || currentFont.Size != m_pText.RichTextBox.SelectionFont.Size || currentFont.Style != m_pText.RichTextBox.SelectionFont.Style || currentSelectionColor != m_pText.RichTextBox.SelectionColor || currentBackColor != m_pText.RichTextBox.SelectionBackColor)){
                    string currentTextBlock = m_pText.RichTextBox.Text.Substring(startPos,m_pText.RichTextBox.SelectionStart - startPos);
       
                    //--- Construct text bloxh html -----------------------------------------------------------------//
                    // Make colors to html color syntax: #hex(r)hex(g)hex(b)
                    string htmlSelectionColor = "#" + currentSelectionColor.R.ToString("X2") + currentSelectionColor.G.ToString("X2") + currentSelectionColor.B.ToString("X2");
                    string htmlBackColor      = "#" + currentBackColor.R.ToString("X2") + currentBackColor.G.ToString("X2") + currentBackColor.B.ToString("X2");
                    string textStyleStartTags = "";
                    string textStyleEndTags   = "";
                    if(currentFont.Bold){
                        textStyleStartTags += "<b>";
                        textStyleEndTags   += "</b>";
                    }
                    if(currentFont.Italic){
                        textStyleStartTags += "<i>";
                        textStyleEndTags   += "</i>";
                    }
                    if(currentFont.Underline){
                        textStyleStartTags += "<u>";
                        textStyleEndTags   += "</u>";
                    }           
                    retVal.Append("<span\n style=\"color:" + htmlSelectionColor + "; font-size:" + currentFont.Size + "pt; font-family:" + currentFont.FontFamily.Name + "; background-color:" + htmlBackColor + ";\">" + textStyleStartTags + currentTextBlock.Replace("\n","</br>") + textStyleEndTags);
                    //-----------------------------------------------------------------------------------------------//

                    startPos              = m_pText.RichTextBox.SelectionStart;
                    currentFont           = m_pText.RichTextBox.SelectionFont;
                    currentSelectionColor = m_pText.RichTextBox.SelectionColor;
                    currentBackColor      = m_pText.RichTextBox.SelectionBackColor;
                    numberOfSpans++;
                }
            }

            for(int i=0;i<numberOfSpans;i++){
                retVal.Append("</span>");
            }

            retVal.Append("\r\n</html>\r\n");
            m_pText.SuspendPaint = false;

            return retVal.ToString();
        }

        #endregion

    }
}
