﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Asteroid : SpaceObject
{
    [System.Serializable]
    //Contains information about what to spawn, where, and what direction it should fly in
    public class SubAsteroid
    {
        //Which prefab to spawn
        public GameObject prefab;
        //Where to spawn, relative to the main Asteroid
        public Vector3 position;
        //Initial velocity, to be effected by the Explode normal direction
        public Vector3 velocity;
        //randomize rotation?
        public bool randomRotation;
    }

    //Asteroid hit points
    public int hp = 5;
    //The mainCollider is used to disable collisions between sibling asteroids as they spawn
    public Collider mainCollider;
    //starting velocities (this is overriden by the Explode function, but good for starting things)
    public float initialVelocity;
    public float initialAngularVelocity;

    //How long to ignore sibling asteroids 
    public float ignoreCollisionTime = 1;

    //List of SubAsteroids to spawn when Explode is called
    public SubAsteroid[] subAsteroids = new SubAsteroid[0];

    //new is required here because Component used to have a built-in one but its deprecated now
    new Rigidbody rigidbody;

    private void Awake()
    {
        //cache our own rigidbody
        rigidbody = GetComponent<Rigidbody>();

        //Generate a unit vector direction, multiply it by somewhere between 0 and initialVelocity
        rigidbody.velocity = Random.onUnitSphere * Random.value * initialVelocity;

        //same deal
        rigidbody.angularVelocity = Random.onUnitSphere * Random.value * initialAngularVelocity;
    }

    public void Damage(int power, Vector3 normal)
    {
        //already dead
        if (hp <= 0)
            return;

        //reduce HP
        hp -= power;

        Debug.Log($"{gameObject.name}[{hp}]");
        //did it blow up?
        if (hp <= 0)
        {
            Explode(normal);
        }
    }

    //Ignore collisions with another collider for a number of seconds
    public void IgnoreCollision(Collider collider, float duration)
    {
        StartCoroutine(IgnoreCollisionRoutine(collider, duration));
    }

    //Coroutine to support IgnoreCollision function
    IEnumerator IgnoreCollisionRoutine(Collider collider, float duration)
    {
        //make sure the collider isn't null to prevent errors
        if (collider != null)
            Physics.IgnoreCollision(GetComponent<Collider>(), collider, true);

        yield return new WaitForSeconds(duration);

        //make sure the collider isn't null to prevent errors
        if (collider != null)
            Physics.IgnoreCollision(GetComponent<Collider>(), collider, false);
    }

    public void Explode(Vector3 normal)
    {

        //Create a new list to store the newly spawned asteroids
        List<Asteroid> roids = new List<Asteroid>();
        foreach (SubAsteroid s in subAsteroids)
        {
            //get the spawn point in world coordinates
            Vector3 position = transform.TransformPoint(s.position);
            //get the velocity in world direction, rotated such that the Velocity's Z- projects away
            //from the incoming Normal
            Vector3 velocity = Quaternion.LookRotation(normal) * s.velocity;
            //get a random rotation because why not
            Quaternion rotation = s.randomRotation ? Quaternion.Euler(Random.Range(-180, 180), Random.Range(-180, 180), Random.Range(-180, 180)) : transform.rotation;
            
            GameObject go = Instantiate(s.prefab, position, rotation);
            Rigidbody rb = go.GetComponent<Rigidbody>();
            Asteroid roid = go.GetComponent<Asteroid>();

            //transfer 75% of our own velocity to the new asteroid
            velocity += rigidbody.velocity * 0.75f;

            //set the new asteroid's velocity
            rb.velocity = velocity;

            //ignore collision between us and 
            //roid.IgnoreCollision(mainCollider, roid.ignoreCollisionTime);

            roids.Add(roid);
        }

        //Loop through each of the new roids and ignore collision between the new pairs
        foreach (Asteroid a in roids)
        {
            foreach (Asteroid b in roids)
            {
                //skip over ourselves
                if (a == b)
                    continue;

                a.IgnoreCollision(b.mainCollider, b.ignoreCollisionTime);
            }
        }

        //Destroy this Asteroid
        Destroy(gameObject);
    }

    //visualize all the spawn positions and points
    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        foreach (var s in subAsteroids)
        {
            //get the spawn point in world coordinates
            Vector3 position = transform.TransformPoint(s.position);
            //get the velocity in world direction
            Vector3 velocity = s.velocity;

            //Draw some useful info to see the results of our SubAsteroid data
            Gizmos.DrawWireSphere(position, 0.15f);
            Gizmos.DrawLine(position, position + velocity);
        }
    }
}
