using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Build.Tasks;
using System.IO;
using System.Diagnostics;

namespace ThriftMSBuildTask
{
	/// <summary>
	/// MSBuild Task to generate csharp from .thrift files, and compile the code into a library: ThriftImpl.dll
	/// </summary>
	public class ThriftBuild : Task
	{
		/// <summary>
		/// The full path to the thrift.exe compiler
		/// </summary>
		[Required]
		public ITaskItem ThriftExecutable
		{
			get;
			set;
		}

		/// <summary>
		/// The full path to a thrift.dll C# library
		/// </summary>
		[Required]
		public ITaskItem ThriftLibrary
		{
			get;
			set;
		}

		/// <summary>
		/// A direcotry containing .thrift files
		/// </summary>
		[Required]
		public ITaskItem ThriftDefinitionDir
		{
			get;
			set;
		}

		/// <summary>
		/// The name of the auto-gen and compiled thrift library. It will placed in
		/// the same directory as ThriftLibrary
		/// </summary>
		[Required]
		public ITaskItem OutputName
		{
			get;
			set;
		}

		/// <summary>
		/// The full path to the compiled ThriftLibrary. This allows msbuild tasks to use this
		/// output as a variable for use elsewhere.
		/// </summary>
		[Output]
		public ITaskItem ThriftImplementation
		{
			get { return thriftImpl; }
		}

		private ITaskItem thriftImpl;
		private const string lastCompilationName = "LAST_COMP_TIMESTAMP";

		//use the Message Build Task to write something to build log
		private void LogMessage(string text, MessageImportance importance)
		{
			Message m = new Message();
			m.Text = text;
			m.Importance = importance.ToString();
			m.BuildEngine = this.BuildEngine;
			m.Execute();
		}

		//recursively find .cs files in srcDir, paths should initially be non-null and empty
		private void FindSourcesHelper(string srcDir, List<string> paths)
		{
			string[] files = Directory.GetFiles(srcDir, "*.cs");
			foreach (string f in files)
			{
				paths.Add(f);
			}
			string[] dirs = Directory.GetDirectories(srcDir);
			foreach (string dir in dirs)
			{
				FindSourcesHelper(dir, paths);
			}
		}

		/// <summary>
		/// Quote paths with spaces
		/// </summary>
		private string SafePath(string path)
		{
			if (path.Contains(' ') && !path.StartsWith("\""))
			{
				return "\"" + path + "\"";
			}
			return path;
		}

		private ITaskItem[] FindSources(string srcDir)
		{
			List<string> files = new List<string>();
			FindSourcesHelper(srcDir, files);
			ITaskItem[] items = new ITaskItem[files.Count];
			for (int i = 0; i < items.Length; i++)
			{
				items[i] = new TaskItem(files[i]);
			}
			return items;
		}

		private string LastWriteTime(string defDir)
		{
			string[] files = Directory.GetFiles(defDir, "*.thrift");
			DateTime d = (new DirectoryInfo(defDir)).LastWriteTime;
			foreach(string file in files)
			{
				FileInfo f = new FileInfo(file);
				DateTime curr = f.LastWriteTime;
				if (DateTime.Compare(curr, d) > 0)
				{
					d = curr;
				}
			}
			return d.ToFileTimeUtc().ToString();
		}

		public override bool Execute()
		{
			string defDir = SafePath(ThriftDefinitionDir.ItemSpec);
			//look for last compilation timestamp
			string lastBuildPath = Path.Combine(defDir, lastCompilationName);
			DirectoryInfo defDirInfo = new DirectoryInfo(defDir);
			string lastWrite = LastWriteTime(defDir);
			if (File.Exists(lastBuildPath))
			{
				string lastComp = File.ReadAllText(lastBuildPath);
				//don't recompile if the thrift library has been updated since lastComp
				FileInfo f = new FileInfo(ThriftLibrary.ItemSpec);
				string thriftLibTime = f.LastWriteTimeUtc.ToFileTimeUtc().ToString();
				if (lastComp.CompareTo(thriftLibTime) < 0)
				{
					//new thrift library, do a compile
					lastWrite = thriftLibTime;
				}
				else if (lastComp == lastWrite || (lastComp == thriftLibTime && lastComp.CompareTo(lastWrite) > 0))
				{
					//the .thrift dir hasn't been written to since last compilation, don't need to do anything
					LogMessage("ThriftImpl up-to-date", MessageImportance.High);
					return true;
				}
			}

			//find the directory of the thriftlibrary (that's where output will go)
			FileInfo thriftLibInfo = new FileInfo(SafePath(ThriftLibrary.ItemSpec));
			string thriftDir = thriftLibInfo.Directory.FullName;

			string genDir = Path.Combine(thriftDir, "gen-csharp");
			if (Directory.Exists(genDir))
			{
				try
				{
					Directory.Delete(genDir, true);
				}
				catch { /*eh i tried, just over-write now*/}
			}

			//run the thrift executable to generate C#
			foreach (string thriftFile in Directory.GetFiles(defDir, "*.thrift"))
			{
				LogMessage("Generating code for: " + thriftFile, MessageImportance.Normal);
				Process p = new Process();
				p.StartInfo.FileName = SafePath(ThriftExecutable.ItemSpec);
				p.StartInfo.Arguments = "--gen csharp -o " + SafePath(thriftDir) + " -r " + thriftFile;
				p.StartInfo.UseShellExecute = false;
				p.StartInfo.CreateNoWindow = true;
				p.StartInfo.RedirectStandardOutput = false;
				p.Start();
				p.WaitForExit();
				if (p.ExitCode != 0)
				{
					LogMessage("thrift.exe failed to compile " + thriftFile, MessageImportance.High);
					return false;
				}
				if (p.ExitCode != 0)
				{
					LogMessage("thrift.exe failed to compile " + thriftFile, MessageImportance.High);
					return false;
				}
			}

			Csc csc = new Csc();
			csc.TargetType = "library";
			csc.References = new ITaskItem[] { new TaskItem(ThriftLibrary.ItemSpec) };
			csc.EmitDebugInformation = true;
			string outputPath = Path.Combine(thriftDir, OutputName.ItemSpec);
			csc.OutputAssembly = new TaskItem(outputPath);
			csc.Sources = FindSources(Path.Combine(thriftDir, "gen-csharp"));
			csc.BuildEngine = this.BuildEngine;
			LogMessage("Compiling generated cs...", MessageImportance.Normal);
			if (!csc.Execute())
			{
				return false;
			}

			//write file to defDir to indicate a build was successfully completed
			File.WriteAllText(lastBuildPath, lastWrite);

			thriftImpl = new TaskItem(outputPath);

			return true;
		}
	}
}
