
using System.IO;
using System.Diagnostics;
using UnityEngine;
using TMPro.EditorUtilities;

namespace UnityEditor.HiveEditor
{
    public static class HiveBuildUtility
    {

        public static class Windows
        {
            public static string GetBuildDataPath(string targetPath)
            {
                return Path.GetFullPath($"{targetPath}/{Application.productName}_Data");
            }
            /// <summary>
            /// Executable 파일과 다른 폴더에서 SDK 로드 시 로드하는 폴더.
            public static string GetBuildExternalSDKPath(string targetPath)
            {
                return Path.Combine(Path.Combine(GetBuildDataPath(targetPath), "StreamingAssets"), hive.HiveUnityPluginStandaloneWindowsConst.HIVE_SDK_LOAD_FROM_STREAMING_ASSETS_DIRECTORY);
            }

            public static void CopyHiveSDKPluginAssetsAndLibrary(string targetPath)
            {
                if (targetPath == null || targetPath.Length == 0)
                {
                    HiveLogger.LogError("Target Path is null or empty.");
                    return;
                }
                if (!Directory.Exists(targetPath))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
                    HiveLogger.Log("Created target directory: " + targetPath);
                }
                
                string windowsHiveStringPath = Path.GetFullPath("Assets/Hive_SDK_v4/Plugins/desktop/hive_string");
                directoryCopy(windowsHiveStringPath, $"{targetPath}\\resources\\hive_string", true);
                string additionalFilesDir = Path.GetFullPath("Assets/Hive_SDK_v4/Plugins/Windows/additional");
                string hivePluginsDir = Path.GetFullPath("Assets/Hive_SDK_v4/Plugins/Windows/hivePlugins");

                // Copy Additional 
                directoryCopy(additionalFilesDir, targetPath, true);

                if (Directory.Exists(additionalFilesDir + "/resources"))
                {
                    HiveLogger.LogWarning("Hive Directory is deprecated. We recommand delete : " + additionalFilesDir + "/resources");
                }
                string windowsResultHiveSdkRes = Path.GetFullPath($"{targetPath}/hive-sdk-res");
                if (Directory.Exists(windowsResultHiveSdkRes))
                {
                    //Copy to resources
                    directoryCopy(windowsResultHiveSdkRes, Path.GetFullPath($"{targetPath}/resources"), true);
                    //delete unused directory.
                    Directory.Delete(windowsResultHiveSdkRes, true);
                }
                // Copy hivePlugins (this is not HIVE_PLUGIN.dll)
                directoryCopyToFlatDirectory(hivePluginsDir, targetPath);

                string windowsHiveConfig = Path.GetFullPath("Assets/Plugins/Windows/res/hive_config.xml");
                if (File.Exists(windowsHiveConfig))
                {
                    File.Copy(windowsHiveConfig, $"{targetPath}\\resources\\hive_config.xml", true);
                }
                else
                {
                    HiveLogger.LogWarning("PostProcessor not found hive_config File : " + windowsHiveConfig);
                }
            }

            public static void ApplyVersionToExecutable(string executablePath, string version)
            {
                string editToolPath = "Assets/Hive_SDK_v4/Plugins/Windows/postBuildUtil";
                if (!Directory.Exists(editToolPath))
                {
                    HiveLogger.LogWarning(editToolPath + "Not Exist! ");
                }
                else
                {
                    // https://github.com/electron/rcedit
                    string toolExecutePath = Path.Combine(editToolPath, "rcedit.exe");
                    if (!File.Exists(toolExecutePath))
                    {
                        HiveLogger.LogWarning("rcedit.exe Not Exist! : " + toolExecutePath);
                    }
                    else
                    {
                        HiveLogger.Log("File, Product Version Change To :" + version);
                        Process p = new System.Diagnostics.Process();   //  Process is included in System.Diagnostics
                        p.StartInfo.FileName = toolExecutePath;
                        p.StartInfo.Arguments = " \"" + executablePath + "\" --set-product-version " + version + " --set-file-version " + version;
                        p.Start();
                    }
                }
            }
            

            /// <summary>
            /// Hive SDK Plugin을 Migration 합니다.
            /// 
            /// 1. Assets/Hive_SDK_v4/Plugins/Windows/HIVE_PLUGIN.dll 이 있으면 제거함.
            /// 
            public static void MigrateHiveSDKPluginPreBuild()
            {
                var olderDllPath = Path.GetFullPath("Assets/Hive_SDK_v4/Plugins/Windows/HIVE_PLUGIN.dll");
                if (File.Exists(olderDllPath))
                {
                    // HIVE_PLUGIN.dll은 Additional 폴더로 통합됨.
                    HiveLogger.Log("Hive SDK Plugin Migration : " + olderDllPath);
                    File.Delete(olderDllPath);
                }
                else
                {
                    HiveLogger.Log("Already Migrated Hive SDK Plugin");
                }
            }

        }
        /// <summary>
        /// 하위 폴더의 파일을 모두 특정 디렉토리로 복사합니다.
        /// 폴더 구조는 복사되지 않으며 모든 하위 파일이 수평으로 배치됩니다.
        /// </summary>
        /// <param name="sourceDirName">원본 폴더</param>
        /// <param name="destDirName">복사할 폴더</param>
        public static void directoryCopyToFlatDirectory(string sourceDirName, string destDirName)
        {
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            if (!dir.Exists)
            {
                HiveLogger.Log("Source directory does not exist or could not be found: "
                    + sourceDirName);
                return;
            }

            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }
            FileInfo[] files = dir.GetFiles("*.*", SearchOption.TopDirectoryOnly);
            copyFiles(files, destDirName);

            DirectoryInfo[] dirs = dir.GetDirectories("*", SearchOption.TopDirectoryOnly);
            foreach (DirectoryInfo subdir in dirs)
            {
                directoryCopyToFlatDirectory(subdir.FullName, destDirName);
            }
        }

        public static void directoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
        { 
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);

            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

#if UNITY_STANDALONE
            DirectoryInfo[] dirs = dir.GetDirectories("*", SearchOption.TopDirectoryOnly);    //  for recursively
#else
            DirectoryInfo[] dirs = dir.GetDirectories();
#endif
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }
#if UNITY_STANDALONE
            FileInfo[] files = dir.GetFiles("*.*",SearchOption.TopDirectoryOnly);
#else
            FileInfo[] files = dir.GetFiles();
#endif
            copyFiles(files, destDirName);

            if (copySubDirs)
            {
                foreach (DirectoryInfo subdir in dirs)
                {
                    string temppath = Path.Combine(destDirName, subdir.Name);
                    directoryCopy(subdir.FullName, temppath, copySubDirs);
                }
            }
        }

        public static void copyFiles(FileInfo[] files, string destDirName) {
            foreach (FileInfo file in files)
            {
                string temppath = Path.Combine(destDirName, file.Name);
#if UNITY_STANDALONE
                if (!temppath.EndsWith(".meta"))
                    file.CopyTo(temppath, true);    //  copy Overwrite option.
#else
                    file.CopyTo(temppath, false);
#endif
            }
        }
    }   
}