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

namespace ZIM.Unity
{
    // 摄像机的取景画面的纵横比设置（取景画面纵横比是否会根据分辨率变化）
    public enum AspectRatioSetting
    {
        FixedAll,       // 高度和宽度都不变
        FixedHeight,    // 高度固定
        FixedWidth,     // 宽度固定
    }

    // 记录屏幕的位置，QuadInCamera表示屏幕4个点在摄像机画面中的坐标
    // TransformToScreen可将摄像机空间的点映射到屏幕空间，反之用TransformToCamera
    public class ScreenMap
    {
        public static AspectRatioSetting ViewAspectRatioSetting = AspectRatioSetting.FixedHeight;// 默认取景画面的高度保持不变，宽度随着分辨率变化

        public Rect QuadRect { get; private set; }
        public Vector2 UVSize { get; private set; }     // UV代表屏幕空间的坐标，UVSize代表屏幕坐标的取值范围
        public bool Active => QuadInCamera != null;

        QuadrilateralInCamera quadInCamera;     // 记录的分辨率和识别时的分辨率可能不同
        public QuadrilateralInCamera QuadInCamera
        {
            get => quadInCamera;
            set
            {
                quadInCamera = value;
                InitByQuad();
                Debug.Log("QuadRect:"+QuadRect);
            }
        }

        // 当分辨率不同时，刷新分辨率并返回true，否则返回false
        public bool RefreshCameraSize(Vector2 curSize)
        {
            var sizeNew = curSize.o0Vector();
            if (QuadInCamera != null && QuadInCamera.CameraSize != sizeNew)
            {
                UnityEngine.Debug.Log("[ScreenMap]根据分辨率映射: from " + QuadInCamera.SizeString + " to " + curSize);
                QuadInCamera.ReSize(sizeNew, ViewAspectRatioSetting);
                InitByQuad();
                return true;
            }
            return false;
        }

        private void InitByQuad()
        {
            if (QuadInCamera != null)
            {
                var quad = QuadInCamera.Quad;
                var x = Math.Min((quad.A - quad.B).Length, (quad.C - quad.D).Length);
                var y = Math.Min((quad.A - quad.C).Length, (quad.B - quad.D).Length);
                UVSize = new Vector2(x, y);
                perspective = new ZIMPerspectiveTransform(quad, new OrdinalQuadrilateral(new Vector(0, 0), new Vector(x, 0), new Vector(0, y), new Vector(x, y)));

                var aabb = quad.AABBRect();
                QuadRect = new Rect(aabb.Item1.x, aabb.Item1.y, aabb.Item2.x - aabb.Item1.x, aabb.Item2.y - aabb.Item1.y);
            }
        }

        private ZIMPerspectiveTransform perspective;

        public ScreenMap()
        {

        }

        public ScreenMap(QuadrilateralInCamera quad)
        {
            QuadInCamera = 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 UVNormalized(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);
        }
    }
}
