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

namespace ZIM.Unity
{
    // 屏幕识别使用，记录摄像机画面内的四边形
    public class QuadrilateralInCamera
    {
        public Vector CameraSize;
        public OrdinalQuadrilateral Quad;

        // 固定的顶点顺序： 左下，右下，左上，右上
        public QuadrilateralInCamera(Vector2 a, Vector2 b, Vector2 c, Vector2 d, Vector2 cameraSize)
        {
            CameraSize = cameraSize.o0Vector();
            Quad = new OrdinalQuadrilateral(a.o0Vector(), b.o0Vector(), c.o0Vector(), d.o0Vector());
        }

        // 固定的顶点顺序： 左下，右下，左上，右上
        public QuadrilateralInCamera(Vector a, Vector b, Vector c, Vector d, Vector cameraSize)
        {
            CameraSize = cameraSize;
            Quad = new OrdinalQuadrilateral(a, b, c, d);
        }

        // 固定的顶点顺序： 左下，右下，左上，右上
        public QuadrilateralInCamera(IEnumerable<Vector> enumable, Vector cameraSize)
        {
            CameraSize = cameraSize;
            Quad = new OrdinalQuadrilateral(enumable);
        }

        public QuadrilateralInCamera(OrdinalQuadrilateral quad, Vector cameraSize)
        {
            CameraSize = cameraSize;
            Quad = quad;
        }

        public string SizeString => $"({CameraSize.x}, {CameraSize.y})";
        public string QuadString => $"[({Quad.A.x}, {Quad.A.y}), ({Quad.B.x}, {Quad.B.y}), ({Quad.C.x}, {Quad.C.y}), ({Quad.D.x}, {Quad.D.y})]";

        // 需要标准化的坐标(即数值范围0-1)时使用，会自动根据当前的CameraSize转换
        private List<Vector> ScreenVertexListNormalized
        {
            get
            {
                return new List<Vector> {
                    Quad.A / CameraSize,
                    Quad.B / CameraSize,
                    Quad.C / CameraSize,
                    Quad.D / CameraSize
                };
            }
            set
            {
                for (int i = 0; i < Quad.Count; i++)
                    Quad[i] = value[i] * CameraSize;
            }
        }

        // 这里是标准化坐标(即数值范围0-1)
        public List<Vector2> GetUnityVertexList()
        {
            return new List<Vector2>() {
                new Vector2(Quad.A.x / CameraSize.x, Quad.A.y / CameraSize.y),
                new Vector2(Quad.B.x / CameraSize.x, Quad.B.y / CameraSize.y),
                new Vector2(Quad.C.x / CameraSize.x, Quad.C.y / CameraSize.y),
                new Vector2(Quad.D.x / CameraSize.x, Quad.D.y / CameraSize.y)
            };
        }

        // 摄像机分辨率变化时调用
        public void ReSize(Vector sizeNew, AspectRatioSetting viewAspectRatioSetting)
        {
            float ratio;
            Func<Vector, Vector> Translate;
            List<Vector> vertices;
            switch (viewAspectRatioSetting)
            {
                case AspectRatioSetting.FixedAll:
                    var scale = new Vector(sizeNew.x / CameraSize.x, sizeNew.y / CameraSize.y);
                    CameraSize = sizeNew;
                    for (int i = 0; i < Quad.Count; i++)
                        Quad[i] *= scale;

                    break;
                case AspectRatioSetting.FixedHeight:
                    var wOld = CameraSize.x / CameraSize.y;                // 宽度比高度
                    var wNew = sizeNew.x / sizeNew.y;
                    ratio = wOld / wNew;
                    Translate = (v) =>
                    {
                        var x = v.x - 0.5f;
                        return new Vector(x * ratio + 0.5f, v.y);
                    };
                    vertices = ScreenVertexListNormalized;
                    for (int i = 0; i < vertices.Count; i++)
                        vertices[i] = Translate(vertices[i]);
                    CameraSize = sizeNew;                           // 这里要先设置Size
                    ScreenVertexListNormalized = vertices;

                    break;
                case AspectRatioSetting.FixedWidth:
                    var hOld = CameraSize.y / CameraSize.x;                // 高度比宽度
                    var hNew = sizeNew.y / sizeNew.x;
                    ratio = hOld / hNew;
                    Translate = (v) =>
                    {
                        var y = v.y - 0.5f;
                        return new Vector(v.x, y * ratio + 0.5f);
                    };
                    vertices = ScreenVertexListNormalized;
                    for (int i = 0; i < vertices.Count; i++)
                        vertices[i] = Translate(vertices[i]);
                    CameraSize = sizeNew;
                    ScreenVertexListNormalized = vertices;

                    break;
            }
        }

        // 四边形是否完整的在屏幕内
        public bool IsQuadComplete()
        {
            if (Quad.A.x < Quad.B.x && Quad.A.y < Quad.C.y && Quad.B.y < Quad.D.y && Quad.C.x < Quad.D.x && Quad.A.x > 0 && Quad.A.y > 0 &&
                Quad.B.x < CameraSize.x && Quad.B.y > 0 && Quad.C.x > 0 && Quad.C.y < CameraSize.y && Quad.D.x < CameraSize.x && Quad.D.y < CameraSize.y)
                return true;
            return false;
        }

    }
}