using UnityEngine;

public class EnvironmentController : MonoBehaviour
{
    private bool spewFire = true;
    public Transform flame;
    public Transform thunder;
    public ParticleSystem bassPS;
    public ParticleSystem treblePS;
    public float particlesTime;
    public float emitCountPerHeightUnit;
    public float amplitudeFactor = 10.0f;
    public float meshHeight = 10.0f;
    public float offset = 0.0f;
    public float dangerSpread = 2;

    public WaveManager waveManager;
    private float particlesTimer;
    private float secondsElapsed;
    private float trebleYOrigin;
    private float bassYOrigin;

    //mesh generation
    private Vector2[] bassVertices; //+2 for bottom points on both sides

    private Vector2[] trebleVertices; //+2 for bottom points on both sides

    private Triangulator bassTriangulator;
    private Triangulator trebleTriangulator;
    private Mesh bassMesh; //yes I realise this should've been an array
    private Mesh trebleMesh;
    private MeshFilter bassFilter;
    private MeshFilter trebleFilter;

    private void Start()
    {
        float sampleDistance = WaveData.Instance.distanceBetweenSamples;
        int bufferSize = WaveData.Instance.bufferSize;
        particlesTimer = 0.0f;
        secondsElapsed = 0.0f;
        trebleYOrigin = treblePS.transform.position.y;
        bassYOrigin = bassPS.transform.position.y;

        bassVertices = new Vector2[bufferSize + 2];
        trebleVertices = new Vector2[bufferSize + 2];

        bassVertices[bufferSize + 1] = new Vector2(0.0f, -meshHeight);
        bassVertices[bufferSize] = new Vector2(sampleDistance * (bufferSize - 1), -meshHeight);
        trebleVertices[bufferSize + 1] = new Vector2(0.0f, -meshHeight);
        trebleVertices[bufferSize] = new Vector2(sampleDistance * (bufferSize - 1), -meshHeight);

        //bassFilter = bassPS.gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
        bassFilter = bassPS.GetComponent<MeshFilter>();
        trebleFilter = treblePS.GetComponent<MeshFilter>();
        bassMesh = new Mesh();
        trebleMesh = new Mesh();

        updateMeshes();
        Vector3 newPosition = transform.position;
        newPosition.y += ((amplitudeFactor) / 2) + waveManager.amplitudeFactor + offset;
        treblePS.transform.position = newPosition;
        newPosition = transform.position;
        newPosition.y -= ((amplitudeFactor) / 2) + waveManager.amplitudeFactor + offset;
        bassPS.transform.position = newPosition;
    }

