using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Giant.Resource;
using Giant.Common;
using Giant.Res;
using UnityEditor.VersionControl;
using System.Net.Configuration;

public class Exporter
{
    const string AssetFolderName = "asset";
    const string AssetFolderPathLower = "assets/asset/";

    public static void BuildAndCopy(BuildTarget bt, bool need2DelMainfest = false)
    {
        if (CreateABForAssetFolder(bt, need2DelMainfest))
        {
            CopytoStreamingAssetsNew(bt);
        }
    }
    public static bool CreateABForAssetFolderRule(BuildTarget bt, bool need2DelMainfest = false, bool isClearABFolder = false, string sBuildNumberTime = "",bool incremental = false, string serverVersion = "")
    {
        if (CreateAssetBundlesRule(bt, need2DelMainfest, isClearABFolder, sBuildNumberTime, incremental, serverVersion))
        {
            Debug.Log("build assetbundles ok");
            return true;
        }
        return false;
    }
    public static bool CreateABForAssetFolder(BuildTarget bt, bool need2DelMainfest = false)
    {
        if (CreateAssetBundlesHash(AssetFolderName, bt, need2DelMainfest))
        {
            Debug.Log("build assetbundles ok");
            return true;
        }
        return false;
    }
    static Dictionary<string, List<string>> _listNoAbMark = new Dictionary<string, List<string>>();
    public static Dictionary<string, List<string>> ShowNoABMarkResource(BuildTarget bt, bool need2DelMainfest = false)
    {
        _listNoAbMark.Clear();
        LoadConfig();
        string sourcePath = config.AssetFolderName;

        sourcePath.Replace("\\", "/");
        if (!sourcePath.StartsWith("/"))
            sourcePath = "/" + sourcePath;

        
        GetNoABMarkResourceByPath(sourcePath, _listNoAbMark, bt);
        return _listNoAbMark;
    }

    public static void GetNoABMarkResourceByPath(string _path,Dictionary<string,List<string>> _lst, BuildTarget bt)
    {
        _path = Application.dataPath + _path;

        string _floderBundleName = GetBundleNameByPath(_path.Replace(Application.dataPath, "Assets"));
        if(!string.IsNullOrEmpty(_floderBundleName))
        {
            return;
        }
        

        List<string> files = new List<string>();
        files.AddRange(Directory.GetFiles(_path, "*", SearchOption.TopDirectoryOnly)
            .Select(d => FileSystemToAssetPath(d)));

        for (int j = 0; j < files.Count; j++)
        {
            string filePath = files[j];
            string AssetBundleName = GetBundleNameByPath(filePath);//AssetDatabase.GetImplicitAssetBundleName(filePath);
            if (string.IsNullOrEmpty(AssetBundleName))
            {
                if(FilterFile(filePath, bt))
                {
                    List<string> st = null;
                    if (!_lst.TryGetValue(_path, out st))
                    {
                        st = new List<string>();
                        _lst.Add(_path, st);
                    }
                    st.Add(filePath);
                }
            }
        }

        

        List<string> dir = new List<string>();
        dir.AddRange(Directory.GetDirectories(_path, "*", SearchOption.TopDirectoryOnly));

        for (int i = 0; i < dir.Count; i++)
        {
            string subPath = dir[i];
            var assetPath = subPath.Replace(Application.dataPath, "");
            assetPath = PathUtility.StandardPath(assetPath);

            GetNoABMarkResourceByPath(assetPath, _lst,bt);
        }
    }

   public static string GetBundleNameByPath(string _subPath)
    {
        var importer = AssetImporter.GetAtPath(_subPath);
        if (importer == null)
        {
            return string.Empty;
        }
        var bundleName = importer.assetBundleName;
        if (importer.assetBundleVariant.Length > 0)
        {
            bundleName = bundleName + "." + importer.assetBundleVariant;
        }

        return bundleName;
    }




