using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class Player : MonoBehaviour {

    public static Player instance;
    [SerializeField] private Text healthTxt;
    [SerializeField] private Text currentCoinText;

    private Rigidbody2D rb;
    private Animator animator;

    [Header("Player Movement")]
    [SerializeField] private float acceleration = .1f;
    [SerializeField] private float jumpHeight = 7f;
    public float speed = 5f;

    private bool isGround;

    [Header("Shoot")]
    public Transform shootPoint;
    public float distance = 5f;
    public LayerMask whatIsEnemy;
    public LineRenderer lr;

    [SerializeField] private GameObject explosionEffectPrefab;
    [SerializeField] private Transform explosionSpawnPoint;
    public int maxHealth = 5;

    private int currentCoin;
    [SerializeField] private GameObject gameOverUI;

    private void Awake()
    {
        if (instance == null) {
            instance = this;
        }
        else {
            Destroy(this);
        }
    }

    void Start() {

        currentCoin = 0;

        isGround = true;
        lr.enabled = false;
        rb = this.GetComponent<Rigidbody2D>();
        animator = this.GetComponent<Animator>();
    }

    void Update() {

        healthTxt.text = maxHealth.ToString();
        if (maxHealth <= 0) {
            Die();
        }

        if (transform.position.y <= -2f) {
            Die();
        }

        speed += acceleration * Time.deltaTime;
        transform.Translate(new Vector2(1f, 0f) * Time.deltaTime * speed);
        
        if (Input.GetKey(KeyCode.Space) && isGround == true) {
            Jump();
            isGround = false;
            animator.SetBool("Jump", true);
            FindAnyObjectByType<SoundManager>().PlayJumpSound();
        }

        if (Input.GetMouseButtonDown(0)) {
            StartCoroutine(Shoot());
        }
    }

    IEnumerator Shoot() {
        lr.enabled = true;
        lr.SetPosition(0, shootPoint.position);
        RaycastHit2D hitInfo = Physics2D.Raycast(shootPoint.position, Vector2.right, distance, whatIsEnemy);
        if (hitInfo) {
            if (hitInfo.transform.GetComponent<Enemy2>() != null) {
                lr.SetPosition(1, hitInfo.point);
                Enemy2.instance.TakeDamage();
            }
            else if (hitInfo.transform.GetComponent<Enemy>() != null) {
                lr.SetPosition(1, hitInfo.point);
                Enemy.instance.TakeDamage(1);
            }
        }
        else {
            lr.SetPosition(1, shootPoint.position + transform.right * distance);
        }
        yield return new WaitForSeconds(.12f);
        lr.enabled = false;
    }

    void Jump() {
        rb.AddForce(new Vector2(0f, jumpHeight), ForceMode2D.Impulse);
    }

    public void TakeDamage(int damage) {
        if (maxHealth <= 0) {
            return;
        }
        maxHealth -= damage;
        CameraShake.instance.Shake();
    }

    private void OnCollisionEnter2D(Collision2D collision) {
        if (collision.gameObject.tag == "Ground") {
            isGround = true;
            animator.SetBool("Jump", false);
        }

        if (collision.gameObject.tag == "Trap") {
            Die();
        }
    }

    private void OnTriggerEnter2D(Collider2D collision) {
        if (collision.gameObject.tag == "Box") {
            GroundSpawner.instance.SpawnGround();
        }

        if (collision.gameObject.tag == "Heart") {
            maxHealth += 1;
            collision.gameObject.transform.GetChild(0).gameObject.GetComponent<Animator>().SetTrigger("Collide");
            Destroy(collision.gameObject, 1f);
        }

        if (collision.gameObject.tag == "Coin") {
            currentCoin++;
            currentCoinText.text = currentCoin.ToString();
            collision.gameObject.transform.GetChild(0).GetComponent<Animator>().SetTrigger("Collide");
            Destroy(collision.gameObject, 1f);
        }
    }

    void Die() {
        Debug.Log(this.gameObject.name + " Died");
        gameOverUI.SetActive(true);
        CameraShake.instance.Shake();
        GameManager.instance.isGameActive = false;
        GameObject tempEffect = Instantiate(explosionEffectPrefab, explosionSpawnPoint.position, Quaternion.identity);
        Destroy(tempEffect, .9f);
        FindAnyObjectByType<SoundManager>().PlayExplosionSound();
        Destroy(this.gameObject);
    }
}
