using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditorInternal;
using UnityEditor.IMGUI.Controls;
using static UnityEditor.IMGUI.Controls.MultiColumnHeader;
using AssetBundleBrowser.AssetBundleDataSource;
using System.Linq;
using System.IO;

public class RuleDataSource : ABDataSource
{
   

    public static List<ABDataSource> CreateDataSources()
    {
        var op = new RuleDataSource();
        var retList = new List<ABDataSource>();
        retList.Add(op);
        return retList;
    }
    private static BuildRules rules;
    public string Name => "dbt";

    public string ProviderName => "Custom Rule";

    public bool CanSpecifyBuildTarget => false;

    public bool CanSpecifyBuildOutputDirectory => false;

    public bool CanSpecifyBuildOptions => false;

    public bool BuildAssetBundles(ABBuildInfo info)
    {
        return false;
       // throw new System.NotImplementedException();
    }

    public string[] GetAllAssetBundleNames()
    {
        return BuildRulesBundleDatas.Load().ruleBundles.Select(x => x.name).ToArray();
       
    }

    public string GetAssetBundleName(string assetPath)
    {
        rules = Exporter.LoadRules();
        var builds = rules.GetBuilds();

        var b = builds.Where(x => x.assetNames.Contains(assetPath)).FirstOrDefault();
        return b.assetBundleName;
    }

    public string[] GetAssetPathsFromAssetBundle(string assetBundleName)
    {
        rules = Exporter.LoadRules();
        var builds = rules.GetBuilds();
        var b = builds.Where(x => x.assetBundleName == assetBundleName).FirstOrDefault();
        return b.assetNames;
    }

    public string GetImplicitAssetBundleName(string assetPath)
    {
        return GetAssetBundleName(assetPath);
    }

    public bool IsReadOnly()
    {
        return true;
    }

    public void RemoveUnusedAssetBundleNames()
    {
       
    }

    public void SetAssetBundleNameAndVariant(string assetPath, string bundleName, string variantName)
    {
        //throw new System.NotImplementedException();
    }
}
public class BuildRuleWindow : EditorWindow
{
    class SearchResult
    {
        public string matchPath;
        public string assetBundleName;
            
    }
    ReorderableList m_list;
    SerializedObject m_serializedObj;
    SerializedProperty m_property;
    BuildRules m_rules;
    int m_toolBarIndex = 0;
    static string[] s_toolBars = new string[] { "规则", "搜索" };
    Vector2 m_scrollPos;


    SearchField m_searchField;
    string m_searchKey = string.Empty;
    List<SearchResult> m_searchResults = new List<SearchResult>();
    Vector2 m_searchScrollPos;
    ReorderableList m_searchResultList;
    double m_searchTime = 0f;
    bool m_searchChanged = false;
    
    public static void OpenWindow()
    {
        var win = GetWindow<BuildRuleWindow>();
        
        win.Show();
    }

    void InitList()
    {
        m_list = new ReorderableList(m_serializedObj, m_property, true, false, true, true);


        m_list.elementHeightCallback = (index) =>
        {
            var ele = m_property.GetArrayElementAtIndex(index);
           
            return EditorGUIUtility.singleLineHeight;
        };
        
        m_list.drawElementCallback = (rect, index, isActive, isFocused) =>
        {
            float lst = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth = 45;
            float single_width = position.width / 7;
            var ele = m_property.GetArrayElementAtIndex(index);
            Rect r = rect;
            r.height = EditorGUIUtility.singleLineHeight;
            r.width = 80;
            
            var assetBundleName = ele.FindPropertyRelative("assetBundleName");
            var isMultiPiece = ele.FindPropertyRelative("isMultiPiece");
            var isSubDirectory = ele.FindPropertyRelative("isSubDirectory");

            EditorGUI.PropertyField(r, isMultiPiece, new GUIContent("多个AB"), false);
            r.x += r.width;
            r.width = single_width;

            using (new EditorGUI.DisabledScope(!isMultiPiece.boolValue))
            {

                EditorGUIUtility.labelWidth = 75;
                EditorGUI.PropertyField(r, isSubDirectory, new GUIContent("按子目录分包"), false);
                r.x += 105;
                r.width = single_width;
            }
            

            EditorGUIUtility.labelWidth = 45;
            GUIContent content = isMultiPiece.boolValue ? new GUIContent("AB目录") : new GUIContent("AB名");
            EditorGUI.PropertyField(r, assetBundleName, content, false);
            r.x += r.width;
            EditorGUI.PropertyField(r, ele.FindPropertyRelative("sharedAssetBundle"), new GUIContent("共享AB"), false);
            r.x += r.width;
            EditorGUI.PropertyField(r, ele.FindPropertyRelative("searchPattern"), new GUIContent("通配符"), false);

            r.x += r.width;
            var searchPath = ele.FindPropertyRelative("searchPath");
            var obj = AssetDatabase.LoadAssetAtPath(searchPath.stringValue, typeof(Object));
            EditorGUI.BeginChangeCheck();
            obj = EditorGUI.ObjectField(r, "路径", obj, typeof(Object), true);
            if (EditorGUI.EndChangeCheck())
            {
                var path = AssetDatabase.GetAssetPath(obj).Replace("\\", "/");
                searchPath.stringValue = path;

                string assetNameWithoutExt = Path.GetFileNameWithoutExtension(path);
                assetBundleName.stringValue = assetNameWithoutExt.Substring(assetNameWithoutExt.LastIndexOf("/") + 1).ToLower();
                

            }

            r.x += r.width;
            r.width = rect.width - r.x;
            EditorGUI.LabelField(r, new GUIContent(searchPath.stringValue));
            EditorGUIUtility.labelWidth = lst;


        };
    }
        
