using System.Collections.Generic;
using System.Linq;
using Assets.Common;
using Assets.Map;
using UnityEngine;

namespace Assets
{
    [RequireComponent(typeof(MeshFilter))]
    [RequireComponent(typeof(MeshRenderer))]
    [RequireComponent(typeof(GraphGenerator))]
    public class MapRenderer : MonoBehaviour
    {
        public float uvScale = 1.0f;
        
        private List<Vector3> _vertices;
        private List<Vector3> _normals;
        private List<int> _triangles;
        private List<Color> _colors;

        public void Generate()
        {
            var graph = GetComponent<GraphGenerator>();
            
            graph.Reset();
            graph.Generate();

            var points = graph.VoronoiGenerator.Voronoi.Vertices;

            _vertices = new List<Vector3>();
            _normals = new List<Vector3>();
            _triangles = new List<int>();
            _colors = new List<Color>();

            foreach (var location in graph.LocationGenerator.Result.Vertices.Skip(1))
                GenerateLocationMesh(location, points);
            
            Mesh mesh = new Mesh();
            mesh.vertices = _vertices.ToArray();
            mesh.uv = _vertices.Select(v => new Vector2(v.x, v.z) / uvScale).ToArray();
            mesh.normals = _normals.ToArray();
            mesh.triangles = _triangles.ToArray();
            mesh.colors = _colors.ToArray();

            GetComponent<MeshFilter>().sharedMesh = mesh;
        }

        public void GenerateLocationMesh(Location location, IList<Point> points)
        {
            foreach (var vertices in location.Sites.Select(site => site.Site.Edges.Select(x => points[x.Item1]).Reverse()))
            {
                int start = _vertices.Count;
                
                foreach (var vertex in vertices)
                {
                    _vertices.Add(new Vector3((float)vertex.x, location.Type.height + Mathf.PerlinNoise((float)vertex.x, (float)vertex.y) * 3, (float)vertex.y));
                    _normals.Add(Vector3.up);
                    _colors.Add(location.Type.color);
                }

                int end = _vertices.Count;

                for (int i = start + 1; i < end - 1; i++)
                {
                    _triangles.AddRange(new []{ start, i, i+1 });
                }
            }
        }
    }
}