using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System;

public class BuildConfigHelper  {
    
    static string[] BuildScenes {
      get
      {
            string[] scenes = new string[EditorBuildSettings.scenes.Length];
            for(int i=0;i< scenes.Length; i++)
            {
                scenes[i] = EditorBuildSettings.scenes[i].path;
            }
            System.Array.ForEach<string>(scenes, (v) => { Debug.Log("build scene path:"+v); });
            return scenes;
       }
    }

    static string projPath
    {
        get { string dataPath = Application.dataPath; return dataPath.Remove(dataPath.Length - "Assets".Length); }
    }
    public static string SDKPath { get { return System.IO.Path.Combine(projPath, "SDK"); } }

    static string PathKeyStore { get { return System.IO.Path.Combine(projPath, "Android"); } }

    static string ApkOutputPath = "E:/APK/DestroyTheBlocks/";

    const string debug = "DEBUG";
    const string release = "RELEASE";

    public static void Config(BuildChannelItem channel)
    {
        ClearOthersSDK(channel);
        if (!string .IsNullOrEmpty(channel.sdkDirName))
        {
            string[] dirNames = channel.sdkDirName.Split(';');

            foreach (var dirName in dirNames)
            {
                Debug.LogError(" Config  dirName:" + dirName);
                string path = System.IO.Path.Combine(SDKPath, dirName);
                AssetsCopyDirectory(path, Application.dataPath);
            }
        }
        Debug.Log("channel.keystoreName:" + channel.keystoreName);
        PlayerSettings.Android.keystoreName = string.IsNullOrEmpty(channel.keystoreName)?"": channel.keystoreName;
        PlayerSettings.Android.keystorePass = channel.keystorePassword;
        PlayerSettings.Android.keyaliasPass = channel.keystoreAliasPass;
      
        List<string> symbols = new List<string>();

        symbols.Add(channel.debug? debug: release);

        if (!string.IsNullOrEmpty(channel.defineSymbols))
        {
            symbols.AddRange(channel.defineSymbols.Split(';'));
        }
        SetDefine(symbols.ToArray());

        PlayerSettings.applicationIdentifier = channel.bundleId;
        PlayerSettings.productName = channel.appName;
    }

    /// <summary>
    /// 清除其他SDK
    /// </summary>
    /// <param name="channel"></param>
    static void ClearOthersSDK(BuildChannelItem channel)
    {
        List<string> m_dirNames = new List<string>(channel.sdkDirName.Split(';'));
        
        string[] allSdkDirs = Directory.GetDirectories(SDKPath);

        foreach (string sdkDir in allSdkDirs)
        {
            Debug.Log("ClearOthersSDK  sdkDir:" + sdkDir);
            if (!m_dirNames.Contains(sdkDir))
            {
                ClearFilesRelativePathInDir(sdkDir, Application.dataPath);
            }
            else
            {
                Debug.Log("m_dirNames  sdkDir:"+ sdkDir);
            }
        }
    }

    public static void BuildForAndroid(BuildChannelItem channel)
    {
        Config(channel);

        var fileName = "MTRE_" + channel.channel + "_" + Application.version + "_" + GetDateTimeStr() + ".apk";

        BuildOptions options = new BuildOptions();
        options = BuildOptions.None;
        string buildFolder = ApkOutputPath;
        if (Application.platform == RuntimePlatform.OSXEditor && SystemInfo.deviceName.Contains("张科的MacBook Pro"))
        {
            buildFolder = "/Users/zhangke/shared/android/";
        }
        Build(buildFolder + fileName, BuildTarget.Android, options);

        Debug.Log("输出包："+ System.IO.Path.Combine( ApkOutputPath, fileName));
    }

    static void Build(string path, BuildTarget target, BuildOptions platformOptions)
    {
        var options = platformOptions; 
        BuildPipeline.BuildPlayer(BuildScenes, path, target, options);
    }

    static string GetDateTimeStr()
    {
        return DateTime.Now.ToString("yyMMdd_HHmmss");
    }