    private void OnEnable()
    {
        EditorUtility.ClearProgressBar();
        m_rules = Exporter.LoadRules();
        m_serializedObj = new SerializedObject(m_rules);
        m_property = m_serializedObj.FindProperty("rules");

        InitList();
        DoSearch();
        EditorApplication.update += CheckSearch;
    }
    private void OnDisable()
    {
        EditorApplication.update -= CheckSearch;
    }


    void DrawDefault()
    {

        DrawCustomAB("默认AB","没有匹配到的资源默认打入此包", "defaultRule");
        DrawCustomAB("Shader AB","shader文件强制打入此包", "shaderRule");
       

    }

    void DrawCustomAB(string title,string tips,string propertyPath)
    {
        EditorGUILayout.BeginVertical(GUI.skin.box);
        GUILayout.Label(tips);
        var defaultPack = m_serializedObj.FindProperty(propertyPath);
        EditorGUILayout.LabelField(title, defaultPack.FindPropertyRelative("assetBundleName").stringValue);
        var searchPath = defaultPack.FindPropertyRelative("searchPath");
        var obj = AssetDatabase.LoadAssetAtPath(searchPath.stringValue, typeof(Object));
        EditorGUI.BeginChangeCheck();
        obj = EditorGUILayout.ObjectField("路径", obj, typeof(Object), true);
        if (EditorGUI.EndChangeCheck())
        {
            var path = AssetDatabase.GetAssetPath(obj).Replace("\\", "/");
            searchPath.stringValue = path;

        }
        EditorGUILayout.EndVertical();
    }

    void DrawRule()
    {
        m_serializedObj.Update();
      
        DrawDefault();
        m_scrollPos = EditorGUILayout.BeginScrollView(m_scrollPos);
        m_list.DoLayoutList();
        EditorGUILayout.EndScrollView();

        m_serializedObj.ApplyModifiedProperties();

        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("保存", GUILayout.Width(120), GUILayout.Height(50)))
        {

            AssetDatabase.SaveAssets();
        }
        if (GUILayout.Button("生成规则", GUILayout.Width(120), GUILayout.Height(50)))
        {

            m_rules.Apply();
            AssetDatabase.Refresh();
            m_searchChanged = true;
        }
 
        EditorGUILayout.EndHorizontal();
    }

    void DoSearch()
    {
        m_searchResults.Clear();
     
        var builds = m_rules.GetBuilds();
        var lowerSearchKey = m_searchKey.ToLower();
        foreach (var build in builds)
        {
            foreach (var asset in build.assetNames)
            {
                if (asset.ToLower().Contains(lowerSearchKey))
                {
                    SearchResult r = new SearchResult();
                    r.matchPath = asset;
                    r.assetBundleName = build.assetBundleName;
                    m_searchResults.Add(r);
                }
            }
        }
        m_searchResults.Sort((x, y) => x.matchPath.CompareTo(y.matchPath));
        Repaint();
       
    }

    void CheckSearch()
    {
        if(m_searchChanged && EditorApplication.timeSinceStartup - m_searchTime > 0.5f)
        {
            DoSearch();
            m_searchChanged = false;
        }
    }
    void DrawSearch()
    {
        if(m_searchField == null)
        {
            m_searchField = new SearchField();
        }
        GUILayout.Label("搜索可以查找某个文件是否打入包中或者属于哪个包");
        EditorGUI.BeginChangeCheck();
        
        m_searchKey = m_searchField.OnGUI(m_searchKey);
        if(EditorGUI.EndChangeCheck())
        {
            m_searchChanged = true;
            m_searchTime = EditorApplication.timeSinceStartup;


        }
        GUILayout.BeginVertical(GUI.skin.box);
        if(m_searchResultList == null)
        {
            m_searchResultList = new ReorderableList(m_searchResults,typeof(SearchResult),false,false,false,false);
            m_searchResultList.drawElementCallback = (rect, index, isActive, isFocus) => {
                var r = m_searchResults[index] as SearchResult;

                

                GUI.Label(rect, r.matchPath);

                var c = new GUIContent(r.assetBundleName, r.assetBundleName);
                var size = GUI.skin.label.CalcSize(c);
                var lr = rect;
                lr.x = rect.width - size.x - rect.x;
                GUI.Label(lr, c);
            };
            m_searchResultList.drawHeaderCallback = rect => {
                GUI.Label(rect, string.Format("搜索到结果:{0}", m_searchResults.Count));
            };

            m_searchResultList.onSelectCallback = list => {
                var r = list.list[list.index] as SearchResult;
                if(r != null)
                {
                    var obj = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(r.matchPath);
                    if(obj != null)
                    {
                        Selection.activeObject = obj;
                    }
                }
            };
        }
        m_searchScrollPos = EditorGUILayout.BeginScrollView(m_searchScrollPos);
        m_searchResultList.DoLayoutList();
        EditorGUILayout.EndScrollView();
        GUILayout.EndVertical();
    }
    
    private void OnGUI()
    {

        m_toolBarIndex = GUILayout.Toolbar(m_toolBarIndex, s_toolBars,GUILayout.MaxWidth(s_toolBars.Length*60));

        switch(m_toolBarIndex)
        {
            case 0:
                DrawRule();
                break;
            case 1:
                DrawSearch();
                break;
        }
       


    }


}
