﻿#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections.Generic;
using UnityEngine.UI;

namespace U3DExtends
{
    public class UILayoutTool : MonoBehaviour
    {
        public static void ResortAllLayout()
        {
            GameObject testUI = GameObject.Find(Configure.UITestNodeName);
            if (testUI != null)
            {
                LayoutInfo[] layouts = testUI.GetComponentsInChildren<LayoutInfo>();
                if (layouts.Length > 0)
                {
                    SceneView.lastActiveSceneView.MoveToView(layouts[0].transform);
                    
                    RectTransform first_trans = layouts[0].transform as RectTransform;
                    Vector2 startPos = new Vector2(first_trans.sizeDelta.x*first_trans.localScale.x/2, -first_trans.sizeDelta.y * first_trans.localScale.y/2);
                    int index = 0;
                    foreach (var item in layouts)
                    {
                        int row = index / 5;
                        int col = index % 5;
                        RectTransform rectTrans = item.transform as RectTransform;
                        Vector3 pos = new Vector3((rectTrans.sizeDelta.x*rectTrans.localScale.x) * col + startPos.x, (-rectTrans.sizeDelta.y * rectTrans.localScale.y) * row + startPos.y, 0);
                        item.transform.localPosition = pos;
                        index++;
                    }
                }
            }
        }

        public static void OptimizeBatchForMenu()
        {
            OptimizeBatch(Selection.activeTransform);
        }

        public static void OptimizeBatch(Transform trans)
        {
            if (trans == null)
                return;
            Dictionary<string, List<Transform>> imageGroup = new Dictionary<string, List<Transform>>();
            Dictionary<string, List<Transform>> textGroup = new Dictionary<string, List<Transform>>();
            List<List<Transform>> sortedImgageGroup = new List<List<Transform>>();
            List<List<Transform>> sortedTextGroup = new List<List<Transform>>();
            for (int i = 0; i < trans.childCount; i++)
            {
                Transform child = trans.GetChild(i);
                Texture cur_texture = null;
                Image img = child.GetComponent<Image>();
                if (img != null)
                {
                    cur_texture = img.mainTexture;
                }
                else
                {
                    RawImage rimg = child.GetComponent<RawImage>();
                    if (rimg != null)
                        cur_texture = rimg.mainTexture;
                }
                if (cur_texture != null)
                {
                    string cur_path = AssetDatabase.GetAssetPath(cur_texture);
                    TextureImporter importer = AssetImporter.GetAtPath(cur_path) as TextureImporter;
                    //Debug.Log("cur_path : " + cur_path + " importer:"+(importer!=null).ToString());
                    if (importer != null)
                    {
                        string atlas = importer.spritePackingTag;
                        //Debug.Log("atlas : " + atlas);
                        if (atlas != "")
                        {
                            if (!imageGroup.ContainsKey(atlas))
                            {
                                List<Transform> list = new List<Transform>();
                                sortedImgageGroup.Add(list);
                                imageGroup.Add(atlas, list);
                            }
                            imageGroup[atlas].Add(child);
                        }
                    }
                }
                else
                {
                    Text text = child.GetComponent<Text>();
                    if (text != null)
                    {
                        string fontName = text.font.name;
                        //Debug.Log("fontName : " + fontName);
                        if (!textGroup.ContainsKey(fontName))
                        {
                            List<Transform> list = new List<Transform>();
                            sortedTextGroup.Add(list);
                            textGroup.Add(fontName, list);
                        }
                        textGroup[fontName].Add(child);
                    }
                }
                OptimizeBatch(child);
            }
            //同一图集的Image间层级顺序继续保留,不同图集的顺序就按每组第一张的来
            for (int i = sortedImgageGroup.Count - 1; i >= 0; i--)
            {
                List<Transform> children = sortedImgageGroup[i];
                for (int j = children.Count - 1; j >= 0; j--)
                {
                    children[j].SetAsFirstSibling();
                }

            }
            foreach (var item in sortedTextGroup)
            {
                List<Transform> children = item;
                for (int i = 0; i < children.Count; i++)
                {
                    children[i].SetAsLastSibling();
                }
            }
        }

        public static void ShowAllSelectedWidgets()
        {
            foreach (var item in Selection.gameObjects)
            {
                item.SetActive(true);
            }
        }
        public static void HideAllSelectedWidgets()
        {
            foreach (var item in Selection.gameObjects)
            {
                item.SetActive(false);
            }
        }

