// Benjamin Gordon, 2016

// This is a heavily modified version of this script:
    // DestructibleObject - provides functionality to destroy whatever GameObject the script is attached to
    // the attached object must have a MeshFilter in its children, and its shrapnel objects must have a renderer in the root.
    // by Eli http://forum.unity3d.com/threads/splitting-a-mesh.11112/
 
using UnityEngine;
 
public class DestructibleObject : MonoBehaviour
{
    public GameObject shrapnelPrefab;
    public AudioClip breakSound;
    public float explodeForce = 10.0f;
    public float explodeDirOffset = 5;
    public int shrapnelLayer = 8;
    //public float lifespan = 10.0f;
    public int density = 8; // lower density is more; affects how many fragments are spawned. 
   
    protected bool destroyed = false;
    //protected GameObject[] pieces;
    protected AudioSource source;
   
    void Start() {
        source = GetComponent<AudioSource>();

        density *= 3; // Just a check to make sure I can divide things right.
    }

    public virtual void Update()
    {
        if(Input.GetButtonDown("Fire1"))
            Explode();
    }
   
    public virtual void Explode()
    {
        if (destroyed)
        {
            return;
        }
        destroyed = true;
       
        //construct all the individual destructible pieces from our mesh
        MeshFilter filter = GetComponent<MeshFilter>();
        Mesh mesh = filter.mesh;
        
        //a sneaky easy way to get the children to be sized correctly is to have a unit scale when spawning them, then restore it later
        Vector3 oldScale = transform.localScale;
        transform.localScale = new Vector3(1,1,1);
       
        for (int i = 0; i < mesh.triangles.Length; i+= density)
        {  
            GameObject go = Instantiate(shrapnelPrefab) as GameObject;
            MeshFilter meshFilter = go.GetComponent<MeshFilter>();
            Mesh newMesh = meshFilter.mesh;

            // Set up the fragment's vertices
            newMesh.vertices = new Vector3[]
            {
                mesh.vertices[mesh.triangles[i+0]],
                mesh.vertices[mesh.triangles[i+1]],
                mesh.vertices[mesh.triangles[i+2]],
                mesh.vertices[mesh.triangles[i]] - mesh.normals[mesh.triangles[i]] * 0.15f,
            };

            // Set up the fragment's UV cooridinates so that it inherits the object's texture.
            newMesh.uv = new Vector2[]
            {
                mesh.uv[mesh.triangles[i+0]],
                mesh.uv[mesh.triangles[i+1]],
                mesh.uv[mesh.triangles[i+2]],
                mesh.uv[mesh.triangles[i+0]]
            };

            // Set up the fragment's triangles, using arrays ordered by vertices.
            // This makes a pyramid shape, rather than a flat triangle.
            newMesh.triangles = new int[]
            {
                2, 1, 3, // Vertex 2, 1, 3 = first tri
                3, 0, 2, // Vertex 3, 0, 2 = second tri
                1, 0, 3, // Vertex 1, 0, 3 = third tri
                0, 1, 2  // Vertex 0, 1, 2 = fourth tri
            };

            newMesh.RecalculateNormals();
            go.GetComponent<MeshCollider>().sharedMesh = newMesh;
            go.GetComponent<MeshRenderer>().material = GetComponent<Renderer>().material;
            //Rigidbody rigidbody = ;

            go.layer = shrapnelLayer;
            go.transform.parent = filter.transform;
            go.transform.localPosition = Vector3.zero;
            go.transform.localRotation = Quaternion.identity;
      
            Vector3 explodeDirection = (meshFilter.mesh.normals[0] + meshFilter.mesh.normals[1] + meshFilter.mesh.normals[2]).normalized * explodeForce;



            // By dividing the y, more of the fragments shoot out too the sides instead of the top.
            explodeDirection.y /= explodeDirOffset;

            //go.GetComponent<Rigidbody>().AddForce(explodeDirection, ForceMode.Impulse);
            go.GetComponent<Rigidbody>().AddForceAtPosition(explodeDirection, go.transform.localPosition, ForceMode.Impulse);
            //go.GetComponent<Rigidbody>().AddForce((go.transform.localPosition - transform.position).normalized * explodeForce, ForceMode.Impulse);
        }

        // Remove geometry from our old mesh.
        mesh.triangles = new int[0];
        mesh.vertices = new Vector3[0];
        mesh.uv = new Vector2[0];
        mesh.normals = new Vector3[0];

        transform.localScale = oldScale;

        // Remove unnecessary components from original gameObject
        Rigidbody rigidBody = GetComponent<Rigidbody>();
        if(rigidBody != null)
            Destroy(rigidBody);

        Collider collider = GetComponent<Collider>();
        if(collider != null)
            Destroy(collider);
        source.PlayOneShot(breakSound);
    }
}
// Extra triangle indexes that didn't work out.
                //0, 1, 2,
                //1, 0, 3,
                //3, 0, 2,
                //2, 1, 3

                //0, 3, 2,
                //0, 1, 2,
                //0, 1, 3,
                //1, 2, 3

                //0, 1, 2,
                //0, 3, 2,
                //0, 2, 3,
                //1, 2, 3

                //2, 1, 0,
                //2, 3, 0,
                //3, 2, 0,
                //3, 2, 1
