using System;
using System.Collections.Generic;
using System.Windows.Forms;
using ComponentPro;
using ComponentPro.Net.Mail;

namespace ScanMessagesSample
{
    public partial class ScanMessages : Form
    {
        private readonly bool _exception;
        private string _dataDir;
        private readonly List<SignatureInfo> _customSignatures = new List<SignatureInfo>();

        public ScanMessages()
        {
            try
            {
                InitializeComponent();

            }
            catch (ComponentPro.Licensing.BounceInspector.UltimateLicenseException exc)
            {
                MessageBox.Show(exc.Message, "Error");
                _exception = true;
            }

            LoadFormSettings();

#if !Framework4_5
            this.bounceFilter.ProcessMessagesCompleted += this.bounceFilter_ProcessMessagesCompleted;
#endif
        }

        /// <summary>
        /// Handles the form Load event.
        /// </summary>
        /// <param name="e">The event arguments.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (_exception)
                this.Close();
        }

        /// <summary>
        /// Loads settings from the Registry.
        /// </summary>
        private void LoadFormSettings()
        {
            txtPath.Text = (string)Util.GetProperty("DataDir", DataDir);
            chkDelete.Checked = Util.GetIntProperty("Delete", 0) == 1;
        }

        /// <summary>
        /// Saves settings to the registry.
        /// </summary>
        private void SaveFormSettings()
        {
            Util.SaveProperty("DataDir", txtPath.Text);
            Util.SaveProperty("Delete", chkDelete.Checked ? 1 : 0);
        }

        /// <summary>
        /// Handles the form's Closed event.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            SaveFormSettings();
        }

        /// <summary>
        /// Gets the default data folder that stores Messages.
        /// </summary>
        public string DataDir
        {
            get
            {
                _dataDir = System.IO.Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "..\\..\\Data");
                if (!System.IO.Directory.Exists(_dataDir))
                    _dataDir = AppDomain.CurrentDomain.BaseDirectory + "Data";

                return _dataDir;
            }
        }

        /// <summary>
        /// Enables/disables form's controls.
        /// </summary>
        /// <param name="enable">Enable or disable the form.</param>
        private void EnableProgress(bool enable)
        {
            progressBar.Enabled = enable; progressBar.Value = 0;
            btnAbort.Enabled = enable;
            btnCustomSignature.Enabled = !enable;
            btnScan.Enabled = !enable;
            lblName.Enabled = !enable;
            txtPath.Enabled = !enable;
            btnBrowse.Enabled = !enable;
            chkDelete.Enabled = !enable;
            //ltvResult.Enabled = !enable;

            Util.EnableCloseButton(this, !enable);
        }

        /// <summary>
        /// Handles the CustomSignature button's Click event.
        /// </summary>
        /// <param name="sender">The button object.</param>
        /// <param name="e">The event arguments.</param>
        private void btnCustomSignature_Click(object sender, EventArgs e)
        {
            CustomSignatures dlg = new CustomSignatures(bounceFilter, _customSignatures);
            dlg.ShowDialog();
        }

        /// <summary>
        /// Handles the Scan button's Click event.
        /// </summary>
        /// <param name="sender">The button object.</param>
        /// <param name="e">The event arguments.</param>
#if Framework4_5
        async