        //[MenuItem("UIEditor/Operate/解除")]
        public static void UnGroup()
        {
            if (Selection.gameObjects == null || Selection.gameObjects.Length <= 0)
            {
                EditorUtility.DisplayDialog("Error", "当前没有选中节点", "Ok");
                return;
            }
            if (Selection.gameObjects.Length > 1)
            {
                EditorUtility.DisplayDialog("Error", "只能同时解除一个Box", "Ok");
                return;
            }
            GameObject target = Selection.activeGameObject;
            Transform new_parent = target.transform.parent;
            if (target.transform.childCount > 0)
            {
                Transform[] child_ui = target.transform.GetComponentsInChildren<Transform>(true);
                foreach (var item in child_ui)
                {
                    //不是自己的子节点或是自己的话就跳过
                    if (item.transform.parent != target.transform || item.transform == target.transform)
                        continue;

                    item.transform.SetParent(new_parent, true);
                }
                Undo.DestroyObjectImmediate(target);
                //GameObject.DestroyImmediate(target);
            }
            else
            {
                EditorUtility.DisplayDialog("Error", "选择对象容器控件", "Ok");
            }
        }

        //[MenuItem("UIEditor/Operate/组合")]
        public static void MakeGroup()
        {
            if (Selection.gameObjects == null || Selection.gameObjects.Length <= 0)
            {
                EditorUtility.DisplayDialog("Error", "当前没有选中节点", "Ok");
                return;
            }
            //先判断选中的节点是不是挂在同个父节点上的
            Transform parent = Selection.gameObjects[0].transform.parent;
            foreach (var item in Selection.gameObjects)
            {
                if (item.transform.parent != parent)
                {
                    EditorUtility.DisplayDialog("Error", "不能跨容器组合", "Ok");
                    return;
                }
            }
            GameObject box = new GameObject("container", typeof(RectTransform));
            Undo.IncrementCurrentGroup();
            int group_index = Undo.GetCurrentGroup();
            Undo.SetCurrentGroupName("Make Group");
            Undo.RegisterCreatedObjectUndo(box, "create group object");
            RectTransform rectTrans = box.GetComponent<RectTransform>();
            if (rectTrans != null)
            {
                Vector2 left_top_pos = new Vector2(99999, -99999);
                Vector2 right_bottom_pos = new Vector2(-99999, 99999);
                foreach (var item in Selection.gameObjects)
                {
                    Bounds bound = UIEditorHelper.GetBounds(item);
                    Vector3 boundMin = item.transform.parent.InverseTransformPoint(bound.min);
                    Vector3 boundMax = item.transform.parent.InverseTransformPoint(bound.max);
                    //Debug.Log("bound : " + boundMin.ToString() + " max:" + boundMax.ToString());
                    if (boundMin.x < left_top_pos.x)
                        left_top_pos.x = boundMin.x;
                    if (boundMax.y > left_top_pos.y)
                        left_top_pos.y = boundMax.y;
                    if (boundMax.x > right_bottom_pos.x)
                        right_bottom_pos.x = boundMax.x;
                    if (boundMin.y < right_bottom_pos.y)
                        right_bottom_pos.y = boundMin.y;
                }
                rectTrans.SetParent(parent);
                rectTrans.sizeDelta = new Vector2(right_bottom_pos.x - left_top_pos.x,  left_top_pos.y - right_bottom_pos.y);
                left_top_pos.x += rectTrans.sizeDelta.x/2;
                left_top_pos.y -= rectTrans.sizeDelta.y/2;
                rectTrans.localPosition = left_top_pos;
                rectTrans.localScale = Vector3.one;

                //需要先生成好Box和设置好它的坐标和大小才可以把选中的节点挂进来，注意要先排好序，不然层次就乱了
                GameObject[] sorted_objs = Selection.gameObjects.OrderBy(x => x.transform.GetSiblingIndex()).ToArray();
                for (int i = 0; i < sorted_objs.Length; i++)
                {
                    Undo.SetTransformParent(sorted_objs[i].transform, rectTrans, "move item to group");
                }
            }
            Selection.activeGameObject = box;
            Undo.CollapseUndoOperations(group_index);
        }

        
    }


    public class PriorityTool
    {
        // [MenuItem("UIEditor/层次/最里层 " + Configure.ShortCut.MoveNodeTop)]
        public static void MoveToTopWidget()
        {
            Transform curSelect = Selection.activeTransform;
            if (curSelect != null)
            {
                curSelect.SetAsFirstSibling();
            }
        }
        // [MenuItem("UIEditor/层次/最外层 " + Configure.ShortCut.MoveNodeBottom)]
        public static void MoveToBottomWidget()
        {
            Transform curSelect = Selection.activeTransform;
            if (curSelect != null)
            {
                curSelect.SetAsLastSibling();
            }
        }

        // [MenuItem("UIEditor/层次/往里挤 " + Configure.ShortCut.MoveNodeUp)]
        public static void MoveUpWidget()
        {
            Transform curSelect = Selection.activeTransform;
            if (curSelect != null)
            {
                int curIndex = curSelect.GetSiblingIndex();
                if (curIndex > 0)
                    curSelect.SetSiblingIndex(curIndex - 1);
            }
        }

        // [MenuItem("UIEditor/层次/往外挤 " + Configure.ShortCut.MoveNodeDown)]
        public static void MoveDownWidget()
        {
            Transform curSelect = Selection.activeTransform;
            if (curSelect != null)
            {
                int curIndex = curSelect.GetSiblingIndex();
                int child_num = curSelect.parent.childCount;
                if (curIndex < child_num - 1)
                    curSelect.SetSiblingIndex(curIndex + 1);
            }
        }
    }