    private void updateMeshes()
    {
        WaveData.WaveProperties[] wp = WaveData.Instance.bufferChannels[0].channel;

        float distance = 0;
        for (int i = 0; i < WaveData.Instance.bufferSize; i++)
        {
            bassVertices[i] = new Vector2(distance, wp[i].bass * amplitudeFactor);
            trebleVertices[i] = new Vector2(distance, wp[i].treble * amplitudeFactor);
            distance += WaveData.Instance.distanceBetweenSamples;
        }

        bassFilter.mesh = calculateMesh(bassMesh, bassVertices);
        trebleFilter.mesh = calculateMesh(trebleMesh, trebleVertices);

        int pos = Mathf.RoundToInt(WaveData.Instance.songOffsetPercentage * WaveData.Instance.bufferSize);
        if (WaveData.Instance.bufferChannels[0].channel[pos].bass > WaveData.Instance.bassToExplodeValue)
        {
            Transform flame_instance = Instantiate(flame, bassPS.transform, false);
            Transform flame_instance2 = Instantiate(flame, bassPS.transform, false);
            Transform flame_instance3 = Instantiate(flame, bassPS.transform, false);

            float fy = flame_instance.transform.position.y;
            float fz = flame_instance.transform.position.z;

            float random_x1 = Random.value * dangerSpread * 2 - dangerSpread;
            float random_x2 = Random.value * dangerSpread * 2 - dangerSpread;

            flame_instance.transform.position = new Vector3(WaveData.Instance.charPos, fy, fz);
            flame_instance2.transform.position = new Vector3(WaveData.Instance.charPos + random_x1, fy, fz);
            flame_instance3.transform.position = new Vector3(WaveData.Instance.charPos + random_x2, fy, fz);

            Destroy(flame_instance.gameObject, 1);
            Destroy(flame_instance2.gameObject, 1);
            Destroy(flame_instance3.gameObject, 1);

            if (!GameManager.Instance.playerInstance.isUp)
            {
                GameManager.Instance.Die();
            }
        }
        else if (WaveData.Instance.bufferChannels[0].channel[pos].treble > WaveData.Instance.trebleToThunderValue)
        {
            Transform thunder_instance = Instantiate(thunder, treblePS.transform, false);
            Transform thunder_instance2 = Instantiate(thunder, treblePS.transform, false);
            Transform thunder_instance3 = Instantiate(thunder, treblePS.transform, false);

            float fy = thunder_instance.transform.position.y;
            float fz = thunder_instance.transform.position.z;

            float random_x1 = Random.value * dangerSpread * 2 - dangerSpread;
            float random_x2 = Random.value * dangerSpread * 2 - dangerSpread;

            thunder_instance.transform.position = new Vector3(WaveData.Instance.charPos + random_x1, fy, fz);
            thunder_instance2.transform.position = new Vector3(WaveData.Instance.charPos + random_x1, fy, fz);
            thunder_instance3.transform.position = new Vector3(WaveData.Instance.charPos + random_x1, fy, fz);

            thunder_instance.transform.localScale = new Vector3(thunder_instance.transform.localScale.x, -thunder_instance.transform.localScale.y, thunder_instance.transform.localScale.z);
            thunder_instance2.transform.localScale = new Vector3(thunder_instance2.transform.localScale.x, -thunder_instance2.transform.localScale.y, thunder_instance.transform.localScale.z);
            thunder_instance3.transform.localScale = new Vector3(thunder_instance3.transform.localScale.x, -thunder_instance3.transform.localScale.y, thunder_instance.transform.localScale.z);

            Destroy(thunder_instance.gameObject, 1);
            Destroy(thunder_instance2.gameObject, 1);
            Destroy(thunder_instance3.gameObject, 1);

            if (GameManager.Instance.playerInstance.isUp)
            {
                GameManager.Instance.Die();
            }
        }
    }

    private Mesh calculateMesh(Mesh mesh, Vector2[] vertices)
    {
        Triangulator tri = new Triangulator(vertices);

        int[] indices = tri.Triangulate();

        Vector3[] vertices3D = new Vector3[vertices.Length];

        for (int i = 0; i < vertices.Length; i++)
        {
            vertices3D[i] = new Vector3(vertices[i].x, vertices[i].y, 0);
        }

        mesh.vertices = vertices3D;
        mesh.triangles = indices;

        return mesh;
    }

    private void Update()
    {
        updateMeshes();

        //secondsElapsed += Time.deltaTime;
        //if(Input.GetKeyDown(KeyCode.F1))
        //{
        //    if (spewFire)
        //    {
        //        for (int i = 0; i < 20; i++)
        //        {
        //            Vector3 spawnPos = transform.position;
        //            spawnPos.x = Random.Range(-5, 5);
        //            spawnPos.z = Random.Range(-0.5f, -1.5f);
        //            Instantiate(flame, spawnPos, transform.rotation,transform);
        //        }
        //    }
        //}
        //particlesTimer += Time.deltaTime;
        //if (particlesTimer > particlesTime)
        //{
        //    particlesTimer = 0.0f;
        //    //treble
        //    float height = WaveData.Instance.bufferChannels[0].channel[0].treble;
        //    //print(height);
        //    height = 0;
        //    Vector3 newPos = treblePS.transform.position;
        //    newPos.y = trebleYOrigin - (height/2.0f);
        //    treblePS.transform.position = newPos;

        //    ParticleSystem.ShapeModule treblePSShape = treblePS.shape;
        //    treblePSShape.radius = (height+1.0f)*0.5f;
        //    treblePS.Emit((int)(emitCountPerHeightUnit * (height+1)));

        //    //bass
        //    height = WaveData.Instance.bufferChannels[0].channel[0].bass;
        //    print(height);
        //    newPos = bassPS.transform.position;
        //    newPos.y = bassYOrigin + (height / 2.0f);
        //    bassPS.transform.position = newPos;

        //    ParticleSystem.ShapeModule bassPSShape = bassPS.shape;
        //    bassPSShape.radius = (height + 1.0f) * 0.5f;
        //    bassPS.Emit((int)(emitCountPerHeightUnit * (height + 1)));
        //}
    }
}