using UnityEngine;
using System.Collections;
using System.Linq;

public class BaseMans : MonoBehaviour {

    protected Rigidbody2D myBody;

    protected float fJumpImpetus;
    public float JumpForce = 400f;

    public GameObject prefab_bloodImpact;

    public bool bFacingRight = true;

    protected Transform groundCollisionCircle;
    public float fGroundCheckRadius;
    [SerializeField]
    protected LayerMask m_WhatIsGround;                  // A mask determining what is ground to the character

    protected SpriteRenderer m_SpriteRenderer;
    public Sprite IdleSprite;
    public Sprite CrouchingSprite;
    public Sprite DashingSprite;
    protected BoxCollider2D m_BoxCollider2D;

    //shootings
    public GameObject projectile_BasicShot;

    public Stance currentStance;

    public TextMesh speechBubble;
    private float fSpeechTimer;

    //resets to 0 when landing, 1 means jumping, 2 means double jump, etc.
    protected int iJumpCounter;

    public float StartingHealth;
    public float fHealth;

    public AudioSource myAudio;

    public Vector2 ProjectileOriginOffset;

	// Use this for initialization
    protected virtual void Start()
    {
        myAudio = gameObject.AddComponent<AudioSource>();

        myBody = GetComponent<Rigidbody2D>();
        groundCollisionCircle = transform.Find("GroundCheck");
        m_SpriteRenderer = GetComponent<SpriteRenderer>();
        m_BoxCollider2D = GetComponent<BoxCollider2D>();

        if( fHealth <= 0.0f)
            fHealth = StartingHealth;

        speechBubble = GetComponentInChildren<TextMesh>();
    }
	
	// Update is called once per frame
    protected virtual void Update()
    {
        if (speechBubble != null && fSpeechTimer > 0.0f)
        {
            fSpeechTimer -= Time.smoothDeltaTime;
            if (fSpeechTimer <= 0.0f)
                speechBubble.text = "";
        }

        myAudio.pitch = Random.Range(0.9f, 1.1f);
	}

    public virtual void FixedUpdate() { }

    protected virtual bool UpdateGrounded()
    {
        bool bLanded = false;
        Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCollisionCircle.position, fGroundCheckRadius, m_WhatIsGround);
        for (int i = 0; i < colliders.Length; i++)
        {
            if (colliders[i].gameObject != gameObject)
            {
                bLanded = true;
                iJumpCounter = 0;
            }
        }

        return bLanded;
    }

    protected virtual void SetState_Idle()
    {
        m_SpriteRenderer.sprite = IdleSprite;
        m_BoxCollider2D.offset = new Vector2(0, 0.07f);
        m_BoxCollider2D.size = new Vector2(1, 2);
        currentStance = Stance.standing;
    }

    protected virtual void SetState_Crouch()
    {
        m_SpriteRenderer.sprite = CrouchingSprite;
        m_BoxCollider2D.offset = new Vector2(0, -0.3f);
        m_BoxCollider2D.size = new Vector2(1, 1.1f);
        currentStance = Stance.crouching;

    }

    public virtual void GetShotOriginAndDirection(ref Vector3 vOrigin, ref Vector2 vDirection)
    {
        vOrigin = transform.position;
        if (currentStance == Stance.standing)
            vOrigin.y += 0.25f;
        else if (currentStance == Stance.crouching)
            vOrigin.y -= 0.25f;

        vOrigin += (Vector3)ProjectileOriginOffset;

        vDirection = new Vector2(bFacingRight ? 1 : -1, 0);
    }

    public virtual void TakeDamage( float fDamageAmount )
    {
        GameObject newBloods = GameObject.Instantiate(prefab_bloodImpact);
        newBloods.transform.position = transform.position;
        newBloods.transform.parent = transform;
        
        Destroy(newBloods,8.0f);

        fHealth -= fDamageAmount;
        if (fHealth <= 0)
            StartDying();
    }

    public virtual void StartDying()
    {
        
    }

    public virtual void FireProjectile()
    {
        GameObject newShot = GameObject.Instantiate(projectile_BasicShot);

        Vector3 vShotOrigin = new Vector3();
        Vector2 vShotDir = new Vector2();

        GetShotOriginAndDirection(ref vShotOrigin, ref vShotDir);
        newShot.transform.position = vShotOrigin;
        Projectile proj = newShot.GetComponent<Projectile>();
        proj.Launch(vShotDir);

    }

    public virtual void OnCollisionEnter2D(Collision2D coll)
    {
    }

    public virtual bool EvaluateImpactWithProjectile(Projectile projHittingMe)
    {
        myBody.AddForce(projHittingMe.GetComponent<Rigidbody2D>().velocity / 12);
        myBody.AddForce(Vector2.up * 100.0f);
        TakeDamage(projHittingMe.DamageToDeal);

        return true;
    }

    public void SaySomething(string text, float fDuration)
    {
        if (speechBubble == null)
            return;

        fSpeechTimer = fDuration;
        speechBubble.text = text;
    }

    public void ToggleFacing()
    {
        Vector3 vScale = transform.localScale;
        vScale.x *= -1;
        transform.localScale = vScale;

        if (speechBubble != null)
        {
            speechBubble.transform.localScale = vScale;
        }
    }
}