    public static bool CreateABForAssetBundleBrowser(BuildTarget bt, bool isClearABFolder = false ,  string sBuildNumberTime = "" , string serverVersion = "") 
    {
        LoadConfig();
        var outputPath = GetOutputPath(bt);
        if (isClearABFolder && System.IO.Directory.Exists(outputPath))
        {
            System.IO.Directory.Delete(outputPath, true);
            AssetDatabase.Refresh();
        }
        if (!Directory.Exists(outputPath))
        {
            Directory.CreateDirectory(outputPath);
        }

        AssetDatabase.RemoveUnusedAssetBundleNames();
		AssetBundleManifest buildManifest;
		//给重复的资源自动指定AB包
		if(config.autoAssignBundleName)
			AssetBundleAssetDuplicateTool.MoveAutoIncludesToBundle("auto_assign_by_code");
        buildManifest = BuildPipeline.BuildAssetBundles(outputPath, config.lastBuildOptions, bt);
        if (buildManifest == null)
        {
            Debug.Log("Error in build");
            return false;
        }

        CreateManifest(outputPath, bt);

        WriteVersion(config.ResultPath, bt , sBuildNumberTime, serverVersion);
        return true;
    }

    public static bool CreateABFromCustom(BuildTarget bt)
    {
        LoadConfig();

        var outputPath = GetOutputPath(bt);
        if (!Directory.Exists(outputPath))
        {
            Directory.CreateDirectory(outputPath);
        }

        AssetDatabase.RemoveUnusedAssetBundleNames();
        AssetBundleManifest buildManifest;
        //给重复的资源自动指定AB包
        if (config.autoAssignBundleName)
            AssetBundleAssetDuplicateTool.MoveAutoIncludesToBundle("auto_assign_by_code");
        buildManifest = BuildPipeline.BuildAssetBundles(outputPath, config.lastBuildOptions, bt);
        if (buildManifest == null)
        {
            Debug.Log("Error in build");
            return false;
        }

        CreateManifest(outputPath, bt);

        WriteVersion(config.ResultPath, bt);
        return true;
    }

    static ExporterCfg config;
    static BuildRules rules;
    public static ExporterCfg LoadConfig() {
        config = (ExporterCfg)AssetDatabase.LoadAssetAtPath(configfullpath, typeof(ExporterCfg));
        if (config == null)
        {
            if (!System.IO.Directory.Exists(Exporter.configPath))
            {
                System.IO.Directory.CreateDirectory(Exporter.configPath);
            }
            config = ScriptableObject.CreateInstance<ExporterCfg>();
            AssetDatabase.CreateAsset(config, configfullpath);
        }
        LoadRules();
        return config;
    }

    public static BuildRules LoadRules()
    {
        rules = (BuildRules)AssetDatabase.LoadAssetAtPath(rulepath, typeof(BuildRules));
        if (rules == null)
        {
            var dir = Path.GetDirectoryName(Exporter.rulepath);
            if (!System.IO.Directory.Exists(dir))
            {
                System.IO.Directory.CreateDirectory(dir);
            }
            rules = ScriptableObject.CreateInstance<BuildRules>();
            AssetDatabase.CreateAsset(rules, rulepath);
            Debug.LogError("Create BuildRules");
        }
        return rules;
    }

