using System.Collections.Generic;
using System.Linq;
using Unity.AI.Navigation;
using UnityEngine;
using UnityEngine.AI;
namespace XenseAR
{

    public class NavigationMeshVisualizer : MonoBehaviour
    {
        public bool ShowVisualization = false;

        [Header("Required components")]
        [SerializeField] Material NavMeshMaterial;
        [SerializeField] Vector3 VisualizationMeshOffset = new Vector3(0f, 0f, 0f);

        [Header("VisualData")]
        [SerializeField] List<NavMeshSurface> navMeshSurfaces;

        NavigationMeshManager navigationMeshManager;
        GameObject MeshVisualization;
        List<GameObject> MeshVisualizations = new List<GameObject>();

        private void Start()
        {
            navigationMeshManager = Container.Resolve<NavigationMeshManager>();
            MeshVisualization = new GameObject("Mesh Visualization");
            MeshVisualization.transform.SetParent(transform);

            //Layer #7 is debug layer
            MeshVisualization.layer = 7;
        }

        public void UpdateNavMesh(/*GameObject NavMeshRoot*/)
        {
            if (navigationMeshManager == null) return;
            navMeshSurfaces = navigationMeshManager.GetNavMeshRoot().GetComponentsInChildren<NavMeshSurface>().ToList();
            List<GameObject> temp = new List<GameObject>(MeshVisualizations);

            foreach (var MeshVisualization in MeshVisualizations)
            {
                if (MeshVisualization == null)
                    temp.Remove(MeshVisualization);
                else
                {
                    Destroy(MeshVisualization);
                    temp.Remove(MeshVisualization);
                }
            }

            MeshVisualizations = temp;

            ShowVisualization = !ShowVisualization;

            MeshVisualization.SetActive(ShowVisualization);
            MeshVisualization.transform.position = VisualizationMeshOffset;

            foreach (var navMeshSurface in navMeshSurfaces)
            {
                NavMesh.RemoveAllNavMeshData();
                navMeshSurface.BuildNavMesh();

                //var navMeshDataInstance = NavMesh.AddNavMeshData(navMeshSurface.navMeshData);

                NavMeshTriangulation triangulation = NavMesh.CalculateTriangulation();

                GameObject visualization = new GameObject($"Surface {navMeshSurface.gameObject.name} for Agent {navMeshSurface.agentTypeID}");
                visualization.transform.SetParent(MeshVisualization.transform, false);
                visualization.layer = MeshVisualization.layer;
                MeshVisualizations.Add(visualization);

                Dictionary<int, List<int>> areaIndices = new Dictionary<int, List<int>>();
                for (int i = 0; i < triangulation.areas.Length; i++)
                {
                    if (!areaIndices.ContainsKey(triangulation.areas[i]))
                    {
                        areaIndices.Add(triangulation.areas[i], new List<int>());
                    }

                    areaIndices[triangulation.areas[i]].Add(triangulation.indices[3 * i]);
                    areaIndices[triangulation.areas[i]].Add(triangulation.indices[3 * i + 1]);
                    areaIndices[triangulation.areas[i]].Add(triangulation.indices[3 * i + 2]);
                }

                MeshRenderer renderer = visualization.AddComponent<MeshRenderer>();
                MeshFilter filter = visualization.AddComponent<MeshFilter>();
                Mesh mesh = new Mesh();

                mesh.subMeshCount = areaIndices.Count;
                mesh.SetVertices(triangulation.vertices);

                Material[] materials = new Material[areaIndices.Count];
                int index = 0;
                foreach (var areaIndice in areaIndices)
                {
                    mesh.SetTriangles(areaIndice.Value, index);

                    Material material = new Material(NavMeshMaterial);
                    Color randomColor = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), 0.4f);
                    material.color = randomColor;
                    materials[index] = material;
                    index++;
                }

                renderer.sharedMaterials = materials;
                filter.mesh = mesh;
            }

            foreach (var navMeshSurface in navMeshSurfaces)
            {
                navMeshSurface.BuildNavMesh();
            }
        }
    }
}
