// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT license.

using System;
using System.IO;
using Tools.DotNETCommon;
using System.Collections.Generic;

namespace UnrealBuildTool.Rules
{
	public class Simplygon : ModuleRules
	{
		public Simplygon(ReadOnlyTargetRules Target) : base(Target)
		{
			// Fix for: "command line is too long to fit in debug record"
			bLegacyPublicIncludePaths = false;
			UnsafeTypeCastWarningLevel = WarningLevel.Warning;

			string SimplygonSdkPath = GetSimplygonSdkPath();
			if (SimplygonSdkPath != String.Empty)
            {
				PublicSystemIncludePaths.Add(SimplygonSdkPath);
			}
			else
            {
				PrintHelpText("Could not find valid Simplygon SDK directory.");
			}

			PublicIncludePaths.AddRange(
				new string[] {
				}
				);

			PrivateIncludePaths.AddRange(
				new string[] 
				{
					"Simplygon/Private"
				}
				);

			PublicDependencyModuleNames.AddRange(
				new string[]
				{
					"Core",
					"CoreUObject",
					"Engine",
				}
				);

			PrivateDependencyModuleNames.AddRange(
				new string[]
				{
					"SimplygonContent",
					"Projects"
				}
				);

			DynamicallyLoadedModuleNames.AddRange(
				new string[]
				{

				}
				);

			if (Target.bBuildDeveloperTools)
			{
				PublicDependencyModuleNames.AddRange(
					new string[] {
					"MessageLog",
					}
				);
			}
		}

		enum ELogCategory
		{
			SkipLog,
			Log,
			Warning,
			Error
		}

		[Flags] enum EValidationResult
        {
			NoError,
			MissingFiles,
        }

		Dictionary<string, ELogCategory> SdkFiles = new Dictionary<string, ELogCategory>()
		{
			{"Simplygon.h", ELogCategory.Error },
			{"Simplygon.dll", ELogCategory.Warning },
			{"SimplygonBatch.exe", ELogCategory.Warning },
			{"SimplygonGridAgent.exe", ELogCategory.Warning },
		};

		private string GetSimplygonSdkPath()
		{
			string SimplygonSdkPath = String.Empty;

			string PluginRootPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../../"));
			string LocalSdkPath = Path.Combine(PluginRootPath, "Source/ThirdParty/SimplygonSDK/");
			string EnvVarSdkPath = GetSimplygonGlobalEnvVarPath();

			//Primaray path: Look for sdk locally in the plugin
			if (UseSdkPath(LocalSdkPath))
            {
				SimplygonSdkPath = LocalSdkPath;
            }
			//Secondary path: Look for sdk using Simplygon's environment path
			else if (UseSdkPath(EnvVarSdkPath))
            {
				SimplygonSdkPath = EnvVarSdkPath;
			}

			return SimplygonSdkPath.Replace("\\", "/").Replace("\\\\", "/");
		}

		private bool UseSdkPath(string Path)
		{
			DirectoryInfo SdkDir = new DirectoryInfo(Path);

			// Don't use this path if it doesn't exists or it doesn't contain any files
			bool bUseSdkDir = SdkDir.Exists && SdkDir.GetFiles().Length > 0;
			if (!bUseSdkDir)
				return false;

			Log.TraceInformationOnce("Using Simplygon SDK at: {0}", SdkDir.FullName);
			
			// Validate SDK directory
			EValidationResult validationResult = ValidateSimplygonSdkDirectory(SdkDir.FullName);

			// Log if we have errors
			if (validationResult != EValidationResult.NoError)
            {
				if(validationResult.HasFlag(EValidationResult.MissingFiles))
					PrintHelpText("Simplygon SDK ["+ SdkDir.FullName + "] is missing files.");
			}

			return true;
		}

		private string GetSimplygonGlobalEnvVarPath()
        {
			string SimplygonEnvPath = Environment.GetEnvironmentVariable("SIMPLYGON_9_PATH");
			return SimplygonEnvPath = SimplygonEnvPath != null ? Environment.ExpandEnvironmentVariables(SimplygonEnvPath) : null;
		}

		private EValidationResult ValidateSimplygonSdkDirectory(string SimplygonSdkPath)
        {
			bool bHasAllFiles = true;
			foreach (var sdkFileKvp in SdkFiles)
            {
				bHasAllFiles &= HasFile(SimplygonSdkPath, sdkFileKvp.Key, sdkFileKvp.Value);
			}

			return bHasAllFiles ? EValidationResult.NoError : EValidationResult.MissingFiles;
		}

		private bool HasFile(string Dir, string Filename, ELogCategory LogCategory)
        {
			if (Dir ==  null || !File.Exists(Path.Combine(Dir, Filename)))
			{
				string path = Dir == null ? "EmptyPath" : Dir;
				string message = String.Format("{0} was not found at: {1}", Filename, path);

				switch (LogCategory)
                {
                    case ELogCategory.SkipLog:
                        break;
                    case ELogCategory.Log:
						Log.TraceInformationOnce(message);
						break;
                    case ELogCategory.Warning:
						Log.TraceWarningOnce(message);
						break;
                    case ELogCategory.Error:
						Log.TraceErrorOnce(message);
						break;
                    default:
                        break;
                }
				
				return false;
			}

			return true;
		}

		private void PrintHelpText(string initialMessage)
        {
			System.Text.StringBuilder Message = new System.Text.StringBuilder("");
			Message.AppendLine(initialMessage);
			Message.AppendLine("Try one of the following suggestions:");
			Message.AppendLine("    - Run InstallSimplygonSDKZip.ps1 located at the root of Simplygon's plugin folder.");
			Message.AppendLine("      SimplygonSDK zip is required, download it from Simplygon's website.");
			Message.AppendLine("      This is the recommended approach if the plugin is added to source control.");
			Message.AppendLine("");
			Message.AppendLine("    - Run SimplygonSDK installer which will setup the environment variable SIMPLYGON_9_PATH.");
			Message.AppendLine("      Download the installer from Simplygon's website.");
			Message.AppendLine("");
			Message.AppendLine("For more information, check out Simplygon's UE4 documentation.");
			Log.TraceWarningOnce(Message.ToString());
		}

	}
}
