﻿using UnityEngine;

namespace JLGames.RocketDriver.Actions.Extensions
{
    public struct TransformInfo
    {
        public Vector3 Position;
        public Vector3 LocalScale;
        public Quaternion LocalRotation;
    }
    
    public static class ExtTransform
    {
        public static TransformInfo CloneTransform(this Transform transform)
        {
            var clone = new TransformInfo
            {
                Position = transform.position,
                LocalScale = transform.localScale,
                LocalRotation = transform.localRotation
            };
            return clone;
        }

        public static void UpdateTransform(this Transform tranform, TransformInfo info)
        {
            tranform.position = info.Position;
            tranform.localScale = info.LocalScale;
            tranform.localRotation = info.LocalRotation;
        }

        public static Bounds GetBounds(this Transform target)
        {
            var renderers = target.GetComponentsInChildren<Renderer>();
            var min = target.position;
            var max = target.position;
            for (var i = 0; i < renderers.Length; i++)
            {
                min = Vector3.Min(renderers[i].bounds.min, min);
                max = Vector3.Max(renderers[i].bounds.max, max);
            }

            return new Bounds((max + min) / 2, max - min);
        }

        /// <summary>
        /// Calculate the screen bounding box of the object projected on the camera
        /// 计算物件投影在相机上的屏幕包围盒
        /// x, y: 像素[0,正无穷]
        /// z: 米
        /// </summary>
        /// <returns>The screen bounds.</returns>
        /// <param name="target">Target.</param>
        /// <param name="targetCamera">Target camera.</param>
        public static Bounds GetScreenBounds(this Transform target, Camera targetCamera)
        {
            var points = target.GetBounds().Get8Points();
            var max = targetCamera.WorldToScreenPoint(target.position);
            var min = max;
            foreach (var point in points)
            {
                var screenPoint = targetCamera.WorldToScreenPoint(point);
                min = Vector3.Min(screenPoint, min);
                max = Vector3.Max(screenPoint, max);
            }

            return new Bounds((max + min) / 2, max - min);
        }

        /// <summary>
        /// Calculate the bounding box of the object projected on the viewport
        /// 计算物件投影在视窗上的包围盒
        /// x,y: [0,1];
        /// z: 米
        /// </summary>
        /// <returns>The viewport bounds.</returns>
        /// <param name="target">Target.</param>
        /// <param name="targetCamera">Target camera.</param>
        public static Bounds GetViewportBounds(this Transform target, Camera targetCamera)
        {
            var points = target.GetBounds().Get8Points();
            var max = targetCamera.WorldToViewportPoint(target.position);
            var min = max;
            foreach (var point in points)
            {
                var screenPoint = targetCamera.WorldToViewportPoint(point);
                min = Vector3.Min(screenPoint, min);
                max = Vector3.Max(screenPoint, max);
            }

            return new Bounds((max + min) / 2, max - min);
        }
    }
}