    public static void ClearAll()
    {
        LoadConfig();

        var outputPath = config.ResultPath;
        if (System.IO.Directory.Exists(outputPath))
        {
            System.IO.Directory.Delete(outputPath, true);
            AssetDatabase.Refresh();
        }
    }
    private static bool CreateAssetBundlesRule(BuildTarget bt, bool need2DelManifest, bool isClearABFolder = false, string sBuildNumberTime = "",bool incremental = false ,string serverVersion = "")
    {
        LoadConfig();
        string sourcePath = config.AssetFolderName;

        sourcePath.Replace("\\", "/");
        if (!sourcePath.StartsWith("/"))
            sourcePath = "/" + sourcePath;

        sourcePath = Application.dataPath + sourcePath;

        var outputPath = GetOutputPath(bt);
        if (isClearABFolder && System.IO.Directory.Exists(outputPath))
        {
            System.IO.Directory.Delete(outputPath, true);
            AssetDatabase.Refresh();
        }
        if (!Directory.Exists(outputPath))
        {
            Directory.CreateDirectory(outputPath);
        }
        Debug.Log("EXPORT outputpath = " + outputPath);
        //增量包不重新收集包信息
        if(!incremental)
            rules.Apply();

        var builds = rules.GetBuilds();
        var assetBundleManifest = BuildPipeline.BuildAssetBundles(outputPath, builds, config.lastBuildOptions, bt);
        if (assetBundleManifest == null)
        {
            return false;
        }

        CreateManifest(builds, outputPath, assetBundleManifest, bt, rules);

        if (need2DelManifest)
        {
            EditorUtility.DisplayProgressBar("build assetbundle", "delete manifests", 1);
            foreach (var path in Directory.GetFiles(outputPath, "*.manifest", SearchOption.AllDirectories))
            {
                File.Delete(path);
            }
            foreach (var path in Directory.GetFiles(outputPath, "*.manifest.meta", SearchOption.AllDirectories))
            {
                File.Delete(path);
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
        }
        //EncryptDir(outputPath);
        WriteVersion(config.ResultPath, bt, sBuildNumberTime, serverVersion);
        return true;
    }
    private static bool CreateAssetBundlesHash(string sourcePath, BuildTarget bt, bool need2DelManifest)
    {
        LoadConfig();
        sourcePath = config.AssetFolderName;

        sourcePath.Replace("\\", "/");
        if (!sourcePath.StartsWith("/"))
            sourcePath = "/" + sourcePath;

        sourcePath = Application.dataPath + sourcePath;

        var outputPath = GetOutputPath(bt);

        List<string> assetEntries = new List<string>();
        assetEntries.AddRange(Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories)
            .Select(d => FileSystemToAssetPath(d)));
        Debug.Log("build ab to " + outputPath);

        if (CreateAB(assetEntries, outputPath, bt) == false)
            return false;

        if (need2DelManifest)
        {
            EditorUtility.DisplayProgressBar("build assetbundle", "delete manifests", 1);
            foreach (var path in Directory.GetFiles(outputPath, "*.manifest", SearchOption.AllDirectories))
            {
                File.Delete(path);
            }
            foreach (var path in Directory.GetFiles(outputPath, "*.manifest.meta", SearchOption.AllDirectories))
            {
                File.Delete(path);
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
        }
        //EncryptDir(outputPath);
        WriteVersion(config.ResultPath, bt);
        return true;
    }

    private static void WriteVersion(string outpath, BuildTarget bt, string sBuildNumberTime = "0", string serverVersion = "")
    {
        string abversion = outpath + GetPlatformName(bt) + "_ab_version.txt";
        //string runtimeversion = outpath + GetPlatformName(bt) + "_version.txt";

        int curversion = 100;
        if (IFile.IsFileExist(abversion)) {
            string[] versions = File.ReadAllText(abversion).Split(',');
            string version = versions[0];
            if (versions.Length >= 3)
            {
                version = versions[1];
                if (string.IsNullOrEmpty(sBuildNumberTime))
                {
                    sBuildNumberTime = versions[2];
                }
            }
            curversion = int.Parse(version);
            curversion++;

        }
        if (string.IsNullOrEmpty(serverVersion))
        {
            serverVersion = UnityEditor.PlayerSettings.bundleVersion;
        }
        string curruntimeversion = serverVersion + "," + curversion + ","+ sBuildNumberTime;
#if UNITY_ANDROID
        curruntimeversion += "," + PlayerSettings.Android.bundleVersionCode;
#elif UNITY_IOS
        curruntimeversion += "," + PlayerSettings.iOS.buildNumber;
#endif
        IFile.WriteBytes(abversion, System.Text.Encoding.Default.GetBytes(curruntimeversion.ToString()));
        //IFile.WriteBytes(runtimeversion, System.Text.Encoding.Default.GetBytes(curruntimeversion));
        Debug.Log("write version ok " + curruntimeversion);
    }

    public static void EncryptDir(string dir)
    {
        var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
        foreach (var file in files)
        {
            var destfile = file + ".temp";
            if (AssetBundleStream.EncryptFile(file, destfile))
            {
                File.Delete(file);
                File.Move(destfile, file);
            }

        }
        Debug.Log("ABEncryptOK!" + dir);
    }

    private static string GetSourcePath() {
        string sourcePath = config.AssetFolderName;
        sourcePath.Replace("\\", "/");
        if (!sourcePath.StartsWith("/"))
            sourcePath = "/" + sourcePath;
        sourcePath = Application.dataPath + sourcePath;
        return sourcePath;
    }

    public static Dictionary<string, string[]> GetBuildAssetList(BuildTarget bt) {
        LoadConfig();

        string sourcePath = GetSourcePath();
        List<string> assetEntries = new List<string>();
        assetEntries.AddRange(Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories)
            .Select(d => FileSystemToAssetPath(d)));
        //Debug.Log("build ab to " + outputPath);

        var assetDict = assetEntries.Where(x => FilterFile(x, bt)).GroupBy(AssetToBundlePath)
                .ToDictionary(g => g.Key, g => g.ToArray());

        return assetDict;
    }