    static void SetDefine(params string[] defines)
    {
        // 增加xLua HOTFIX_ENABLE
        List<string> defineList = new List<string>(defines.Length + 1);

        if(!defines.AsList().Contains("HOTFIX_ENABLE"))
            defineList.Add("HOTFIX_ENABLE");
        defineList.AddRange(defines);

        defines = defineList.ToArray();

        string define = "";

        int defineCount = defines == null ? 0 : defines.Length;

        if (defineCount > 0)
        {
            define = defines[0];
        }
        for (int i = 1; i < defineCount; ++i)
        {
            define += ("," + defines[i]);
        }

        BuildTargetGroup targetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
        if (targetGroup == BuildTargetGroup.iOS)
        {
            SetForAlliOS();
        }
        else if (targetGroup == BuildTargetGroup.Android)
        {
            SetForAllAndroid();
        }

        PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, define);
    }

    static void SetForAlliOS()
    {
        // 使用assetBundle, iOS需要关闭UnityEngine脚本剔除
        // for error: Could not product class with ID 90/91....
        PlayerSettings.stripEngineCode = false;
    }

    static void SetForAllAndroid()
    {
        // 关闭 strippingLevel
        PlayerSettings.strippingLevel = StrippingLevel.Disabled;
    }


    static List<string> fileDirCopy = new List<string>();//暂存所有拷贝过去的文件

    /// <summary>
    /// 复制资源到目标路径,返回所有复制了的文件和文件夹,0是文件，1是文件夹
    /// </summary>
    /// <param name="fromPath"></param>
    /// <param name="toPath"></param>
    static string[] AssetsCopyDirectory(string fromPath, string toPath)
    {
        fileDirCopy = new List<string>();

        if (!Directory.Exists(fromPath))
        {
            Debug.Log("!Directory.Exists(fromPath)" + "  fromPath：" + fromPath);
            return null;
        }

        if (!Directory.Exists(toPath))
        {
            Directory.CreateDirectory(toPath);
        }

        string[] files = Directory.GetFiles(fromPath);
        CopyFiles(files, toPath);

        string[] dirs = Directory.GetDirectories(fromPath);
        CopyDirectors(dirs, toPath);

        AssetDatabase.Refresh();

        return fileDirCopy.ToArray();
    }
    static void CopyFiles(string[] files, string toPath)
    {
        if (!Directory.Exists(toPath))
        {
            Directory.CreateDirectory(toPath);
        }
        foreach (string file in files)
        {
            string name = Path.GetFileName(file);
           // Debug.Log(toPath + "  : " + name);
            var targetFile = Path.Combine(toPath, name);
            if (File.Exists(targetFile))
            {
                Debug.Log("Replace file:" + targetFile);
                File.Delete(targetFile);
            }
            FileUtil.CopyFileOrDirectory(file, targetFile);
            fileDirCopy.Add(targetFile);
        }
    }

    static void CopyDirectors(string[] dirs, string toPath)
    {
        foreach (string dir in dirs)
        {
            string name = Path.GetFileName(dir); //dir.Substring(dir.LastIndexOf("/"));
            //Debug.Log("CopyDirectors name:" + name);
            var targetDir = toPath + "/" + name;

            if (Directory.Exists(targetDir))
            {
                string[] SubFiles = Directory.GetFiles(dir);
                CopyFiles(SubFiles, targetDir);

                string[] subDirs = Directory.GetDirectories(dir);
                CopyDirectors(subDirs, targetDir);
            }
            else
            {
                FileUtil.CopyFileOrDirectory(dir, targetDir);
               // Debug.Log("fileDirCopy Add Directory：" + targetDir);
                fileDirCopy.Add(targetDir);
            }
        }
    }

    static List<string> GetFilesRelativePathInDir(string Dir)
    {
        var allFiles = new List<string>();
        if (Directory.Exists(Dir))
        {
            DirectoryInfo directory = new DirectoryInfo(Dir);
            FileInfo[] files = directory.GetFiles("*", SearchOption.AllDirectories);

            //Debug.Log(files.Length);

            string filesStr = "";
            for (int i = 0; i < files.Length; i++)
            {
                if (files[i].Name.EndsWith(".meta"))
                {
                    continue;
                }
                var fileDir = files[i].DirectoryName;

                var newDirLength = fileDir.Length - Dir.Length;
                if (newDirLength - 1 < 0) continue;
                var relativePath = fileDir.Substring(Dir.Length + 1, newDirLength - 1) + "\\" + files[i].Name;

                allFiles.Add(relativePath);
                filesStr += "      " + relativePath;
            }
            Debug.Log("GetFilesRelativePathInDir:" + filesStr);
        }
        return allFiles;
    }

    static void ClearFilesRelativePathInDir(string srcPath, string dstPath)
    {
        var list = GetFilesRelativePathInDir(srcPath);

        for (int i = 0; i < list.Count; i++)
        {
            list[i] = dstPath + "\\" + list[i];
        }
        DeleteFilesDir(list.ToArray());//拷贝过去的文件再删掉

        UnityEmptyFolderClean.Clean();//清理空文件夹
    }
    static void DeleteFilesDir(string[] files)
    {
        foreach (var file in files)
        {
            DeleteFileDir(file);
        }
    }
    static void DeleteFileDir(string file)
    {
        file = file.Replace("\\", "/");
        if (File.Exists(file))
        {
            //如果存在则删除
            File.Delete(file);
            // UnityEngine.Debug.LogError("DeleteFile " + "  file：" + file);
        }
        if (Directory.Exists(file))
        {
            Debug.Log("DeleteDirectory " + "  Directory：" + file);
            Directory.Delete(file, true);
        }
    }

    static string GetCurrentSymbols()
    {
        string curSymbols = "";
        BuildTargetGroup targetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
        if (targetGroup == BuildTargetGroup.iOS)
        {
            curSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS);
        }
        else if (targetGroup == BuildTargetGroup.Android)
        {
            curSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
        }
        return curSymbols;
    }

    /// <summary>
    /// 设置为本地测试模式
    /// </summary>
    [MenuItem("Dyspace/Set Local Test Mode On",false, 201)]
    static void SetLocalTestModeOn()
    {
        string curSymbols = GetCurrentSymbols();

        if (curSymbols.EndsWith(";"))
            curSymbols = curSymbols.Substring(0, curSymbols.Length - 1);

        SetDefine(curSymbols+";LOCALTESTMODE;");
    }
    [MenuItem("Dyspace/Set Local Test Mode Off", false, 201)]
    static void SetLocalTestModeOff()
    {
        string curSymbols = GetCurrentSymbols();

        Debug.Log("当前的Symbols:"+ curSymbols);
        curSymbols.Replace("LOCALTESTMODE", "");

        Debug.Log("移除LOCALTESTMODE后的Symbols:" + curSymbols);
        SetDefine(curSymbols);
    }

}
