using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour {

    private Transform playerPos;
    public float moveSpeed = 0f;
    public float range = 0f;
    public float health = 100f;
    public float stronkHealth = 150f;
    public float stronkScale = 1.5f;
    public float bigBossHealth = 200f;
    public float bigBossScale = 2f;
    
    enum EnemyState { spawning, hunting, shooting, dying };
    private EnemyState enemyState = EnemyState.spawning;

    public GameObject projectile;

    private NavMeshAgent navMeshAgent;

    public float shootTime = 2f;
    public int shootBursts = 4;

    public Transform projectileSpawn;

    //Vars for calculating rotation
    private Vector3 newDir;
    private Vector3 oldDir;

    public float leadingAngleMax = 5f;

	// Use this for initialization
	void Start () {
        playerPos = GameObject.FindWithTag("Player").transform;
        navMeshAgent = GetComponent<NavMeshAgent>();
	}
	
	// Update is called once per frame
	void Update () {
        if (enemyState == EnemyState.hunting)
        {
            navMeshAgent.SetDestination(playerPos.position);
            if (CheckLoS())
            {
                enemyState = EnemyState.shooting;
                navMeshAgent.Stop();
                StartCoroutine(Shoot());
            }
        }
        if(enemyState == EnemyState.shooting)
        {
            CalculateRotation();
        }
	}

    public void OnSpawn(string type)
    {
        // start anims here
        enemyState = EnemyState.spawning;
        if (type == "stronk")
        {
            transform.localScale = new Vector3(stronkScale, stronkScale, stronkScale);
            health = stronkHealth;
        }
        else if(type == "bigBoss")
        {
            transform.localScale = new Vector3(bigBossScale, bigBossScale, bigBossScale);
            health = bigBossHealth;
        }
        StartCoroutine(Spawn());
    }

    IEnumerator Spawn()
    {
        Debug.Log("SPAWNING");
        yield return new WaitForSeconds(1.0f);
        Debug.Log("HUNTING");
        enemyState = EnemyState.hunting;
    }

    /**
    CHECKLoS
    Check if enemy has line of sight on player.
    **/
    private bool CheckLoS()
    {
        Vector3 heading = playerPos.position - transform.position;
        float distance = heading.magnitude;
        if(distance > range)
        {
            return false;
        }
        Vector3 direction = heading / distance;
        RaycastHit rayHit;
        if(Physics.Raycast(transform.position, direction, out rayHit, distance))
        {
            if (!rayHit.transform.CompareTag("Player"))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        return false;
    }

    IEnumerator Shoot()
    {
        bool hasLos = true;
        while (hasLos)
        {
            for (int i = 0; i < shootBursts; i++)
            {
                Instantiate(projectile, projectileSpawn.position, projectileSpawn.rotation);
                yield return new WaitForSeconds(shootTime / shootBursts);
            }
            hasLos = CheckLoS();
            Debug.Log(hasLos);
        }
        enemyState = EnemyState.hunting;
        newDir = Quaternion.LookRotation(GetDirection()).eulerAngles;
        oldDir = newDir;
        navMeshAgent.Resume();
    }

    void CalculateRotation()
    {
        /**newDir = GetDirection();
        Vector3 dir = new Vector3(0, 0, newDir.z);
        Quaternion dirQ = Quaternion.LookRotation(newDir);
        Debug.Log(dirQ.eulerAngles);
        transform.eulerAngles = new Vector3(0, dirQ.eulerAngles.y, 0);
        projectileSpawn.rotation = dirQ;
        transform.eulerAngles = dir;**/

        newDir = Quaternion.LookRotation(GetDirection()).eulerAngles;
        float angle = newDir.y - oldDir.y;
        if(angle < -180)
        {
            angle += 360;
        } else if(angle > 180)
        {
            angle -= 360;
        }
        if (angle != 0)
        {
            angle /= Mathf.Abs(angle);
        }
        newDir.y += Random.Range(0f, leadingAngleMax) * angle;
        //Debug.Log(angle);
        transform.eulerAngles = new Vector3(0,newDir.y,0);

        oldDir = newDir;
    }

    Vector3 GetDirection()
    {
        Vector3 heading = playerPos.position - transform.position;
        float distance = heading.magnitude;
        Vector3 dir = heading / distance;
        return dir;
    }

    public void TakeDamage(float damage)
    {
        health -= damage;
        if(health <= 0)
        {
            Die();
        }
    }

    void Die()
    {
        enemyState = EnemyState.dying;
        Destroy(gameObject, 5.0f);
    }
}