using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Linq;
using UnityEditor;
using System.Text;
using System.Text.RegularExpressions;
using GameLogic;
/// 
/// 查找无引用资源(当前为贴图)version 2.0
/// Copyright (c) 2018 Ganchong Xingli
/// 
public class FindNoReferenceAssetWindow:EditorWindow {
	/// 
	/// 匹配资源类型库
	/// 
	public static string ContainsExtensions = "*.prefab*.unity*.mat*.asset";
	/// 
	/// Lua文件夹屏蔽库
	/// 
	public static string WithoutLuaExtensions = "*3rd*.idea*Base*Common*UITools*Logic*";
	/// 
	/// 所有游戏
	/// 
	string[] games;
    /// 
    /// 匹配资源类型库
    /// 
    string containsExtensions = ContainsExtensions;
    /// 
    /// Lua文件夹屏蔽库
    /// 
    string withoutLuaExtensions = WithoutLuaExtensions;
	/// 
	/// 是否检查所有游戏
	/// 
	bool isCheckAllGames;
    /// 
    /// 是否交叉检查
    /// 
    bool isCorssCheck;
    /// 
    /// 是否显示动态加载列表
    /// 
    bool isShowDynamicList;
	/// 
	/// 资源GUID列表
	/// 
	List AssetFileGuidList;
	/// 
	/// 无引用资源 guid列表
	/// 
	List NoRefAssetGuidList;
	/// 
	/// 没有直接引用但动态加载列表
	/// 
	Dictionary DynamicLoadAssetList;
	/// 
	/// 所有检查的游戏
	/// 
	Dictionary CheckGames;
    /// 
    /// 查找资源目录
    /// 
    public static string FindPath = AppConst.GameResRealPath + "/{0}";
    /// 
    /// 资源目录
    /// 
    public static string AssetPath = AppConst.GameResRealPath + "/{0}/Atlas";
    /// 
    /// Lua文件路径
    /// 
    public static string LuaFilesPath = AppConst.GameResRealPath + "/{0}/~Lua";
    List checkList = new List();
	[MenuItem("Tools/查找无引用贴图", false, 1)]
	static void Init()
	{
		// Get existing open window or if none, make a new one:
		FindNoReferenceAssetWindow window = (FindNoReferenceAssetWindow)EditorWindow.GetWindow(typeof(FindNoReferenceAssetWindow));
		window.Show();
        window.titleContent = new GUIContent("查找无引用资源");
		window.InitWindow();
	}
	/// 
	/// 初始化窗口
	/// 
	void InitWindow()
	{
		InitSize();
		InitGames ();
		//FindNoReferences();
	}
	/// 
	/// 初始化大小
	/// 
	void InitSize()
	{
		minSize = new Vector2(512, 400);
		maxSize = new Vector2(512, 400);
	}
	/// 
	/// 初始化游戏
	/// 
	void InitGames()
	{
		CheckGames = new Dictionary ();
		games = Directory.GetDirectories(AppConst.GameResRealPath);
		for (int i = 0; i < games.Length; i++)
		{
			games[i] = Path.GetFileNameWithoutExtension(games[i]);
			CheckGames.Add (games[i],false);
		}
	}
	void OnGUI()
	{
		ShowCheckGames ();
        ShowWithout();
        ShowButtons();
	}
	/// 
	/// 选择哪些游戏需要检查
	/// 
	void ShowCheckGames()
	{
		EditorGUILayout.BeginVertical();
		EditorGUILayout.HelpBox("请勾选需要检查的游戏", MessageType.None, true);
		//全选/反选
		bool tmpAllGames = isCheckAllGames;
		isCheckAllGames = EditorGUILayout.Toggle("All/None", isCheckAllGames);
        EditorGUILayout.Space();
		if (tmpAllGames != isCheckAllGames) 
		{
			string[] keys = CheckGames.Keys.ToArray();
			foreach (var each in keys)
			{
				CheckGames[each] = isCheckAllGames;
			}
		}
		for (int i = 0; i < games.Length; i++)
		{
			CheckGames[games[i]] = EditorGUILayout.Toggle(games[i], CheckGames[games[i]]);
		}
        EditorGUILayout.EndVertical();
        EditorGUILayout.Space();
        EditorGUILayout.Space();
        EditorGUILayout.BeginVertical();
        isCorssCheck = EditorGUILayout.Toggle("是否交叉检查?", isCorssCheck);
        isShowDynamicList = EditorGUILayout.Toggle("是否显示动态加载列表?", isShowDynamicList);
        EditorGUILayout.EndVertical();
        EditorGUILayout.Space();
	}
    /// 
    /// 显示屏蔽库
    /// 
    void ShowWithout()
    {
        EditorGUILayout.BeginVertical();
        containsExtensions = EditorGUILayout.TextField("匹配资源类型库?", containsExtensions);
        withoutLuaExtensions = EditorGUILayout.TextField("Lua文件夹屏蔽库?", withoutLuaExtensions);
        EditorGUILayout.EndVertical();
        EditorGUILayout.Space();
    }
    /// 
    /// 显示Build按钮
    /// 
    void ShowButtons()
    {
        if (GUILayout.Button("开始检查", GUILayout.Height(40f)))
        {
            FindNoReferences();
        }
    }
	/// 
	/// 查找无引用贴图
	/// 
	void FindNoReferences()
	{
        checkList.Clear();
        if (isCorssCheck)
        {
            ResetList();
            foreach (var game in CheckGames)
            {
                if (!game.Value) continue;
                CollectAllAsset(game.Key);
            }
            foreach(var game in CheckGames)
            {
                if (!game.Value) continue;
                checkList.Add(game.Key);
            }
            ResetList();
            CollectAllAsset(checkList[0]);
            FindReferences(checkList[0]);
        }
        else {
            foreach (var game in CheckGames) {
                if (!game.Value) continue;
                checkList.Add(game.Key);
            }
            ResetList();
            CollectAllAsset(checkList[0]);
            FindReferences(checkList[0]);
        }
	}
    void ResetList()
    {
        AssetFileGuidList = new List();
        NoRefAssetGuidList = new List();
        DynamicLoadAssetList = new Dictionary();
    }
	/// 
	/// 搜集所有的资源
	/// 
	void CollectAllAsset(string game)
	{
        string assetPath = string.Format(AssetPath, game);
        var files = Directory.GetFiles(assetPath, "*.*", SearchOption.AllDirectories).Where(item => { return Path.GetExtension(item) == ".png" || Path.GetExtension(item) == ".jpg"; });
		foreach (var path in files) {
			if(string.IsNullOrEmpty(path))continue;
			var guid = AssetDatabase.AssetPathToGUID (GetRelativeAssetsPath(path));
			AssetFileGuidList.Add(guid);
		}
	}
	/// 
	/// 查找引用
	/// 
	void FindReferences(string game)
	{
		int startIndex = 0;
		int count = AssetFileGuidList.Count;
		string guid = AssetFileGuidList [startIndex];
		string curAssetPath = AssetDatabase.GUIDToAssetPath (guid);
        string findPath = string.Format(FindPath,game);
		string[] files = Directory.GetFiles(findPath, "*.*", SearchOption.AllDirectories)
			.Where(s => containsExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();
		int findIndex = 0;
		bool haveRef = false;
		EditorApplication.update += delegate() {
			string file = files [findIndex];
			bool isCancel = EditorUtility.DisplayCancelableProgressBar ("查找资源中。。。", curAssetPath.Replace(AssetPath.Replace(Application.dataPath,"Assets")+"/",""), (float)(findIndex+startIndex*files.Length) / (float)(count*files.Length));
			if (Regex.IsMatch (File.ReadAllText (file), guid)) {
				haveRef = true;
			}
			findIndex++;
			if(findIndex>=files.Length)
			{
				findIndex = 0;
				startIndex++;
				if(!haveRef&&!MatchLuaFiles(curAssetPath,game)){
					NoRefAssetGuidList.Add(guid);
				}
				haveRef = false;
				if(startIndex= count) {
				EditorUtility.ClearProgressBar ();
				EditorApplication.update = null;
				findIndex = 0;
				startIndex = 0;
                DebugNoRefList(game);
                DebugDynamicLoadList(game);
                checkList.Remove(game);
                if (checkList.Count > 0)
                {
                    ResetList();
                    CollectAllAsset(checkList[0]);
                    FindReferences(checkList[0]);
                }
			}
		};
	}
	/// 
	/// 获取资源真实路径
	/// 
	private string GetRelativeAssetsPath(string path)
	{
		return "Assets" + Path.GetFullPath(path).Replace(Path.GetFullPath(Application.dataPath), "").Replace('\\', '/');
	}
	/// 
	/// 打印无引用资源列表
	/// 
	void DebugNoRefList(string game)
	{
        Debug.Log(string.Format("=============================={0}无引用资源列表Start================================",game));
		foreach (var guid in NoRefAssetGuidList) {
			if (string.IsNullOrEmpty (guid))
				continue;
			Debug.Log (AssetDatabase.GUIDToAssetPath (guid));
		}
        Debug.Log(string.Format("=============================={0}无引用资源列表  End================================\n", game));
	}
	/// 
	/// 打印动态加载资源列表
	/// 
	void DebugDynamicLoadList(string game)
	{
        if (!isShowDynamicList) return;
        Debug.Log(string.Format("=============================={0}动态加载资源列表Start================================", game));
		DirectoryInfo directoryInfo;
		foreach (var dic in DynamicLoadAssetList) {
			if (string.IsNullOrEmpty (dic.Key))
				continue;
			directoryInfo = new DirectoryInfo (dic.Key);
			Debug.Log (string.Format("Asset:{0} is dynamic load in lua file {1}",directoryInfo.Name,dic.Value));
		}
        Debug.Log(string.Format("=============================={0}动态加载资源列表  End================================\n", game));
	}
	/// 
	/// 匹配lua文件
	/// 
	bool MatchLuaFiles(string assetPath,string game)
	{
		DirectoryInfo directoryInfo = new DirectoryInfo (assetPath);
		var assetName = directoryInfo.Name.Replace(".jpg","").Replace(".png","");
        var luaFilesPath = string.Format(LuaFilesPath,game);
        directoryInfo = new DirectoryInfo(luaFilesPath);
		var dirctoryInfos = directoryInfo.GetDirectories ().Where(item=>!withoutLuaExtensions.Contains(item.Name));
		foreach(var info in dirctoryInfos)
		{
			if (info == null)
				continue;
			var files = Directory.GetFiles (info.FullName, "*.*", SearchOption.AllDirectories);
			foreach(var file in files)
			{
				if (file.EndsWith (".meta"))
					continue;
				var text = File.ReadAllText (file);
				if (Regex.IsMatch (File.ReadAllText (file), assetName)) {
					DynamicLoadAssetList.Add (assetPath,file);
					return true;
				}
                if(Regex.IsMatch(assetName,"[0-9]{1,}$")){
                    var str = assetName.Substring(0, assetName.Length - 1);
                    if (Regex.IsMatch(File.ReadAllText(file), str))
                    {
                        DynamicLoadAssetList.Add(assetPath, file);
                        return true;
                    }
                }
			}
		}
		return false;
	}
}