using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;

namespace VOID.Generic.AreaOfEffect
{
    [TypeRegistryItem("Cone")]
    public class ConeAreaOfEffect : AbstractAreaOfEffect
    {
        [SerializeField, Required, MinValue(0.5), MaxValue(10)]
        private float length;
        [SerializeField, Required, MinValue(10), MaxValue(350)]
        private float degree;

        public override Mesh GetMesh()
        {
            var mesh = GenerateConeMesh();
            mesh.vertices = mesh.vertices.Select(vertex => Vector3.Scale(vertex, new Vector3(length, 1, length))).ToArray();
            return mesh;
        }

        public override Collider AddCollider(GameObject gameObject)
        {
            var collider = gameObject.AddComponent<MeshCollider>();
            collider.sharedMesh = GetMesh();
            collider.convex = true;
            collider.isTrigger = true;

            return collider;
        }

        private Mesh GenerateConeMesh()
        {
            var sections = Mathf.FloorToInt(degree / 10);
            var mesh = new Mesh();

            var vertices = new Vector3[4 + sections * 2];
            var uv = new Vector2[vertices.Length];
            var triangles = new int[(4 + sections * 4) * 3];

            var currentAngle = -sections * 10 / 2;
            var vertexIndex = 0;
            var triangleIndex = 0;

            vertices[0] = new Vector3(0,-0.5f,0);
            vertices[1] = new Vector3(0,0.5f,0);
            vertices[2] = new Vector3(Mathf.Sin(Mathf.Deg2Rad * currentAngle), -0.5f, Mathf.Cos(Mathf.Deg2Rad * currentAngle));
            vertices[3] = new Vector3(Mathf.Sin(Mathf.Deg2Rad * currentAngle), 0.5f, Mathf.Cos(Mathf.Deg2Rad * currentAngle));

            triangles[0] = 0;
            triangles[1] = 3;
            triangles[2] = 1;
            triangles[3] = 0;
            triangles[4] = 2;
            triangles[5] = 3;

            for (var i = 0; i < sections; i++)
            {

                vertexIndex = 4 + i*2;
                triangleIndex = (2 + i*4) * 3;
                currentAngle += 10;
                
                vertices[vertexIndex+0] = new Vector3(Mathf.Sin(Mathf.Deg2Rad * currentAngle), -0.5f, Mathf.Cos(Mathf.Deg2Rad * currentAngle));
                vertices[vertexIndex+1] = new Vector3(Mathf.Sin(Mathf.Deg2Rad * currentAngle), 0.5f, Mathf.Cos(Mathf.Deg2Rad * currentAngle));

                triangles[triangleIndex+0] = 0;
                triangles[triangleIndex+1] = vertexIndex;
                triangles[triangleIndex+2] = vertexIndex-2;

                triangles[triangleIndex+3] = 1;
                triangles[triangleIndex+4] = vertexIndex-1;
                triangles[triangleIndex+5] = vertexIndex+1;

                triangles[triangleIndex+6] = vertexIndex-2;
                triangles[triangleIndex+7] = vertexIndex;
                triangles[triangleIndex+8] = vertexIndex-1;

                triangles[triangleIndex+9] = vertexIndex;
                triangles[triangleIndex+10] = vertexIndex+1;
                triangles[triangleIndex+11] = vertexIndex-1;
            }

            triangleIndex += 12;
            triangles[triangleIndex+0] = 0;
            triangles[triangleIndex+1] = vertexIndex+1;
            triangles[triangleIndex+2] = vertexIndex;
            
            triangles[triangleIndex+3] = 0;
            triangles[triangleIndex+4] = 1;
            triangles[triangleIndex+5] = vertexIndex+1;

            mesh.vertices = vertices;
            mesh.uv = uv;
            mesh.triangles = triangles;
            
            return mesh;
        }
    }
}