#endif
        void btnScan_Click(object sender, EventArgs e)        
        {
            if (txtPath.Text.Length == 0)
            {
                MessageBox.Show("Please enter path to messages to scan", "BounceInspector", MessageBoxButtons.OK);
                return;
            }

            EnableProgress(true);

            ltvResult.Items.Clear();
            tsbOpen.Enabled = false;

            // Allow delete bounced emails?
            bounceFilter.AllowDelete = chkDelete.Checked;

#if Framework4_5
            BounceResultCollection result;

            try
            {
                // Scan messages.
                result = await bounceFilter.ProcessMessagesAsync(txtPath.Text);
            }
            catch (Exception ex)
            {
                Util.ShowError(ex);
                return;
            }

            PostProcessMessages(result);
#else
            // Scan messages.
            bounceFilter.ProcessMessagesAsync(txtPath.Text);
#endif
        }

        void PostProcessMessages(BounceResultCollection result)
        {
            EnableProgress(false);

            if (result != null)
            {
                if (result.HasErrors)
                {
                    Errors dlg = new Errors();
                    dlg.SetErrors(result);
                    dlg.ShowDialog();
                }

                string found = string.Format("{0}/{1} bounced e-mails found.", result.BounceCount, result.Count);

                MessageBox.Show(result.CancelledIndex != -1 ? "Operation has been cancelled by user. " + found : found, "BounceInspector", MessageBoxButtons.OK);
            }
        }

        /// <summary>
        /// Handles the Browse button's Click event.
        /// </summary>
        /// <param name="sender">The button object.</param>
        /// <param name="e">The event arguments.</param>
        private void btnBrowse_Click(object sender, EventArgs e)
        {
            // Open Folder Browser Dialog.
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            dlg.SelectedPath = txtPath.Text;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                txtPath.Text = dlg.SelectedPath;
            }
        }

        /// <summary>
        /// Handles the Abort button's Click event.
        /// </summary>
        /// <param name="sender">The button object.</param>
        /// <param name="e">The event arguments.</param>
        private void btnAbort_Click(object sender, EventArgs e)
        {
            // Abort scanning.
            bounceFilter.Cancel();
        }

        private void bounceFilter_Processed(object sender, ProcessedEventArgs e)
        {
            // Handle the bounce Processed event here.
        }

#if !Framework4_5
        /// <summary>
        /// Handles the bounce ProcessMessagesCompleted event.
        /// </summary>
        /// <param name="sender">The BounceInspector object.</param>
        /// <param name="e">The event arguments.</param>
        private void bounceFilter_ProcessMessagesCompleted(object sender, ExtendedAsyncCompletedEventArgs<BounceResultCollection> e)
        {
            if (e.Error != null)
            {
                Util.ShowError(e.Error);
                return;
            }

            PostProcessMessages(e.Result);
        }
#endif

        /// <summary>
        /// Handles the BounceInspector's Progress event.
        /// </summary>
        /// <param name="sender">The BounceInspector object.</param>
        /// <param name="e">The event arguments.</param>
        private void bounceFilter_Progress(object sender, ProgressEventArgs e)
        {
            try
            {
                BounceResult r = e.Result;

                if (r.MailMessage == null)
                    return;

                progressBar.Value = e.Current * 100 / e.Total;

                if (r.Identified)
                {
                    // Add to the result list view.
                    ListViewItem item = new ListViewItem(new string[] {
                                    System.IO.Path.GetFileName(r.FilePath),
                                    r.MailMessage.Subject,
                                    r.Addresses[0],
                                    r.BounceCategory.Name,
                                    r.BounceType.Name,
                                    r.FileDeleted.ToString(),
                                    r.Dsn.Action.ToString(),
                                    r.Dsn.DiagnosticCode
                            });

                    item.Tag = r.FilePath;

                    ltvResult.Items.Add(item);
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }

        private void tsbOpen_Click(object sender, EventArgs e)
        {
            MessageViewer form = new MessageViewer((string)ltvResult.SelectedItems[0].Tag);
            form.ShowDialog(this);
        }

        private void ltvResult_SelectedIndexChanged(object sender, EventArgs e)
        {
            tsbOpen.Enabled = ltvResult.SelectedItems.Count > 0 && ltvResult.SelectedItems[0].Tag != null;
        }

        private void ltvResult_DoubleClick(object sender, EventArgs e)
        {
            if (tsbOpen.Enabled)
                tsbOpen_Click(sender, e);
        }
    }

    /// <summary>
    /// Contains signature information for local uses.
    /// </summary>
    public class SignatureInfo
    {
        public int Index;
        public string RegexPattern;
        public int CategoryCode;
        public int TypeCode;
        public bool Delete;
        public BounceSignaturePart SignaturePart;
    }    
}