    public static readonly string configPath = "Assets/";
    public static readonly string configname = "ExporterCfg.asset";
    public static readonly string configfullpath = "Assets/ExporterCfg.asset";
    public static readonly string rulepath = "Assets/BuildRule.asset";
    // 用于标记是否正在打包资源
    public static bool BuildingAssetBundle = false;
    private static bool CreateAB(List<string> assetEntries, string outputPath, BuildTarget bt)
    {
        BuildingAssetBundle = true;
        try
        {
            //int total = 0;
            EditorUtility.DisplayProgressBar("build assetbundle", "grouping...", 0);
            //Init
            //InitializeFileTypeData();
            var assetDict = assetEntries.Where(x => FilterFile(x, bt)).GroupBy(AssetToBundlePath)
                .ToDictionary(g => g.Key, g => g.ToArray());
            /* foreach (string key in fileTypeData.Keys)
             {
                 total = total + fileTypeData[key];
                 Debug.LogFormat("{0}: {1}", key, fileTypeData[key]);
             }
             Debug.LogFormat("totalNumber: {0}", total);*/
            List<AssetBundleBuild> builds = new List<AssetBundleBuild>(assetDict.Count);
            foreach (var entry in assetDict)
            {
                AssetBundleBuild ab = new AssetBundleBuild();
                ab.assetNames = entry.Value;
                ab.assetBundleName = entry.Key;
                builds.Add(ab);
            }

            //打包而外场景
            for (int i = 0; i < config.scenes.Count; i++)
            {
                // Debug.Log(config.scenes[i]);
                if (!string.IsNullOrEmpty(config.scenes[i]))
                {
                    string scenename = System.IO.Path.GetFileNameWithoutExtension(config.scenes[i]);
                    AssetBundleBuild ab = new AssetBundleBuild();
                    ab.assetNames = new string[] { config.scenes[i] };
                    ab.assetBundleName = "outscenes/" + scenename.ToLower();
                    builds.Add(ab);
                }
            }

         

            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }
            var buildarr = builds.ToArray();
            EditorUtility.DisplayProgressBar("build assetbundle", "output to " + outputPath, 0);
            try
            {
                AssetBundleManifest result = BuildPipeline.BuildAssetBundles(outputPath, buildarr, BuildAssetBundleOptions.ChunkBasedCompression
                    | BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension | BuildAssetBundleOptions.DisableLoadAssetByFileName, bt);
                if (result == null)
                    return false;

                CreateManifest(buildarr, outputPath, result, bt);
            }
            catch (Exception e)
            {
                Debug.Log(e);
                return false;
            }
            finally
            {
                BuildingAssetBundle = false;
            }
            
        }
        finally
        {
            AssetDatabase.Refresh();
            EditorUtility.ClearProgressBar();
            BuildingAssetBundle = false;
        }

