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

public class EnemyColliderManager : ColliderManager
{
    public GameObject shipCore;
    public GameObject shipModel;
    public float bounceForce;
    public float coreSpawnDelayTime;

    public ParticleSystem effectA;
    public ParticleSystem effectB;

    public AudioClip shipDeathSFX;
    public AudioClip coreSpawnedSFX;

    private bool _enemyDestroyed = false;

    // The position the enemy died
    private Vector3 _deathPos;
    private float _deathHeight;

    /// <summary>
    /// Trigger the enemy death without a collision, this is mostly for the debug menu and testing but could be called in a case where you need it to die.
    /// </summary>
    public override void TriggerDeath()
    {
        DestoryEnemy();
        base.TriggerDeath();
    }

    /// <summary>
    /// Process the Enemy collision.
    /// </summary>
    /// <param name="direction">Direction the collision happened, typically checking if hit from above or below.</param>
    /// <param name="collision">Collision object holding the details on the collided object.</param>
    /// <param name="wasChild">Was the hit collider a child of this game object.</param>
    public override void ProcessCollision(CollisionDirection direction, Collision collision, bool wasChild)
    {
        GameObject collisionGO;
        if (wasChild)
        {
            collisionGO = collision.transform.parent.gameObject;
        }
        else
        {
            collisionGO = collision.gameObject;
        }

        switch (direction)
        {
            // We were hit from the top
            case CollisionDirection.Top:                
                switch (collisionGO.tag)
                {
                    case "Player":
                        // We were killed by the player above
                        DestoryEnemy();
                        break;
                    case "Enemy":
                        // Bounce other enemies back
                        BounceAway(collision.contacts[0].normal);
                        break;
                    case "Core":
                    case "Dead":
                        // Now handled by the layer NoCollide
                        // Ignore the physics between this and the core or dead players
                        //Physics.IgnoreCollision(collision.collider, gameObject.GetComponent<Collider>());
                        break;
                }
                break;
            // We were hit from the bottom
            case CollisionDirection.Bottom:                
                switch (collisionGO.tag)
                {
                    case "Player":
                        // Kill the player because we were on top
                        PlayerColliderManager playerColliderManager = collisionGO.GetComponent<PlayerColliderManager>();
                        if (playerColliderManager)
                        {
                            playerColliderManager.PlayerHit();
                        }
                        break;
                    case "Enemy":
                        // Bounce the enemy away
                        EnemyColliderManager enemyColliderManager = collisionGO.GetComponent<EnemyColliderManager>();
                        if (enemyColliderManager)
                        {
                            enemyColliderManager.BounceAway(-collision.contacts[0].normal);
                        }                        
                        break;
                    case "Core":
                    case "Dead":
                        // Now handled by the layer NoCollide
                        //Physics.IgnoreCollision(collision.collider, gameObject.GetComponent<Collider>());
                        break;
                }
                break;
            // Hits coming from any direction
            default:
                switch (collisionGO.tag)
                {
                    case "Mine":
                        MineColliderManager mineColliderManager = collisionGO.GetComponent<MineColliderManager>();
                        if (mineColliderManager)
                        {
                            mineColliderManager.HitMine();
                        }
                        break;
                    case "Asteroid":                       
                        AsteroidColliderManager asteroidColliderManager = collisionGO.GetComponent<AsteroidColliderManager>();
                        if (asteroidColliderManager)
                        {
                            asteroidColliderManager.BounceAway(gameObject, -collision.contacts[0].normal);
                        }
                        break;
                    case "Enemy":
                        EnemyColliderManager enemyColliderManager = collisionGO.GetComponent<EnemyColliderManager>();
                        if (enemyColliderManager)
                        {
                            enemyColliderManager.BounceAway(-collision.contacts[0].normal);
                        }
                        break;
                    case "Core":
                    case "Dead":
                        // Handled by the layers now
                        //Physics.IgnoreCollision(collision.collider, gameObject.GetComponent<Collider>());
                        break;
                }
                break;
        }        
    }

    /// <summary>
    /// Bounce away from the given position.
    /// </summary>
    /// <param name="collisionPos">Vector position the collision happened at.</param>
    public void BounceAway(Vector3 collisionPos)
    {        
        gameObject.GetComponent<Rigidbody>().AddForce(collisionPos * bounceForce, ForceMode.Impulse);
    }

    /// <summary>
    /// Delayed core spawning method, this allows the ship to "die" and play its animation and then for the spawn to appear.
    /// </summary>
    /// <returns></returns>
    public IEnumerator DelayedCoreSpawn()
    {
        bool timeWaited = false;
        bool waitEnded = false;

        while (!waitEnded)
        {
            if (timeWaited)
            {
                // Spawn a new core at the death location
                GameObject newCore = Instantiate(shipCore);
                CoreHoverMovement coreMovement = newCore.GetComponent<CoreHoverMovement>();
                if (coreMovement)
                {
                    coreMovement.startPositionVector = _deathPos;
                    coreMovement.startHeight = _deathHeight;
                }

                newCore.SetActive(true);
                AudioSource newCoreAS = newCore.GetComponent<AudioSource>();
                newCoreAS.PlayOneShot(coreSpawnedSFX);

                StopCoroutine("DelayedCoreSpawn");
                ObjectSpawning attachedShared = gameObject.GetComponent<EnemyObjectShared>().Spawner;
                if (attachedShared)
                {
                    // Reduce the spawner objects count
                    attachedShared.ReduceSpawnedCount();
                }
                Destroy(gameObject);
                waitEnded = true;
            }
            else
            {
                timeWaited = true;
            }
            yield return new WaitForSeconds(coreSpawnDelayTime);
        }
    }

    /// <summary>
    /// Method for destroying the enemy game object, it starts a coroutine to allow for an animation to be played.
    /// </summary>
    public void DestoryEnemy()
    {
        if (!_enemyDestroyed)
        {
            // Store the position of death since the AI still moves after the models been deactivated.
            _deathPos = transform.position;
            _deathHeight = gameObject.GetComponent<HoverMovement>().GetCurrentHeight();
            if (_attachedAudioSource)
            {
                _attachedAudioSource.PlayOneShot(shipDeathSFX);
            }

            // Start the delayed core spawn coroutine, this can probs be replaced once the death animations are in to spawn once that has ended.
            StartCoroutine("DelayedCoreSpawn");
            ParticleSystem boomboom = Instantiate(effectA);
            ParticleSystem boomboom2 = Instantiate(effectB);
            boomboom.transform.position = _deathPos;
            boomboom2.transform.position = _deathPos;
            shipModel.SetActive(false);
            gameObject.tag = "Dead";
            gameObject.layer = LayerMask.NameToLayer("NoCollide");
            _enemyDestroyed = true;
        }
    }
}
