/*
 *Copyright(C) 2024 by Chief All rights reserved.
 *Unity版本：2023.2.5f1c1 
 *作者:Chief  
 *创建日期: 2024-03-06 
 *模块说明：Ecs通用模块-渲染部分编辑器工具
 *版本: 1.0
*/

using Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Mathematics;
using UnityEngine;

namespace Aster.DotsRenderEditor
{
    /// <summary>
    /// 预制统计信息
    /// </summary>
    [Serializable]
    public class PrefabStatisticsInfo 
    {


        [HideInInspector]
        public Transform Trans;

        [DisplayAsString]
        [HideLabel]
        [VerticalGroup("Key")]
        [PropertyOrder(0)]
        public string UniqueKey;

        [HideLabel]
        [VerticalGroup("网格")]
        [PropertyOrder(1)]
        public Mesh mesh;

        [HideLabel]
        [ShowInInspector]
        [DisplayAsString]
        [VerticalGroup("网格顶点数")]
        [PropertyOrder(1)]
        public int MeshVertexCount
        {
            get { return mesh == null ? 0 : mesh.vertexCount; }
            set { }
        }

        [HideLabel]
        [VerticalGroup("材质球")]
        [PropertyOrder(2)]
        public Material material;

        [DisplayAsString]
        [HideLabel, ShowInInspector]
        [VerticalGroup("引用计数")]
        [PropertyOrder(3)]
        public int RefrenceCount => RefrenceTargets.Count;

        [HideLabel]
        [VerticalGroup("缩放边界")]
        [PropertyOrder(2)]
        [DisplayAsString]
        [ShowInInspector]
        public string ScaleMinMaxStr
        {
            get { return $"{ScaleMinMax.x} => {ScaleMinMax.y} "; }
            set { }
        }

        [HideLabel]
        [VerticalGroup("网格尺寸")]
        [PropertyOrder(2)]
        [DisplayAsString, ShowInInspector]
        public float MeshBounds
        {
            get
            {
                if (mesh == null)
                    return 0;
                return mesh.bounds.extents.magnitude;
            }
            set { }
        }

        [HideLabel]
        [VerticalGroup("推荐缩放精度")]
        [PropertyOrder(2)]
        [DisplayAsString, ShowInInspector]
        public float SuggestScalePrecision
        {
            get { return 1.0f / MeshBounds; }
            set { }
        }

        [HideInInspector]
        public Vector2 ScaleMinMax = new Vector2(float.MaxValue, float.MinValue);

        /// <summary>
        /// 缓存引用的对象；
        /// </summary>
        [HideInInspector]
        public List<PrefabInfo> RefrenceTargets = new List<PrefabInfo>(2048);

        public void AddRefrenceTarget(PrefabInfo target)
        {
            //if (RefrenceTargets.Contains(target))
            //    return;耗时非常严重，先不判定 Contains

            RefrenceTargets.Add(target);

            float3 scale = target.Scale;
            float scaleMin = math.min(math.min(scale.x, scale.y), scale.z);
            float scaleMax = math.max(math.max(scale.x, scale.y), scale.z);

            ScaleMinMax.x = math.min(ScaleMinMax.x, scaleMin);
            ScaleMinMax.y = math.max(ScaleMinMax.y, scaleMax);
        }

        public bool HasSameTransform(PrefabInfo target)
        {
            bool hasSameTrasform = false;

            Parallel.ForEach(RefrenceTargets, (info, loopState) =>
            {
                if (math.any(info.Position != target.Position))
                    return;

                if (math.any(info.Rotation.value != target.Rotation.value))
                    return;

                if (math.any(info.Scale != target.Scale))
                    return;

                hasSameTrasform = true;
                loopState.Break();
            });

            return hasSameTrasform;
        }

        public void CopyToParent(Transform parent)
        {
            foreach (var item in RefrenceTargets)
            {
                var newObj = UnityEngine.Object.Instantiate(item.Renderer.gameObject, parent, true);
                newObj.name = UniqueKey;
                newObj.transform.localPosition = item.Position;
                newObj.transform.localRotation = item.Rotation;
                newObj.transform.localScale = item.Scale;

                var count = newObj.transform.childCount;
                for (int i = count - 1; i >= 0; i--)
                {
                    var child = newObj.transform.GetChild(i);
                    child.gameObject.Destory();
                }
            }
        }

    }
}
