using System;
using System.Diagnostics;
using System.Windows;
using TaskIt.Infrastructure;

namespace TaskIt.Views.Dialogs
{
    public partial class ErrorChildWindow
    {
        protected ErrorChildWindow(string message, string errorDetails)
        {
            InitializeComponent();

            IntroductoryText.Text = message;
            ErrorTextBox.Text = errorDetails;
        }

        /// <summary>
        ///     Returns whether running under a dev environment, i.e., with a debugger attached or
        ///     with the server hosted on localhost
        /// </summary>
        private static bool IsRunningUnderDebugOrLocalhost
        {
            get
            {
                if (Debugger.IsAttached)
                {
                    return true;
                }
                var hostUrl = Application.Current.Host.Source.Host;
                return hostUrl.Contains("::1") || hostUrl.Contains("localhost") || hostUrl.Contains("127.0.0.1");
            }
        }

        /// <summary>
        ///     Creates a new Error Window given an error message.
        ///     Current stack trace will be displayed if app is running under
        ///     debug or on the local machine
        /// </summary>
        public static void CreateNew(string message)
        {
            CreateNew(message, StackTracePolicy.OnlyWhenDebuggingOrRunningLocally);
        }

        /// <summary>
        ///     Creates a new Error Window given an exception.
        ///     Current stack trace will be displayed if app is running under
        ///     debug or on the local machine
        ///     
        ///     The exception is converted onto a message using
        ///     <see cref="ConvertExceptionToMessage"/>
        /// </summary>
        public static void CreateNew(Exception exception)
        {
            CreateNew(exception, StackTracePolicy.OnlyWhenDebuggingOrRunningLocally);
        }

        /// <summary>
        ///     Creates a new Error Window given an exception. The exception is converted onto a message using
        ///     <see cref="ConvertExceptionToMessage"/>
        ///     
        ///     <param name="policy">When to display the stack trace, see <see cref="StackTracePolicy"/></param>
        /// </summary>
        public static void CreateNew(Exception exception, StackTracePolicy policy)
        {
            var fullStackTrace = exception.StackTrace;

            // Account for nested exceptions
            var innerException = exception.InnerException;
            while (innerException != null)
            {
                fullStackTrace += "\nCaused by: " + exception.Message + "\n\n" + exception.StackTrace;
                innerException = innerException.InnerException;
            }

            CreateNew(ConvertExceptionToMessage(exception), fullStackTrace, policy);
        }

        /// <summary>
        ///     Creates a new Error Window given an error message.
        ///     
        ///     <param name="policy">When to display the stack trace, see <see cref="StackTracePolicy"/></param>
        /// </summary>
        public static void CreateNew(string message, StackTracePolicy policy)
        {
            CreateNew(message, new StackTrace().ToString(), policy);
        }

        /// <summary>
        ///     All other factory methods will result in a call to this one
        /// </summary>
        /// 
        /// <param name="message">Which message to display</param>
        /// <param name="stackTrace">The associated stack trace</param>
        /// <param name="policy">In which situations the stack trace should be appended to the message</param>
        private static void CreateNew(string message, string stackTrace, StackTracePolicy policy)
        {
            var errorDetails = string.Empty;

            if (policy == StackTracePolicy.Never ||
                policy == StackTracePolicy.OnlyWhenDebuggingOrRunningLocally && IsRunningUnderDebugOrLocalhost)
            {
                errorDetails = stackTrace ?? string.Empty;
            }

            var window = new ErrorChildWindow(message, errorDetails);
            window.Show();
        }

        /// <summary>
        ///     Creates a user friendly message given an Exception. Currently this simply
        ///     takes the Exception.Message value, optionally  but you might want to change this to treat
        ///     some specific Exception classes differently
        /// </summary>
        private static string ConvertExceptionToMessage(Exception e)
        {
            return e.Message;
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
        }
    }
}