using UnityEngine;
using System.Collections;

public enum AIMode
{
    Idle,
    Fleeing,
    Pursuing,
    Throwing
}

public class Customer : MonoBehaviour 
{
    public Rigidbody myRigidbody;
    public AIMode aiMode = AIMode.Idle;
    public float turnSpeed = 3.5f;
    public float walkSpeed = 15f;
    public float maxSpeed = 5f;
    public float dignity = 1f;
    public float jumpForce = 5f;
    public string[] retorts;
    public AudioClip[] hitSounds;

    public bool wasKilled;

    public float walkRaw;
    public float turnRaw;

    public float heading;
    private bool canJump;
    private PlayerController playerController;
    static public int customerCount;

    private bool CanJump()
    {
        return Physics.Raycast(new Ray(transform.position + new Vector3(0f, 0.01f, 0f), Vector3.down), 0.021f, Layers.GetMask(Layers.Floor) | Layers.GetMask(Layers.Furnishing));
    }

    private void IdleUpdate()
    {
        walkRaw = 0f;
        turnRaw = 0f;
    }

	private void FleeingUpdate()
    {
        var targetPosition = new Vector3(25f, 0f, 8f);
        var desiredHeading = VectorXZToAngle(targetPosition - transform.position);
        //Debug.Log(desiredHeading);

        walkRaw = 1f;
        turnRaw = Mathf.Sign(desiredHeading - heading);

    }

    private void MovementUpdate()
    {
        if (Mathf.Abs(turnRaw) > 0.0f)
        {
            heading += turnSpeed * turnRaw;
        }

        heading = ClampAngle(heading, -360f, 360f);
        Quaternion xQuaternion = Quaternion.AngleAxis(heading, Vector3.up);
        transform.localRotation = xQuaternion;
    }

    private void Jump()
    {
        myRigidbody.AddForce(new Vector3(0f, jumpForce, 0f), ForceMode.VelocityChange);
    }

    void Awake()
    {
        playerController = FindObjectOfType<PlayerController>();
        customerCount++;
    }

    void Start()
    {
        heading = transform.rotation.eulerAngles.y;
    }

	void Update () 
    {
        switch(aiMode)
        {
            case AIMode.Idle:
                IdleUpdate();
                break;
            case AIMode.Fleeing:
                FleeingUpdate();
                break;
        }
        MovementUpdate();
	
	}

    void FixedUpdate()
    {
        canJump = CanJump();

        if (canJump)
        {
            if (Mathf.Abs(walkRaw) > 0.0f && myRigidbody.velocity.sqrMagnitude < maxSpeed * maxSpeed)
            {
                //Debug.Log(myRigidbody.velocity.sqrMagnitude);
                myRigidbody.AddForce(Quaternion.Euler(0f, heading, 0f) * ((Vector3.forward * walkRaw) * walkSpeed), ForceMode.Acceleration);
            }

            //if (Mathf.Abs(strafeRaw) > 0f && myRigidbody.velocity.sqrMagnitude < maxSpeed * maxSpeed)
            //{
            //    myRigidbody.AddForce(Quaternion.Euler(0f, heading, 0f) * ((Vector3.right * strafeRaw) * walkSpeed), ForceMode.Acceleration);
            //}
        }
    }

    void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.layer == Layers.Furnishing)
        { 
            if(canJump)
            {
                Jump();
            }
        }
    }

    void FoundExit()
    {
        Destroy(gameObject);
    }

    void Splatted()
    {
        playerController.message = retorts[Random.Range(0, retorts.Length)];

        dignity -= 1f;

        if (dignity <= 0f && !wasKilled)
        {
            aiMode = AIMode.Fleeing;
            gameObject.SetLayerRecursively(Layers.Fleeing);
            wasKilled = true;
            playerController.AwardKill(0);
        }
    }

    private float VectorXZToAngle(Vector3 vector)
    {
        return (float)Mathf.Atan2(vector.x, vector.z) / Mathf.PI * 180.0f;
    }

    private static float ClampAngle(float angle, float min, float max)
    {
        if (angle < -360F)
            angle += 360F;
        if (angle > 360F)
            angle -= 360F;
        return Mathf.Clamp(angle, min, max);
    }

}
