#if DEBUG
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using TweetDuck.Browser;
using TweetDuck.Management;
using TweetLib.Core.Features.Plugins;

namespace TweetDuck.Resources {
	sealed class ScriptLoaderDebug : ScriptLoader {
		private static readonly string HotSwapProjectRoot = FixPathSlash(Path.GetFullPath(Path.Combine(Program.ProgramPath, "../../../")));
		private static readonly string HotSwapTargetDir = FixPathSlash(Path.Combine(HotSwapProjectRoot, "bin", "tmp"));
		private static readonly string HotSwapRebuildScript = Path.Combine(HotSwapProjectRoot, "bld", "post_build.exe");

		private static string FixPathSlash(string path) {
			return path.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + '\\';
		}

		public ScriptLoaderDebug() {
			if (File.Exists(HotSwapRebuildScript)) {
				Debug.WriteLine("Activating resource hot swap...");

				ResetHotSwap();
				System.Windows.Forms.Application.ApplicationExit += (sender, args) => ResetHotSwap();
			}
		}

		public override void OnReloadTriggered() {
			HotSwap();
		}

		protected override string LocateFile(string path) {
			if (Directory.Exists(HotSwapTargetDir)) {
				Debug.WriteLine($"Hot swap active, redirecting {path}");
				return Path.Combine(HotSwapTargetDir, "resources", path);
			}

			return base.LocateFile(path);
		}

		private void HotSwap() {
			if (!File.Exists(HotSwapRebuildScript)) {
				Debug.WriteLine($"Failed resource hot swap, missing rebuild script: {HotSwapRebuildScript}");
				return;
			}

			ResetHotSwap();
			Directory.CreateDirectory(HotSwapTargetDir);

			Stopwatch sw = Stopwatch.StartNew();

			using (Process process = Process.Start(new ProcessStartInfo {
				FileName = HotSwapRebuildScript,
				Arguments = $"\"{HotSwapTargetDir}\\\" \"{HotSwapProjectRoot}\\\" \"Debug\" \"{Program.VersionTag}\"",
				WindowStyle = ProcessWindowStyle.Hidden
			})) {
				// ReSharper disable once PossibleNullReferenceException
				if (!process.WaitForExit(8000)) {
					Debug.WriteLine("Failed resource hot swap, script did not finish in time");
					return;
				}
				else if (process.ExitCode != 0) {
					Debug.WriteLine($"Failed resource hot swap, script exited with code {process.ExitCode}");
					return;
				}
			}

			sw.Stop();
			Debug.WriteLine($"Finished rebuild script in {sw.ElapsedMilliseconds} ms");

			ClearCache();

			// Force update plugin manager setup scripts

			string newPluginRoot = Path.Combine(HotSwapTargetDir, "plugins");

			const BindingFlags flagsInstance = BindingFlags.Instance | BindingFlags.NonPublic;

			Type typePluginManager = typeof(PluginManager);
			Type typeFormBrowser = typeof(FormBrowser);

			// ReSharper disable PossibleNullReferenceException
			object instPluginManager = typeFormBrowser.GetField("plugins", flagsInstance).GetValue(FormManager.TryFind<FormBrowser>());
			typePluginManager.GetField("pluginFolder", flagsInstance).SetValue(instPluginManager, newPluginRoot);

			Debug.WriteLine("Reloading hot swapped plugins...");
			((PluginManager) instPluginManager).Reload();
			// ReSharper restore PossibleNullReferenceException
		}

		private void ResetHotSwap() {
			try {
				Directory.Delete(HotSwapTargetDir, true);
			} catch (DirectoryNotFoundException) {}
		}
	}
}

#endif