using o0.Geometry2D.Float;
using System;
using System.Diagnostics;
using UnityEngine;

namespace ZIM.Unity
{
    // 记录屏幕的位置，Quad表示屏幕4个点的坐标
    // TransformToScreen可将摄像机空间的点映射到屏幕空间，反之用TransformToCamera
    public class ScreenMap
    {
        public Rect QuadRect { get; private set; }
        public Vector2 UVSize { get; private set; }     // UV代表屏幕空间的坐标，UVSize代表屏幕坐标的取值范围
        public bool Active => quad != null;
        

        public OrdinalQuadrilateral Quad
        {
            get => quad;
            set
            {
                quad = value;
                if (value != null)
                {
                    var x = Math.Min((value.A - value.B).Length, (value.C - value.D).Length);
                    var y = Math.Min((value.A - value.C).Length, (value.B - value.D).Length);
                    UVSize = new Vector2(x, y);
                    perspective = new ZIMPerspectiveTransform(value, new OrdinalQuadrilateral(new Vector(0, 0), new Vector(x, 0), new Vector(0, y), new Vector(x, y)));

                    var aabb = value.AABBRect();
                    QuadRect = new Rect(aabb.Item1.x, aabb.Item1.y, aabb.Item2.x - aabb.Item1.x, aabb.Item2.y - aabb.Item1.y);
                    //Debug.Log(QuadRect);
                }
            }
        }
        OrdinalQuadrilateral quad;
        ZIMPerspectiveTransform perspective;

        public ScreenMap()
        {

        }

        public ScreenMap(OrdinalQuadrilateral quad)
        {
            Quad = quad;
        }

        public bool UVInScreen(Vector2 v)
        {
            return v.x > 0 && v.x < UVSize.x && v.y > 0 && v.y < UVSize.y;
        }

        // UV归一化到[0, 1]范围，仅用于输出最终结果
        public Vector2 UVNormalize(Vector2 location)
        {
            return new Vector2(location.x / UVSize.x, location.y / UVSize.y);
        }

        public Vector2 TransformToScreen(Vector2 vIn)
        {
            var v = perspective.Transform(vIn.x, vIn.y);
            return new Vector2(v.x, v.y);
        }

        public Vector2 TransformToCamera(Vector2 vIn)
        {
            var v = perspective.TransformInverse(vIn.x, vIn.y);
            return new Vector2(v.x, v.y);
        }
    }
}