    public class AlignTool
    {
        // [MenuItem("UIEditor/对齐/左对齐 ←")]
        internal static void AlignInHorziontalLeft()
        {
            float x = Mathf.Min(Selection.gameObjects.Select(obj => obj.transform.localPosition.x).ToArray());

            foreach (GameObject gameObject in Selection.gameObjects)
            {
                gameObject.transform.localPosition = new Vector2(x,
                    gameObject.transform.localPosition.y);
            }
        }

        // [MenuItem("UIEditor/对齐/右对齐 →")]
        public static void AlignInHorziontalRight()
        {
            float x = Mathf.Max(Selection.gameObjects.Select(obj => obj.transform.localPosition.x +
            ((RectTransform)obj.transform).sizeDelta.x).ToArray());
            foreach (GameObject gameObject in Selection.gameObjects)
            {
                gameObject.transform.localPosition = new Vector3(x -
            ((RectTransform)gameObject.transform).sizeDelta.x, gameObject.transform.localPosition.y);
            }
        }

        // [MenuItem("UIEditor/对齐/上对齐 ↑")]
        public static void AlignInVerticalUp()
        {
            float y = Mathf.Max(Selection.gameObjects.Select(obj => obj.transform.localPosition.y).ToArray());
            foreach (GameObject gameObject in Selection.gameObjects)
            {
                gameObject.transform.localPosition = new Vector3(gameObject.transform.localPosition.x, y);
            }
        }

        // [MenuItem("UIEditor/对齐/下对齐 ↓")]
        public static void AlignInVerticalDown()
        {
            float y = Mathf.Min(Selection.gameObjects.Select(obj => obj.transform.localPosition.y -
            ((RectTransform)obj.transform).sizeDelta.y).ToArray());

            foreach (GameObject gameObject in Selection.gameObjects)
            {
                gameObject.transform.localPosition = new Vector3(gameObject.transform.localPosition.x, y + ((RectTransform)gameObject.transform).sizeDelta.y);
            }
        }


        // [MenuItem("UIEditor/对齐/水平均匀 |||")]
        public static void UniformDistributionInHorziontal()
        {
            int count = Selection.gameObjects.Length;
            float firstX = Mathf.Min(Selection.gameObjects.Select(obj => obj.transform.localPosition.x).ToArray());
            float lastX = Mathf.Max(Selection.gameObjects.Select(obj => obj.transform.localPosition.x).ToArray());
            float distance = (lastX - firstX) / (count - 1);
            var objects = Selection.gameObjects.ToList();
            objects.Sort((x, y) => (int)(x.transform.localPosition.x - y.transform.localPosition.x));
            for (int i = 0; i < count; i++)
            {
                objects[i].transform.localPosition = new Vector3(firstX + i * distance, objects[i].transform.localPosition.y);
            }
        }

        // [MenuItem("UIEditor/对齐/垂直均匀 ☰")]
        public static void UniformDistributionInVertical()
        {
            int count = Selection.gameObjects.Length;
            float firstY = Mathf.Min(Selection.gameObjects.Select(obj => obj.transform.localPosition.y).ToArray());
            float lastY = Mathf.Max(Selection.gameObjects.Select(obj => obj.transform.localPosition.y).ToArray());
            float distance = (lastY - firstY) / (count - 1);
            var objects = Selection.gameObjects.ToList();
            objects.Sort((x, y) => (int)(x.transform.localPosition.y - y.transform.localPosition.y));
            for (int i = 0; i < count; i++)
            {
                objects[i].transform.localPosition = new Vector3(objects[i].transform.localPosition.x, firstY + i * distance);
            }
        }

        // [MenuItem("UIEditor/对齐/一样大 ■")]
        public static void ResizeMax()
        {
            var height = Mathf.Max(Selection.gameObjects.Select(obj => ((RectTransform)obj.transform).sizeDelta.y).ToArray());
            var width = Mathf.Max(Selection.gameObjects.Select(obj => ((RectTransform)obj.transform).sizeDelta.x).ToArray());
            foreach (GameObject gameObject in Selection.gameObjects)
            {
                ((RectTransform)gameObject.transform).sizeDelta = new Vector2(width, height);
            }
        }

        // [MenuItem("UIEditor/对齐/一样小 ●")]
        public static void ResizeMin()
        {
            var height = Mathf.Min(Selection.gameObjects.Select(obj => ((RectTransform)obj.transform).sizeDelta.y).ToArray());
            var width = Mathf.Min(Selection.gameObjects.Select(obj => ((RectTransform)obj.transform).sizeDelta.x).ToArray());
            foreach (GameObject gameObject in Selection.gameObjects)
            {
                ((RectTransform)gameObject.transform).sizeDelta = new Vector2(width, height);
            }
        }

    }
}
#endif