using UnityEngine;
using System.Collections;

public class GlassBall : BallBase
{
    public AudioClip breakSound;

    private int health = 3;

    private bool isBroken = false;

    private float damageTimer = 0.0f;

    private float damageCooldown = 0.5f;

    private SpriteRenderer spriteRenderer;

    private Bounds boardBounds;

    private Collider2D selfCollider;

    private bool hasBoardBounds = false;

    private float magnetBounceDuration = 0.35f;

    private float magnetCenterLeeway = 0.12f;

    private MagnetBounceAxisState xMagnetBounceState;

    private MagnetBounceAxisState yMagnetBounceState;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        audioSource = GetComponent<AudioSource>();
        animator = GetComponent<Animator>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        selfCollider = GetComponent<Collider2D>();
        speed = new Vector2(Random.Range(-0.05f, 0.05f), Random.Range(-0.05f, 0.05f));

        hasBoardBounds = TryCacheGameBoardBounds(out boardBounds);

        audioSource.PlayOneShot(spawnSound);
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if (damageTimer > 0.0f)
        {
            damageTimer -= Time.fixedDeltaTime;
        }

        AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);

        if (stateInfo.IsName("GlassBallMove1") ||
            stateInfo.IsName("GlassBallMove2") ||
            stateInfo.IsName("GlassBallMove3"))
        {
            transform.Translate(speed);

            if (affectedByMagnet && hasBoardBounds)
            {
                Vector3 currentPosition = transform.position;

                currentPosition.x = ApplyMagnetBounceAxis(
                    currentPosition.x,
                    boardBounds.min.x,
                    boardBounds.max.x,
                    magnetActiveLeftRight,
                    ref xMagnetBounceState,
                    selfCollider != null ? selfCollider.bounds.extents.x : 0.0f,
                    magnetBounceDuration,
                    magnetCenterLeeway
                );

                currentPosition.y = ApplyMagnetBounceAxis(
                    currentPosition.y,
                    boardBounds.min.y,
                    boardBounds.max.y,
                    magnetActiveTopBottom,
                    ref yMagnetBounceState,
                    selfCollider != null ? selfCollider.bounds.extents.y : 0.0f,
                    magnetBounceDuration,
                    magnetCenterLeeway
                );

                transform.position = currentPosition;
            }
        }
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Wall") || 
            collision.gameObject.CompareTag("GlassBall"))
        {
            ContactPoint2D contact = collision.GetContact(0);
            speed = Vector2.Reflect(speed, contact.normal);

            // Glass balls take damage when colliding with other GlassBalls
            if (collision.gameObject.CompareTag("GlassBall"))
            {
                Damage();
            }
        }
        else
        {
            Physics2D.IgnoreCollision(collision.collider, GetComponent<Collider2D>(), true);
        }
    }

    private void Damage()
    {
        if (isBroken || damageTimer > 0.0f)
        {
            return;
        }

        health--;
        damageTimer = damageCooldown;

        if (health < 0)
        {
            health = 0;
        }

        animator.SetInteger("health", health);

        if (health > 0)
        {
            audioSource.PlayOneShot(hitSound);
        }
        else
        {
            audioSource.PlayOneShot(breakSound);
        }
    }

    public void Break()
    {
        if (isBroken)
        {
            return;
        }

        isBroken = true;
        spriteRenderer.enabled = false;
        var collider = GetComponent<Collider2D>();

        if (collider != null)
        {
            collider.enabled = false;
        }

        StartCoroutine(BreakCoroutine());
    }

    private IEnumerator BreakCoroutine()
    {
        yield return new WaitForSeconds(0.6f);

        Destroy(gameObject);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if(other.gameObject.CompareTag("Bar"))
        {
            Damage();

            // Destroy all bar segments when the ball hits a bar.
            var barSegments = GameObject.FindGameObjectsWithTag("Bar");

            foreach (var barSegment in barSegments)
            {
                Destroy(barSegment);
            }

            // Notify the player that the bar has been hit.
            var player = GameObject.FindGameObjectWithTag("Player");

            if (player != null)
            {
                player.GetComponent<Player>().OnBarHit();
            }
        }
    }
}
