using System;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Ionic.Zip;

namespace SebWindowsConfig.Utilities
{
	internal class LogCollector
	{
		private readonly IWin32Window owner;

		internal LogCollector(IWin32Window owner)
		{
			this.owner = owner;
		}

		internal void Run()
		{
			var description = "Please select the location where you would like to save the collected log files:";
			var password = default(string);
			var path = default(string);

			using (var dialog = new FolderBrowserDialog { Description = description })
			{
				if (dialog.ShowDialog(owner) == DialogResult.OK)
				{
					path = dialog.SelectedPath;
				}
			}

			if (path != default(string))
			{
				var encrypt = AskUserForDataEncrpytion();

				if (!encrypt || (encrypt && TryAskForPassword(out password)))
				{
					CollectLogFiles(path, password);
				}
			}
		}

		private bool AskUserForDataEncrpytion()
		{
			var message = "Log files can contain sensitive information about you and your computer. Would you like to protect the data with a password?";
			var result = MessageBox.Show(owner, message, "Data Protection", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

			return result == DialogResult.Yes;
		}

		private bool TryAskForPassword(out string password)
		{
			password = default(string);

			using (var dialog = new SebPasswordDialogForm())
			{
				dialog.Text = "Data Protection";
				dialog.LabelText = "Please enter the password to be used to encrypt the data:";

				if (dialog.ShowDialog(owner) == DialogResult.OK)
				{
					password = dialog.txtSEBPassword.Text;
				}
			}

			return password != default(string);
		}

		private void CollectLogFiles(string outputPath, string password = null)
		{
			try
			{
				var zipPath = Path.Combine(outputPath, $"SEB_Logs_{DateTime.Today.ToString("yyyy-MM-dd")}.zip");
				var logFiles = new[]
				{
					SEBClientInfo.SebClientLogFile,
					Path.Combine(SEBClientInfo.SebClientSettingsAppDataDirectory, SebWindowsConfigForm.SEB_CONFIG_LOG),
					Path.Combine(SEBClientInfo.SebClientSettingsAppDataDirectory, "seb.log"),
					Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"SafeExamBrowser\SebWindowsServiceWCF\sebwindowsservice.log")
				};
				var existingFiles = logFiles.Where(f => File.Exists(f));
				var missingFiles = logFiles.Except(existingFiles);

				using (var stream = new FileStream(zipPath, FileMode.Create))
				using (var zip = new ZipFile())
				{
					if (password != default(string))
					{
						zip.Password = password;
					}

					foreach (var file in existingFiles)
					{
						zip.AddFile(file, string.Empty);
					}

					zip.Save(stream);
				}

				if (missingFiles.Any())
				{
					var count = $"{existingFiles.Count()} of {logFiles.Count()}";
					var missing = $"The following file(s) could not be found:\n\n{String.Join("\n\n", missingFiles)}";

					MessageBox.Show(owner, $"{count} log files were collected and saved as '{zipPath}'.\n\n{missing}", "Status", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				}
				else
				{
					MessageBox.Show(owner, $"The log files were successfully collected and saved as '{zipPath}'.", "Sucess", MessageBoxButtons.OK, MessageBoxIcon.Information);
				}
			}
			catch (Exception e)
			{
				MessageBox.Show(owner, $"Failed to collect the log files. Reason: {e.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
	}
}