using UnityEngine;
using System.Collections;

public class AIMove_Base : MonoBehaviour
{
    protected Vector3 vMoveInertia;

    public float MaxMoveSpeed = 10.0f;
    public float Acceleration = 8.0f;
    public float SpeedDecay = 2.0f;

    public virtual bool AllowTurningToFire()
    {
        return true;
    }

    public virtual void UpdateMovement(PlayerController attackTarget)
    {
        
    }

    protected virtual void FaceObject(PlayerController faceMe)
    {
        Vector3 vFaceDir = faceMe.transform.position - transform.position;
        vFaceDir.Normalize();

        Vector2 v2Facing = vFaceDir;

        float fDesiredZ = Vector2.Angle(Vector2.up, v2Facing);

        if (v2Facing.x > 0)
            fDesiredZ = 360.0f - fDesiredZ;

        transform.rotation = Quaternion.Euler(0, 0, fDesiredZ);


    }

    public void AddImpulse(Vector3 vNewImpulse)
    {
        vMoveInertia += vNewImpulse;
    }

    protected virtual void ApplyInertiaTowardsGoalPosition(Vector3 vGoalPosition)
    {
        Vector3 vToGoal = vGoalPosition - transform.position;
        vToGoal.z = 0;
        vToGoal.Normalize();

        vMoveInertia += vToGoal * (Acceleration) * Time.deltaTime;

        //cap inertia at max speed
        float fInertiaMag = vMoveInertia.magnitude;
        if (fInertiaMag > MaxMoveSpeed)
        {
            vMoveInertia.x = (vMoveInertia.x / fInertiaMag) * MaxMoveSpeed;
            vMoveInertia.y = (vMoveInertia.y / fInertiaMag) * MaxMoveSpeed;
        }
    }

    protected void DecayInertia()
    {
        //decay jet speed
        if (vMoveInertia.x > 0)
            vMoveInertia.x -= SpeedDecay * Time.deltaTime;
        if (vMoveInertia.x < 0)
            vMoveInertia.x += SpeedDecay * Time.deltaTime;
        if (vMoveInertia.y > 0)
            vMoveInertia.y -= SpeedDecay * Time.deltaTime;
        if (vMoveInertia.y < 0)
            vMoveInertia.y += SpeedDecay * Time.deltaTime;

        if (Mathf.Abs(vMoveInertia.sqrMagnitude) < 0.01f * 0.01f)
            vMoveInertia = Vector3.zero;
    }
}

public class AIMove_Swarm : AIMove_Base
{
    [Header("Swarm Behavior")] 
    public Vector2 MinMaxTime_NewGoal;
    public Vector2 MinMaxRange_Target = new Vector2(6.0f,10.0f);
    public float DistanceToBeginChase = 14.0f;

    private float fTimeTillChangeGoal;
    private Vector3 vCurrentGoal;


	// Use this for initialization
	void Start () 
    {
	
	}
	
	// Update is called once per frame
	void Update () 
    {
	
	}

    void PickGoalNearTarget(GameObject target)
    {
        Vector3 vPos = target.transform.position;

        Vector3 vDir = Random.onUnitSphere;
        vDir.z = 0;
        vDir.Normalize();

        vCurrentGoal = vPos + vDir * (Random.Range(6.0f, 10.0f));
        fTimeTillChangeGoal = Random.Range(MinMaxTime_NewGoal.x, MinMaxTime_NewGoal.y);
    }

    public override void UpdateMovement(PlayerController attackTarget)
    {
        //look at the target
        FaceObject(attackTarget);

        //pick a goal position if we don't have one or if time is up.
        if( fTimeTillChangeGoal <= 0.0f || (vCurrentGoal - attackTarget.transform.position).sqrMagnitude > DistanceToBeginChase * DistanceToBeginChase  )
            PickGoalNearTarget(attackTarget.gameObject);

        fTimeTillChangeGoal -= Time.deltaTime;

        //if we have a goal position, move towards it.
        ApplyInertiaTowardsGoalPosition(vCurrentGoal);

        DecayInertia();

        //move
        transform.position += vMoveInertia*Time.deltaTime;
    }
}
