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

public class PlayerColliderManager : ColliderManager
{
    // After death immunity variables
    public float immunityTimer;
    private float _immunityCurrentTick;    
    private bool _dying = false;

    private static PlayerColliderManager _instance;

    public static PlayerColliderManager Instance
    {
        get
        {
            return _instance;
        }
        set
        { 
            Instance = value;
        }
    }

    public float flashTick;
    private float _currentFlashTick;
    private bool _flashed;
    
    public GameObject mainMeshGO;
    private MeshRenderer _currentMeshRenderer;
    public Color immunityColorFlash;
    private Color _originalColor;

    public AudioClip shipDeathSFX;
    public AudioClip playerImmunitySFX;

    private PlayerHoverMovement _currentMovement;    

    /// <summary>
    /// Method to handle awake tasks for the player collider.
    /// </summary>
    public override void DoAwakeTasks()
    {
        _currentMovement = gameObject.GetComponent<PlayerHoverMovement>();
        _currentMeshRenderer = mainMeshGO.GetComponent<MeshRenderer>();
        _originalColor = _currentMeshRenderer.material.color;
        base.DoAwakeTasks();
    }

    public void SetImmune(float length)
    {
        Debug.Log("I am immune");
        _immunityCurrentTick = length;
    }

    /// <summary>
    /// Method for firing the core pick up method.
    /// </summary>
    /// <param name="coreGO">Core game object.</param>
    private void PickUpCore(GameObject coreGO)
    {
        CoreColliderManager coreColliderManager = coreGO.GetComponent<CoreColliderManager>();
        if (coreColliderManager)
        {
            coreColliderManager.PickupCore();
        }
    }

    /// <summary>
    /// Method for killing the player without a collision, used for the debug console mainly
    /// </summary>
    public override void TriggerDeath()
    {
        PlayerHit(true);
        base.TriggerDeath();
    }

    /// <summary>
    /// Process the Player 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.gameObject.transform.parent.gameObject;
        }
        else
        {
            collisionGO = collision.gameObject;
        }

        switch(direction)
        {
            case CollisionDirection.Top:                
                switch(collisionGO.tag)
                {
                    case "Mine":
                        MineColliderManager mineColliderManager = collisionGO.GetComponent<MineColliderManager>();
                        if (mineColliderManager)
                        {
                            mineColliderManager.HitMine();
                        }
                        break;
                    case "Enemy":
                        // Enemy hit players top.
                        PlayerHit();
                        break;
                    case "Core":
                        // Collected a core.
                        PickUpCore(collisionGO);
                        break;
                    case "Dead":
                        // Now handled by the layer NoCollide
                        // Ignore dead enemies collision
                        //Physics.IgnoreCollision(collision.collider, gameObject.GetComponent<Collider>());
                        break;
                }
                break;
            case CollisionDirection.Bottom:                
                switch (collisionGO.tag)
                {
                    case "Mine":
                        MineColliderManager mineColliderManager = collisionGO.GetComponent<MineColliderManager>();
                        if (mineColliderManager)
                        {
                            mineColliderManager.HitMine();
                        }
                        break;
                    case "Enemy":
                        // Kill the collided enemy
                        EnemyColliderManager enemyColliderManager = collisionGO.GetComponent<EnemyColliderManager>();
                        if (enemyColliderManager)
                        {
                            enemyColliderManager.DestoryEnemy();
                        }
                        break;
                    case "Core":
                        // Pick up core
                        PickUpCore(collisionGO);
                        break;
                    case "Dead":
                        // Now handled by the layer NoCollide
                        //Physics.IgnoreCollision(collision.collider, gameObject.GetComponent<Collider>());
                        break;
                }
                break;
            default:
                switch (collisionGO.tag)
                {
                    case "Mine":
                        MineColliderManager mineColliderManager = collisionGO.GetComponent<MineColliderManager>();
                        if (mineColliderManager)
                        {
                            mineColliderManager.HitMine();
                        }
                        break;
                    case "Asteroid":
                        // Player hit an asteroid from any direction, get bounced
                        AsteroidColliderManager asteroidColliderManager = collisionGO.GetComponent<AsteroidColliderManager>();
                        if (asteroidColliderManager)
                        {
                            asteroidColliderManager.BounceAway(gameObject, -collision.contacts[0].normal);
                        }
                        break;
                    case "Core":
                        PickUpCore(collisionGO);
                        break;
                }
                break;
        }        
    }

    /// <summary>
    /// Method for dealing with the player being hit and losing a life
    /// </summary>
    /// <param name="blackHoleDeath">If the player was hit by the black hole, this ignores immunity.</param>
    public void PlayerHit(bool blackHoleDeath = false)
    {
        if (_dying || GameManager.Instance.godMode)
        {
            return;
        }

        // Check if we are currently in immunity.
        if (_immunityCurrentTick == 0.0f || blackHoleDeath)
        {
            if (_attachedAudioSource)
            {
                _attachedAudioSource.PlayOneShot(shipDeathSFX);
            }
            // Remove a life from the game manager
            _dying = true;
            GameManager.Instance.LostLife();
            _currentMovement.ForceStartLocationReset();
            
            //Check if its game over (moved to the game manager)
            if (GameManager.Instance.isGameOver)
            {
                //GameManager.Instance.DoGameOver();
                //gameObject.SetActive(false);
            }
            else
            {
                SetImmune(immunityTimer);
                //_immunityCurrentTick = immunityTimer;
                _flashed = false;
            }
        }        
    }

    /// <summary>
    /// Method for dealing with the immunity flashing.
    /// </summary>
    /// <param name="forceReset">Force the flash to end.</param>
    private void FlashToggle(bool forceReset = false)
    {
        if (_flashed || forceReset)
        {
            _currentMeshRenderer.material.color = _originalColor;
            _flashed = false;
        }
        else
        {
            _currentMeshRenderer.material.color = immunityColorFlash;
            if (_attachedAudioSource)
            {
                _attachedAudioSource.PlayOneShot(playerImmunitySFX);
            }
            _flashed = true;
        }
    }

    public void Update()
    {
        // If we are immune flash the player to show it.
        if (_immunityCurrentTick > 0.0f)
        {
            if (_currentFlashTick >= flashTick)
            {
                FlashToggle();
                _currentFlashTick = 0.0f;
            }
            else
            {
                _currentFlashTick += Time.deltaTime;
            }
            
            _immunityCurrentTick -= Time.deltaTime;
            if (_immunityCurrentTick < 0.0f)
            {
                _immunityCurrentTick = 0.0f;
            }
        }
        else
        {            
            _immunityCurrentTick = 0.0f;
            _dying = false;
            FlashToggle(true);
            _flashed = false;
        }
    }
}
