using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using TweetDuck.Configuration;
using TweetDuck.Dialogs;
using TweetLib.Core;
using TweetLib.Core.Application;

namespace TweetDuck {
	sealed class Reporter : IAppErrorHandler {
		private readonly string logFile;

		public Reporter(string logFile) {
			this.logFile = logFile;
		}

		public void SetupUnhandledExceptionHandler(string caption) {
			AppDomain.CurrentDomain.UnhandledException += (sender, args) => {
				if (args.ExceptionObject is Exception ex) {
					HandleException(caption, "An unhandled exception has occurred.", false, ex);
				}
			};
		}

		public bool LogVerbose(string data) {
			return Arguments.HasFlag(Arguments.ArgLogging) && LogImportant(data);
		}

		public bool LogImportant(string data) {
			return ((IAppErrorHandler) this).Log(data);
		}

		bool IAppErrorHandler.Log(string text) {
			#if DEBUG
			Debug.WriteLine(text);
			#endif

			StringBuilder build = new StringBuilder();

			if (!File.Exists(logFile)) {
				build.Append("Please, report all issues to: https://github.com/chylex/TweetDuck/issues\r\n\r\n");
			}

			build.Append("[").Append(DateTime.Now.ToString("G", Lib.Culture)).Append("]\r\n");
			build.Append(text).Append("\r\n\r\n");

			try {
				File.AppendAllText(logFile, build.ToString(), Encoding.UTF8);
				return true;
			} catch {
				return false;
			}
		}

		public void HandleException(string caption, string message, bool canIgnore, Exception e) {
			bool loggedSuccessfully = LogImportant(e.ToString());

			string exceptionText = e is ExpandedLogException ? e.Message + "\n\nDetails with potentially sensitive information are in the Error Log." : e.Message;
			FormMessage form = new FormMessage(caption, message + "\nError: " + exceptionText, canIgnore ? MessageBoxIcon.Warning : MessageBoxIcon.Error);

			Button btnExit = form.AddButton(FormMessage.Exit);
			Button btnIgnore = form.AddButton(FormMessage.Ignore, DialogResult.Ignore, ControlType.Cancel);

			btnIgnore.Enabled = canIgnore;
			form.ActiveControl = canIgnore ? btnIgnore : btnExit;

			Button btnOpenLog = new Button {
				Anchor = AnchorStyles.Bottom | AnchorStyles.Left,
				Enabled = loggedSuccessfully,
				Font = SystemFonts.MessageBoxFont,
				Location = new Point(9, 12),
				Margin = new Padding(0, 0, 48, 0),
				Size = new Size(106, 26),
				Text = "Show Error Log",
				UseVisualStyleBackColor = true
			};

			btnOpenLog.Click += (sender, args) => {
				using (Process.Start(logFile)) {}
			};

			form.AddActionControl(btnOpenLog);

			if (form.ShowDialog() == DialogResult.Ignore) {
				return;
			}

			try {
				Process.GetCurrentProcess().Kill();
			} catch {
				Environment.FailFast(message, e);
			}
		}

		public static void HandleEarlyFailure(string caption, string message) {
			Program.SetupWinForms();
			FormMessage.Error(caption, message, "Exit");

			try {
				Process.GetCurrentProcess().Kill();
			} catch {
				Environment.FailFast(message, new Exception(message));
			}
		}

		public sealed class ExpandedLogException : Exception {
			private readonly string details;

			public ExpandedLogException(Exception source, string details) : base(source.Message, source) {
				this.details = details;
			}

			public override string ToString() => base.ToString() + "\r\n" + details;
		}
	}
}