using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

//============================================================
//支持中文,文件使用UTF-8编码
//@author	JiphuTzu
//@create	20220910
//@company	Umawerse
//
//@description:
//============================================================
namespace Umawerse.FiniteStateMachines
{
    public class PolygonDrawState : DrawingState
    {
        private Mesh _mesh;
        private LineRenderer _line;
        public PolygonDrawState(ToolsBootstrap root) : base(root, StateName.polygon, 3, 99)
        {
        }

        protected override void OnTap(Vector3 pos)
        {
            AddPoint(pos);
        }

        protected override void OnDoubleTap(Vector3 pos)
        {
            AddPoint(pos);
        }

        protected override void UpdatePreview(Vector3 pos)
        {
            var verts = new List<Vector3>();
            verts.AddRange(vertices);
            verts.Add(pos);
            Show(verts);
        }

        public override void Init()
        {
            base.Init();
            _mesh = new Mesh();
            target.AddComponent<MeshFilter>().mesh = _mesh;
            var renderer = target.AddComponent<MeshRenderer>();
            renderer.material = root.ployMaterial;
            renderer.material.color = Color.green;
            //
            var mr = new GameObject("LineRender");
            mr.transform.SetParent(target.transform);
            _line = mr.AddComponent<LineRenderer>();
            _line.sortingOrder = -1;
            _line.startWidth = 0.3f;
            _line.endWidth = 0.3f;
            _line.numCornerVertices = 3;
            _line.material = root.solidLineMaterial;
            _line.material.color = Color.green;
        }

        public override void Complete()
        {
            Show(vertices);
            var mc = target.AddComponent<MeshCollider>();
            //var label = Object.Instantiate(root.labelPrefab, target.transform);
            //label.Init($"面积:", false);
            //label.SetPosition(mc.bounds.center + Vector3.up);
            //label.SetAlignment();
        }



        public override void AddPoint(Vector3 position, bool showImmediately = true)
        {
            vertices.Add(position);
            if (showImmediately)
            {
                var h = vertices[0].y > position.y ? vertices[0].y : position.y;
                for (var i = 0; i < vertices.Count; i++)
                {
                    var v = vertices[i];
                    v.y = h;
                    vertices[i] = v;
                    if (i + 1 < target.transform.childCount)
                        target.transform.GetChild(i + 1).position = v;
                }
            }
            var ployPoint = Object.Instantiate(root.ployPointPrefab, target.transform);
            ployPoint.transform.localPosition = vertices[vertices.Count - 1];
            var mr = ployPoint.GetComponent<MeshRenderer>();
            mr.material.SetColor(COLOR_ID, Color.green);
            mr.sortingOrder = 2;

            if (vertices.Count < 3 || !showImmediately) return;
            Show(vertices);
        }

        private void Show(List<Vector3> verts)
        {
            var triangles = new List<int>();
            for (var i = 2; i < verts.Count; i++)
            {
                triangles.Add(0);
                if (IsUp(verts[i] - verts[0], verts[i - 1] - verts[0]))
                {
                    triangles.Add(i);
                    triangles.Add(i - 1);
                }
                else
                {
                    triangles.Add(i - 1);
                    triangles.Add(i);
                }

            }
            _mesh.vertices = verts.ToArray();
            _mesh.triangles = triangles.ToArray();
            //
            var vs = new Vector3[verts.Count + 1];
            verts.CopyTo(vs);
            vs[vs.Length - 1] = vs[0];
            _line.positionCount = vs.Length;
            _line.SetPositions(vs);
            _line.material.SetFloat("_Cnt", GetLength(vs) / 3);
        }

        private bool IsUp(Vector3 a, Vector3 b)
        {
            var nor = Vector3.Cross(a, b);
            var angle = Vector3.Dot(nor, Vector3.up);
            return angle > 0;
        }
        private float GetLength(Vector3[] verts)
        {
            var length = 0f;
            for (var i = 1; i < verts.Length; i++)
            {
                length += Vector3.Distance(verts[i], verts[i - 1]);
            }
            return length;
        }
    }
}