﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class AgentController : MonoBehaviour
{
    [Range(0.1f,20f)]
    public float predatorSpeed = 3f;
    [Range(0.1f,20f)]
    public float preySpeed = 5f;

    public float preyRadius = 5f;
    public float preyFleeRadius = 10f;
    public float predatorRadius = 10f;

    // public float roamSpeed = 4f;
    // public bool predatorRoam = false;
    // public bool preyRoam = false;
    

    GameObject[] preds;
    GameObject[] preys;

    Vector3 predatorRoamTarget;
    Vector3 preyRoamTarget;
    // NavMeshAgent agent;
    // Start is called before the first frame update
    void Start()
    {
        // agent = GetComponent<NavMeshAgent>();

        // get all preds and get all preys
        preds = GameObject.FindGameObjectsWithTag("predator");
        preys = GameObject.FindGameObjectsWithTag("prey");

        // set the speeds
        foreach (var pred in preds) {
            NavMeshAgent agent = pred.GetComponent<NavMeshAgent>();
            agent.speed = predatorSpeed;
            // agent.SetDestination(predatorRoamTarget);
        }
            
        foreach (var prey in preys)
            prey.GetComponent<NavMeshAgent>().speed = preySpeed;


        StartCoroutine(UpdatePrey());
        StartCoroutine(UpdatePredator());

    }

    IEnumerator UpdatePrey(){
        while(true){
            // for prey check if there are preds close to you
            foreach(var prey in preys) {
                Collider[] colliders = Physics.OverlapSphere(prey.transform.position, preyRadius);

                // don't do anything unless something is nearby
                if(colliders.Length > 0) {
                    // figure out where all the predators are coming from and go the other way
                    Vector3 fleeDir = Vector3.zero;
                    foreach(var collider in colliders) {
                        if(collider.tag == "predator")
                            fleeDir += (prey.transform.position - collider.gameObject.transform.position);
                    }

                    if(!fleeDir.Equals(Vector3.zero)){
                        Vector3 fleeGoal = prey.transform.position + fleeDir.normalized * preyFleeRadius;
                    
                        // only set the new destination if the path is valid
                        NavMeshPath path = new NavMeshPath();
                        NavMeshAgent agent = prey.GetComponent<NavMeshAgent>();
                        agent.speed = preySpeed;
                        agent.CalculatePath(fleeGoal, path);

                        if(path.status != NavMeshPathStatus.PathInvalid) {
                            agent.SetDestination(path.corners[path.corners.Length - 1]);
                        } else {
                            // assume this means I'm at the border, force a turn around
                            fleeGoal = prey.transform.position - fleeDir.normalized * preyFleeRadius;
                            agent.SetDestination(fleeGoal);
                        }
                    }
                }
            }

            yield return new WaitForSeconds(0.5f);
        }
    }

    IEnumerator UpdatePredator(){
        while(true) {
            // for each pred find the closest prey
            foreach (var pred in preds)
            {
                Collider[] colliders = Physics.OverlapSphere(pred.transform.position, predatorRadius);

                // don't do anything unless something is nearby
                if(colliders.Length > 0) {
                    // calculate closest prey
                    float minDist = 100f;
                    Vector3 closestPrey = Vector3.zero;

                    foreach(var collider in colliders) {
                        if(collider.tag == "prey") {
                            float dist = Vector3.Distance(pred.transform.position, collider.transform.position);
                            if(dist < minDist) {
                                minDist = dist;
                                closestPrey = collider.transform.position;
                            }
                        }
                    }

                    if(!closestPrey.Equals(Vector3.zero)){                    
                        // only set the new destination if the path is valid
                        NavMeshPath path = new NavMeshPath();
                        NavMeshAgent agent = pred.GetComponent<NavMeshAgent>();
                        agent.speed = predatorSpeed;
                        agent.CalculatePath(closestPrey, path);

                        if(path.status != NavMeshPathStatus.PathInvalid) {
                            agent.SetDestination(path.corners[path.corners.Length - 1]);
                        }
                    }
                }

                
                // set closest prey as destination for pred
                // NavMeshAgent agent = pred.GetComponent<NavMeshAgent>();
                // agent.speed = predatorSpeed;
                // agent.SetDestination(closestPrey.transform.position);
            }

            yield return new WaitForSeconds(1f);
        }
    }
}
