using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using Random = UnityEngine.Random;

public class PlanetPopulator : MonoBehaviour
{
    public GameObject[] doodads;

    [SerializeField]
    private int[] patchCount;
    [SerializeField]
    private int[] patchSize;
    [SerializeField]
    private float[] patchNoise;

    [SerializeField]
    private int earthMatIndex;

    private int[] earthTriangles;
    
    private List<int> earthTriangleIndexes = new List<int>();

    private void Cleanup()
    {
        GetComponent<MeshCollider>().enabled = false;
        earthTriangles = null;
        earthTriangleIndexes = null;
    }

    private void SpawnTrees(GameObject prefab, int pc, int ps, float pn)
    {
        MeshCollider meshCollider = GetComponent<MeshCollider>();
        for (int patch = 0; patch < pc; patch++)
        {
            float centerX = Random.Range(0, 360);
            float centerZ = Random.Range(0, 360);
            for (int treeNum = 0; treeNum < ps; treeNum++)
            {
                Quaternion rotation = Quaternion.Euler(centerX + Random.Range(-pn, pn), 0,
                    centerZ + Random.Range(-pn, pn));

                Vector3 direction = rotation * Vector3.up;
                Vector3 rayOrig = direction * 10;
                Ray ray = new Ray(rayOrig, -direction);
                // Instantiate(debug, rayOrig, Quaternion.identity, transform);
                if (meshCollider.Raycast(ray, out RaycastHit hit, 100.0f))
                {
                    if (earthTriangleIndexes.Contains(hit.triangleIndex))
                    {
                        Instantiate(prefab, Vector3.zero, rotation, transform);
                    }
                }
            }
        }
    }

    private void InitEarthTriangles()
    {
        Mesh mesh = GetComponent<MeshCollider>().sharedMesh;
        int[] earthTriangles = mesh.GetTriangles(earthMatIndex);
        int earthTrianglesLength = earthTriangles.Length;
        int meshTrianglesLength = mesh.triangles.Length;

        Dictionary<string, int> triangleLookup = new Dictionary<string, int>();
        for (int triangleIndex = 0; triangleIndex < meshTrianglesLength; triangleIndex += 3)
        {
            triangleLookup.Add(createKey(mesh.triangles[triangleIndex],mesh.triangles[triangleIndex+1],mesh.triangles[triangleIndex+2]),
                triangleIndex/3);
        }
        
        for (int earthTriangleIndex = 0; earthTriangleIndex < earthTrianglesLength; earthTriangleIndex += 3)
        {
            if (triangleLookup.TryGetValue(createKey(earthTriangles[earthTriangleIndex], earthTriangles[earthTriangleIndex + 1],
                earthTriangles[earthTriangleIndex + 2]), out int triangleIndex)) {
                earthTriangleIndexes.Add(triangleIndex);
            }
        }
    }

    private string createKey(int id1, int id2, int id3)
    {
        return ""+id1+"/"+id2+"/"+id3;
    }

    // Start is called before the first frame update
    void Start()
    {
        InitEarthTriangles();
        for (int i = 0; i < doodads.Length; i++)
        {
            SpawnTrees(doodads[i], patchCount[i], patchSize[i], patchNoise[i]);
        }
        Cleanup();
    }

    // Update is called once per frame
}