        return true;
    }

    private static T GetAsset<T>(string path) where T : ScriptableObject
    {
        var asset = AssetDatabase.LoadAssetAtPath<T>(path);
        if (asset == null)
        {
            asset = ScriptableObject.CreateInstance<T>();
            AssetDatabase.CreateAsset(asset, path);
            AssetDatabase.SaveAssets();
        }

        return asset;
    }

    [MenuItem("Giant Tools/AssetBundles/CreateManifest")]
    static void Ccc() {
        LoadConfig();
        string sourcePath = config.AssetFolderName;

        sourcePath.Replace("\\", "/");
        if (!sourcePath.StartsWith("/"))
            sourcePath = "/" + sourcePath;

        sourcePath = Application.dataPath + sourcePath;
        BuildTarget bt = BuildTarget.StandaloneWindows64;
        var outputPath = GetOutputPath(bt);
        CreateManifest(outputPath, bt);
    }

    static bool CreateManifest(string outputPath, BuildTarget bt) {
        var a2ab = GetAsset<AssetCatlog>(AssetsMgr.CatlogAsset);

        var assets = new List<AssetRef>();
        var bundles = AssetDatabase.GetAllAssetBundleNames();

        var bundleRefs = new List<BundleRef>();

        //var sceneName2Path = new Dictionary<string, string>();
        for (int i = 0; i < bundles.Length; i++)
        {
            var bundle = bundles[i];
            var deps = AssetDatabase.GetAssetBundleDependencies(bundle, false);
            var path = string.Format("{0}/{1}", outputPath, bundle);
            if (File.Exists(path))
            {
                using (var stream = File.OpenRead(path))
                {
                    bundleRefs.Add(new BundleRef
                    {
                        name = bundle,
                        deps = deps,//Array.ConvertAll(deps, Input=>)
                        len = stream.Length,
                        hash = ""//AssetDatabase..GetAssetBundleHash(bundle).ToString()
                    }); ;
                }

                var bundleassets = AssetDatabase.GetAssetPathsFromAssetBundle(bundle);
                for (int j = 0; j < bundleassets.Length; j++)
                {
                    string assetname = bundleassets[j];
                    AssetRef temp = new AssetRef()
                    {
                        name = System.IO.Path.GetFileName(assetname)
                    ,
                        bundle = bundle
                    ,
                        dir = System.IO.Path.GetDirectoryName(assetname).Replace("\\", "/")
                    };
                    assets.Add(temp);

                    //if (assetname.EndsWith(".unity")) {
                   //     sceneName2Path.Add(System.IO.Path.GetFileName(assetname), assetname);
                    //}
                    Debug.Log(bundleassets[j]);
                }
            }
            else
            {
                Debug.LogError(path + " file not exsit");
            }
        }
        a2ab.assets = assets.ToArray();
        a2ab.bundles = bundleRefs.ToArray();
       
        //a2ab.sceneNametoPath = sceneName2Path;

        EditorUtility.SetDirty(a2ab);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();

        var manifestBundleName = System.IO.Path.GetFileNameWithoutExtension(AssetsMgr.CatlogAsset).ToLower();// "manifest";
        var buildm = new[] {
                new AssetBundleBuild {
                    assetNames = new[] { AssetDatabase.GetAssetPath (a2ab), },
                    assetBundleName = manifestBundleName
                }
            };
        if (BuildPipeline.BuildAssetBundles(outputPath, buildm.ToArray(), BuildAssetBundleOptions.ChunkBasedCompression
                | BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension | BuildAssetBundleOptions.DisableLoadAssetByFileName, bt) == null)
            return false;

        return true;

    }

    static bool CreateManifest(AssetBundleBuild[] builds, 
        string outputPath, 
        AssetBundleManifest assetBundleManifest, 
        BuildTarget bt,
        BuildRules rules = null) {

        #region buildmanifest
        var a2ab = GetAsset<AssetCatlog>(AssetsMgr.CatlogAsset);

        var assets = new List<AssetRef>();
        var bundles = assetBundleManifest.GetAllAssetBundles();

        var bundleRefs = new List<BundleRef>();
        for (int i = 0; i < bundles.Length; i++) {
            var bundle = bundles[i];
            var deps = assetBundleManifest.GetAllDependencies(bundle);
            var path = string.Format("{0}/{1}", outputPath, bundle);
            if (File.Exists(path))
            {
                using (var stream = File.OpenRead(path))
                {
                    bundleRefs.Add(new BundleRef
                    {
                        name = bundle,
                        deps = deps,//Array.ConvertAll(deps, Input=>)
                        len = stream.Length,
                        hash = assetBundleManifest.GetAssetBundleHash(bundle).ToString()
                    }); ;
                }

                var bundleassets = AssetDatabase.GetAssetPathsFromAssetBundle(bundle);
                for (int j = 0; j < bundleassets.Length; j++) {
                    Debug.Log(bundleassets[j]);
                }
            }
            else
            {
                Debug.LogError(path + " file not exsit");
            }
        }


        

        for (int i = 0; i < builds.Length; i++)
        {
            var assetnames = builds[i].assetNames;
            var bundlename = builds[i].assetBundleName;
            for (int j = 0; j < assetnames.Length; j++)
            {
                string assetname = assetnames[j];
                AssetRef temp = new AssetRef()
                {
                    name = System.IO.Path.GetFileName(assetname)
                ,
                    bundle = bundlename
                ,
                    dir = System.IO.Path.GetDirectoryName(assetname).Replace("\\", "/")
                };
                assets.Add(temp);
            }
        }
        a2ab.assets = assets.ToArray();
        a2ab.bundles = bundleRefs.ToArray();
        EditorUtility.SetDirty(a2ab);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();

        var manifestBundleName = System.IO.Path.GetFileNameWithoutExtension(AssetsMgr.CatlogAsset).ToLower();// "manifest";
        var buildm = new[] {
                new AssetBundleBuild {
                    assetNames = new[] { AssetDatabase.GetAssetPath (a2ab), },
                    assetBundleName = manifestBundleName
                }
            };
        if (BuildPipeline.BuildAssetBundles(outputPath, buildm.ToArray(), BuildAssetBundleOptions.ChunkBasedCompression
                | BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension | BuildAssetBundleOptions.DisableLoadAssetByFileName, bt) == null)
            return false;

        return true;
        #endregion
    }


    static string GetHashCodeAssetbundleName(string resPath)
    {
        uint hashCode = (uint)resPath.GetHashCode();
        hashCode = hashCode % ResourceloadConfig.PackageNum;


        return hashCode.ToString("x2");
    }

    static string AssetToBundlePath(string assetPath)
    {
        var ext = Path.GetExtension(assetPath);
        assetPath = assetPath.ToLower();

        if (assetPath.Contains("shaders/"))
        {
            assetPath = "shaders";
        }
        else if (ext.IndexOf(".unity") < 0)
        {
            assetPath = GetHashCodeAssetbundleName(assetPath);
        }
        else
        {
            assetPath = assetPath.Replace(config.AssetFolderPathLower, String.Empty);
            assetPath = assetPath.Substring(0, assetPath.Length - ext.Length);
        }
        return assetPath;
    }

    public static bool filterWorldMap = true;
    private static Dictionary<string, int> fileTypeData = new Dictionary<string, int>();

    private static void InitializeFileTypeData()
    {
        fileTypeData.Clear();
        fileTypeData.Add("animation", 0);
        fileTypeData.Add("effect", 0);
        fileTypeData.Add("eventdata", 0);
        fileTypeData.Add("character", 0);
        fileTypeData.Add("environment", 0);
        fileTypeData.Add("sky", 0);
        fileTypeData.Add("lightmap", 0);
        fileTypeData.Add("scene", 0);
        fileTypeData.Add("ui", 0);
        fileTypeData.Add("shader", 0);
        fileTypeData.Add("others", 0);
    }

    private static bool FilterFile(string assetPath, BuildTarget bt)
    {
        var filePath = assetPath.ToLower().Replace('\\', '/');
        var ext = Path.GetExtension(filePath);

        if (config.ignorestuffixes.Contains(ext)) {
            return false;
        }

        for (int i = 0; i < config.ignorefiles.Count; i++) {
            if (string.IsNullOrEmpty(config.ignorefiles[i]))
                continue;
            string igf = config.ignorefiles[i].ToLower();
            if (filePath.Contains(igf))
                return false;
        }

        CountABFileType(filePath);
        return true;
    }

    private static void CountABFileType(string filePath)
    {
       // fileTypeData["others"]++;
    }

    public static string GetOutputPath(BuildTarget bt)
    {
        return GetResourcePath(bt) + GetManifestPath();
    }

    private static string GetManifestPath()
    {
        //var product = Application.productName;
        //if (product == "SceneEditor")
        return IResourceLoader.abpath;//"scenes/";
        //if (product == "UIEditor")
        //    return "ui/";
        //throw new Exception("Unknown editor product name " + product);
    }

    private static string GetResourcePath(BuildTarget bt)
    {
        var resPath = config.ResultPath;//GetArtRootPath();

        switch (bt) {
            case BuildTarget.StandaloneWindows:
            case BuildTarget.StandaloneWindows64:
                resPath = resPath + "/win/";
                break;
            case BuildTarget.iOS:
                resPath = resPath + "/ios/";
                break;
            case BuildTarget.Android:
                resPath = resPath + "/android/";
                break;
        }
            
        return resPath;
    }

    private static string GetPlatformName(BuildTarget bt) {
        switch (bt) {
            case BuildTarget.StandaloneWindows:
            case BuildTarget.StandaloneWindows64:
                return "win";
            case BuildTarget.Android:
                return "android";
            case BuildTarget.iOS:
                return "ios";
        }
        return "";
    }

    private static string artRootPath = null;
    private static string GetArtRootPath()
    {
        const string end = "/art";
        if (artRootPath == null)
        {
            var outputPath = Application.dataPath;
            //for (int i = 0; i < 3; ++i)
            //{
            //    outputPath = outputPath.Substring(0, outputPath.LastIndexOf("/"));
            //}
            if (!outputPath.ToLower().EndsWith(end))
                outputPath = outputPath.Substring(0, outputPath.LastIndexOf("/"));
            // Debug.Assert(outputPath.EndsWith(end));
            artRootPath = outputPath;
        }
        return artRootPath;
        //return Application.streamingAssetsPath;
    }

    static string FileSystemToAssetPath(string filePath)
    {
        var assetPath = filePath.Replace(Application.dataPath, "Assets");
        assetPath = PathUtility.StandardPath(assetPath);
        return assetPath;
    }

    public static void ClearStreamingAssets()
    {
        //删除StreamingAssets内的资源
        //string[] needDeleteDirs = new string[] { "Assets/StreamingAssets/AssetBundles", "Assets/StreamingAssets/Audio" };
        string[] needDeleteDirs = new string[] { "Assets/StreamingAssets/AssetBundles" };
        foreach (var dir in needDeleteDirs)
        {
            if (System.IO.Directory.Exists(dir))
            {
                System.IO.Directory.Delete(dir, true);
                AssetDatabase.Refresh();
            }
        }
    }

    public static void CopytoStreamingAssets(BuildTarget bt) {
        ClearStreamingAssets();
        LoadConfig();
        string[] files = System.IO.Directory.GetFiles(config.ResultPath + "/" + GetPlatformName(bt), "*", System.IO.SearchOption.AllDirectories);
        for (int i = 0; i < files.Length; i++)
        {
          
            string filepath = files[i].Replace("\\", "/");
            EditorUtility.DisplayProgressBar("Copy files", filepath, (float)i / (float)files.Length);
            filepath = filepath.Replace(config.ResultPath, "");

            string destpath = Giant.Resource.IResourceLoader.streamingAssetsPath + "/AssetBundles/" + filepath;
            var filedir = System.IO.Path.GetDirectoryName(destpath);
            if (!System.IO.Directory.Exists(filedir))
                System.IO.Directory.CreateDirectory(filedir);

            System.IO.File.Copy(config.ResultPath + filepath, destpath, true);
        }
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }




    internal static void CopytoStreamingAssetsNew(BuildTarget bt)
    {
        LoadConfig();
        if (!System.IO.Directory.Exists(config.ResultPath + "/" + GetPlatformName(bt))) {
            return;
        }
        string[] files = System.IO.Directory.GetFiles(config.ResultPath + "/" + GetPlatformName(bt), "*", System.IO.SearchOption.AllDirectories);
        for (int i = 0; i < files.Length; i++)
        {
            string filepath = files[i].Replace("\\", "/");
            filepath = filepath.Replace(config.ResultPath, "");

            string destpath = Giant.Resource.IResourceLoader.persistentDataPath + "/AssetBundles/" + filepath;
            var filedir = System.IO.Path.GetDirectoryName(destpath);
            if (!System.IO.Directory.Exists(filedir))
                System.IO.Directory.CreateDirectory(filedir);

            System.IO.File.Copy(config.ResultPath + filepath, destpath, true);
        }
        string versionfile = config.ResultPath + "/" + GetPlatformName(bt) + "/" + GetPlatformName(bt) + "_ab_version.txt";
        if (System.IO.File.Exists(versionfile)) {
            System.IO.File.Copy(versionfile, Giant.Resource.IResourceLoader.persistentDataPath + "/" + GetPlatformName(bt) + "_ab_version.txt", true);
        }
        AssetDatabase.Refresh();
    }

    public static void CreateABMap() {
        var abs = AssetDatabase.GetAllAssetBundleNames();
        for (int i = 0; i < abs.Length; i++) {
            var abname = abs[i];
            var assets = AssetDatabase.GetAssetPathsFromAssetBundle(abname);
        }
    }

}
