using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using ChuPiao.AutoPrint.Common;
using ChuPiao.AutoPrint.Services;

namespace ChuPiao.AutoPrint.Desktop
{
    /// <summary>
    /// Form used to display display unhandled errors.
    /// </summary>
    public class ExceptionBox : Form
    {
        private System.Windows.Forms.TextBox exceptionTextBox;
        private System.Windows.Forms.CheckBox copyErrorCheckBox;
        //private System.Windows.Forms.CheckBox includeSysInfoCheckBox;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label;
        private System.Windows.Forms.Button continueButton;
        private System.Windows.Forms.Button reportButton;
        private System.Windows.Forms.PictureBox pictureBox;
        Exception exceptionThrown;
        string message;

        internal static void RegisterExceptionBoxForUnhandledExceptions()
        {
            Application.ThreadException += ShowErrorBox;
            AppDomain.CurrentDomain.UnhandledException += ShowErrorBox;
            MessageService.CustomErrorReporter = ShowErrorBox;
        }

        static void ShowErrorBox(object sender, ThreadExceptionEventArgs e)
        {
            LoggingService.Error("ThreadException caught", e.Exception);
            ShowErrorBox(e.Exception, null);
        }

        [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")]
        static void ShowErrorBox(object sender, UnhandledExceptionEventArgs e)
        {
            Exception ex = e.ExceptionObject as Exception;
            LoggingService.Fatal("UnhandledException caught", ex);
            if (e.IsTerminating)
                LoggingService.Fatal("Runtime is terminating because of unhandled exception.");
            ShowErrorBox(ex, "Unhandled exception", e.IsTerminating);
        }

        static void ShowErrorBox(Exception exception, string message)
        {
            ShowErrorBox(exception, message, false);
        }

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        static void ShowErrorBox(Exception exception, string message, bool mustTerminate)
        {
            try
            {
                using (ExceptionBox box = new ExceptionBox(exception, message, mustTerminate))
                {
                    try
                    {
                        box.ShowDialog(WorkbenchSingleton.MainForm);
                    }
                    catch (InvalidOperationException)
                    {
                        box.ShowDialog();
                    }
                }
            }
            catch (Exception ex)
            {
                LoggingService.Warn("Error showing ExceptionBox", ex);
                MessageBox.Show(exception.ToString(), message, MessageBoxButtons.OK,
                                MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
            }
        }

        /// <summary>
        /// Creates a new ExceptionBox instance.
        /// </summary>
        /// <param name="e">The exception to display</param>
        /// <param name="message">An additional message to display</param>
        /// <param name="mustTerminate">If <paramref name="mustTerminate"/> is true, the
        /// continue button is not available.</param>
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public ExceptionBox(Exception e, string message, bool mustTerminate)
        {
            this.exceptionThrown = e;
            this.message = message;
            InitializeComponent();
            if (mustTerminate)
            {
                closeButton.Visible = false;
                continueButton.Text = closeButton.Text;
                continueButton.Left -= closeButton.Width - continueButton.Width;
                continueButton.Width = closeButton.Width;
            }

            try
            {
                Translate(this);
            }
            catch { }

            exceptionTextBox.Text = getClipboardString();

            try
            {
                //this.pictureBox.Image = ResourceService.GetBitmap("ErrorReport");
            }
            catch { }
        }

        void Translate(Control ctl)
        {
            //ctl.Text = StringParser.Parse(ctl.Text);
            foreach (Control child in ctl.Controls)
            {
                Translate(child);
            }
        }

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        string getClipboardString()
        {
            string str = "";
            Version v = typeof(ExceptionBox).Assembly.GetName().Version;
            str += "Version : " + v.ToString() + Environment.NewLine;
            str += ".NET Version         : " + Environment.Version.ToString() + Environment.NewLine;
            str += "OS Version           : " + Environment.OSVersion.ToString() + Environment.NewLine;
            string cultureName = null;
            try
            {
                cultureName = CultureInfo.CurrentCulture.Name;
                str += "Current culture      : " + CultureInfo.CurrentCulture.EnglishName + " (" + cultureName + ")" + Environment.NewLine;
            }
            catch { }
            try
            {
                //if (cultureName == null || !cultureName.StartsWith(ResourceService.Language))
                //{
                //    str += "Current UI language  : " + ResourceService.Language + Environment.NewLine;
                //}
            }
            catch { }
            try
            {
                if (IntPtr.Size != 4)
                {
                    str += "Running as " + (IntPtr.Size * 8) + " bit process" + Environment.NewLine;
                }
                if (SystemInformation.TerminalServerSession)
                {
                    str += "Terminal Server Session" + Environment.NewLine;
                }
                if (SystemInformation.BootMode != BootMode.Normal)
                {
                    str += "Boot Mode            : " + SystemInformation.BootMode + Environment.NewLine;
                }
            }
            catch { }
            str += "Working Set Memory   : " + (Environment.WorkingSet / 1024) + "kb" + Environment.NewLine;
            str += "GC Heap Memory       : " + (GC.GetTotalMemory(false) / 1024) + "kb" + Environment.NewLine;

            str += Environment.NewLine;

            if (message != null)
            {
                str += message + Environment.NewLine;
            }
            str += "Exception thrown: " + Environment.NewLine;
            str += exceptionThrown.ToString();
            return str;
        }

        void CopyInfoToClipboard()
        {
            if (copyErrorCheckBox.Checked)
            {
                if (Application.OleRequired() == ApartmentState.STA)
                {
                    ClipboardWrapper.SetText(getClipboardString());
                }
                else
                {
                    Thread th = new Thread((ThreadStart)delegate
                    {
                        ClipboardWrapper.SetText(getClipboardString());
                    });
                    th.Name = "CopyInfoToClipboard";
                    th.SetApartmentState(ApartmentState.STA);
                    th.Start();
                }
            }
        }

        void buttonClick(object sender, System.EventArgs e)
        {
            CopyInfoToClipboard();
        }

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        static void StartUrl(string url)
        {
            try
            {
                Process.Start(url);
            }
            catch (Exception e)
            {
                LoggingService.Warn("Cannot start " + url, e);
            }
        }

        void continueButtonClick(object sender, System.EventArgs e)
        {
            DialogResult = System.Windows.Forms.DialogResult.Ignore;
            Close();
        }

        void CloseButtonClick(object sender, EventArgs e)
        {
            if (MessageBox.Show("您真的要退出吗? 所有未保存的修改都将丢失!", MessageService.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, MessageBoxOptions.DefaultDesktopOnly)
                == DialogResult.Yes)
            {
                Application.Exit();
            }
        }

        [SuppressMessage("Microsoft.Globalization", "CA1303")]
        void InitializeComponent()
        {
            this.closeButton = new System.Windows.Forms.Button();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.label = new System.Windows.Forms.Label();
            this.continueButton = new System.Windows.Forms.Button();
            this.reportButton = new System.Windows.Forms.Button();
            this.copyErrorCheckBox = new System.Windows.Forms.CheckBox();
            this.exceptionTextBox = new System.Windows.Forms.TextBox();
            this.pictureBox = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
            this.SuspendLayout();
            // 
            // closeButton
            // 
            this.closeButton.Location = new System.Drawing.Point(445, 424);
            this.closeButton.Name = "closeButton";
            this.closeButton.Size = new System.Drawing.Size(141, 23);
            this.closeButton.TabIndex = 5;
            this.closeButton.Text = "退出";
            this.closeButton.Click += new System.EventHandler(this.CloseButtonClick);
            // 
            // label3
            // 
            this.label3.Location = new System.Drawing.Point(230, 159);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(448, 23);
            this.label3.TabIndex = 9;
            this.label3.Text = "非常感谢您为使AutoPrint成为更出色的工具而做出贡献!";
            // 
            // label2
            // 
            this.label2.Location = new System.Drawing.Point(232, 64);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(448, 95);
            this.label2.TabIndex = 8;
            this.label2.Text = "有效地报告错误的方法: 我们已经为AutoPrint用户建立了报告和跟踪错误的网站. 为了尽可能减少大家重复的问题, 最简单的办法是直接将系统报告的错误复制到剪贴板上再复制到网页上, 此外我们还希望您详细描述您在产生错误前的每一步操作.";
            // 
            // label
            // 
            this.label.Location = new System.Drawing.Point(232, 8);
            this.label.Name = "label";
            this.label.Size = new System.Drawing.Size(448, 48);
            this.label.TabIndex = 6;
            this.label.Text = "AutoPrint出现了未处理的异常. 此异常未经处理, 我们希望您报告此异常给AutoPrint开发小组以改进AutoPrint.";
            // 
            // continueButton
            // 
            this.continueButton.Location = new System.Drawing.Point(592, 424);
            this.continueButton.Name = "continueButton";
            this.continueButton.Size = new System.Drawing.Size(88, 23);
            this.continueButton.TabIndex = 6;
            this.continueButton.Text = "继续";
            this.continueButton.Click += new System.EventHandler(this.continueButtonClick);
            // 
            // reportButton
            // 
            this.reportButton.Location = new System.Drawing.Point(230, 424);
            this.reportButton.Name = "reportButton";
            this.reportButton.Size = new System.Drawing.Size(209, 23);
            this.reportButton.TabIndex = 4;
            this.reportButton.Text = "向AutoPrint开发小组报告错误";
            this.reportButton.Click += new System.EventHandler(this.buttonClick);
            // 
            // copyErrorCheckBox
            // 
            this.copyErrorCheckBox.Checked = true;
            this.copyErrorCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
            this.copyErrorCheckBox.Location = new System.Drawing.Point(230, 373);
            this.copyErrorCheckBox.Name = "copyErrorCheckBox";
            this.copyErrorCheckBox.Size = new System.Drawing.Size(440, 24);
            this.copyErrorCheckBox.TabIndex = 2;
            this.copyErrorCheckBox.Text = "把错误信息复制到剪贴板";
            // 
            // exceptionTextBox
            // 
            this.exceptionTextBox.Location = new System.Drawing.Point(230, 183);
            this.exceptionTextBox.Multiline = true;
            this.exceptionTextBox.Name = "exceptionTextBox";
            this.exceptionTextBox.ReadOnly = true;
            this.exceptionTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.exceptionTextBox.Size = new System.Drawing.Size(448, 184);
            this.exceptionTextBox.TabIndex = 1;
            this.exceptionTextBox.Text = "textBoxExceptionText";
            // 
            // pictureBox
            // 
            this.pictureBox.Location = new System.Drawing.Point(0, 0);
            this.pictureBox.Name = "pictureBox";
            this.pictureBox.Size = new System.Drawing.Size(224, 464);
            this.pictureBox.TabIndex = 0;
            this.pictureBox.TabStop = false;
            // 
            // ExceptionBox
            // 
            this.ClientSize = new System.Drawing.Size(688, 453);
            this.Controls.Add(this.closeButton);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label);
            this.Controls.Add(this.continueButton);
            this.Controls.Add(this.reportButton);
            this.Controls.Add(this.copyErrorCheckBox);
            this.Controls.Add(this.exceptionTextBox);
            this.Controls.Add(this.pictureBox);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "ExceptionBox";
            this.Text = "发生了未处理的异常";
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();
        }
        private System.Windows.Forms.Button closeButton;
    }
    
}
