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

public class Guest : MonoBehaviour {

    [HideInInspector]
    public bool seen = false;
    
    [HideInInspector]
    public bool greeted = false;

    public Sprite Body;
    public Sprite Suit;
    public Sprite Eyes;
    public Sprite Hair;

    [HideInInspector]
    public List<FeatureInfo> modsInfo = new List<FeatureInfo>();
    public List<Sprite> modsSprites = new List<Sprite>();

    public List<string> CorrectGreetings()
    {
        return modsInfo.Select((x) => x.greeting).ToList();
    }
    private bool waitingToBeGreeted = true;
    private bool greeting = false;
    //adjust this to set (waiting for greeting ) timer
    [HideInInspector]
    public float greetTimer = 3f;
    //adjust this to set how before guest leaves
    [HideInInspector]
    public float leaveTimer = 5f;
    // Use this for initialization

    public Animator anim;
    NavMeshAgent agent;
    Vector2 smoothDeltaPosition = Vector2.zero;
    Vector2 velocity = Vector2.zero;

    GameState state;

    public void Awake()
    {
        state = GameObject.Find("GameState").GetComponent<GameState>();
    }

    private bool timerOn;
    private float timer = 0;
    private int seatIndex = -1;
    private bool walking = false;
	void Start () {
        greetTimer = state.greetTime;
        leaveTimer = state.leaveTime;

        agent = GetComponent<NavMeshAgent>();

        timerOn = true;
        timer = -2f;

        anim.SetBool("walking", true);
        walking = true;
        //anim = GetComponent<Animator>();
        // Don’t update position automatically
        //agent.updatePosition = false;
    }

    void Update() {
        //simple timer 
        if (timerOn) {
            //increment with time passed
            timer += Time.deltaTime;
            
            if (timer > greetTimer && waitingToBeGreeted)
            {
                Debug.Log("Took too long, guest leaving");
                //randomly pick which door to exit
                Vector3 exitPosition = SeatAllocator.instance.exitPositions[Random.Range(0, SeatAllocator.instance.exitPositions.Length)].transform.position;
                //navigate to exit
                GoToPoint(exitPosition);

                //turn off timer
                timerOn = false;
                //no longer waiting for greeting
                waitingToBeGreeted = false;
                //reset timer;
                timer = 0;
            }
            else if (timer > leaveTimer) {
                
                //timer up now leave
                SeatAllocator.instance.UnAssignSeat(seatIndex);
                //randomly pick which door to exit
                Vector3 exitPosition = SeatAllocator.instance.exitPositions[Random.Range(0, SeatAllocator.instance.exitPositions.Length)].transform.position;
                //navigate to exit
                GoToPoint(exitPosition);
                //turn off timer
                timerOn = false;
                //reset timer;
                timer = 0;
            }
        }

        if(timerOn && timer < greetTimer && waitingToBeGreeted)
        {
            var child = transform.GetChild(0);
            child.localScale = new Vector3(Mathf.Max(0f, 1f - timer / greetTimer), child.localScale.y, child.localScale.z);
        }
        else
        {
            var child = transform.GetChild(0);
            child.localScale = new Vector3(0f, child.localScale.y, child.localScale.z);
        }


        if (walking && agent.remainingDistance <= agent.stoppingDistance + 0.08 )
        {
            // Arrived
            anim.SetBool("walking", false);
        }
        //NavigationAnimation();

        if(state.currentCharacter == this)
            state.Portrait.transform.position = Camera.main.WorldToScreenPoint(transform.position);
    }

    void NavigationAnimation()
    {
        Vector3 worldDeltaPosition = agent.nextPosition - transform.position;

        // Map 'worldDeltaPosition' to local space
        float dx = Vector3.Dot(transform.right, worldDeltaPosition);
        float dy = Vector3.Dot(transform.forward, worldDeltaPosition);
        Vector2 deltaPosition = new Vector2(dx, dy);

        // Low-pass filter the deltaMove
        float smooth = Mathf.Min(1.0f, Time.deltaTime / 0.15f);
        smoothDeltaPosition = Vector2.Lerp(smoothDeltaPosition, deltaPosition, smooth);

        // Update velocity if time advances
        if (Time.deltaTime > 1e-5f)
            velocity = smoothDeltaPosition / Time.deltaTime;

        bool shouldMove = velocity.magnitude > 0.5f && agent.remainingDistance > agent.radius;

        /*if (velocity.x == 0 && velocity.y == 0)
        {
            anim.SetBool("walking", false);
        }
        else {
            anim.SetBool("walking", true);
        }*/
        // Update animation parameters
        anim.SetBool("walking", shouldMove);
        //anim.SetFloat("velx", velocity.x);
        //anim.SetFloat("vely", velocity.y);

        // GetComponent<LookAt>().lookAtTargetPosition = agent.steeringTarget + transform.forward;
        //agent.updatePosition = true;
    }

    public void SetAgentDestination(Vector3 destination) {
        agent.SetDestination(destination);
        walking = true;
    }

    void OnTriggerEnter(Collider other) {
        Debug.Log("Collided");
        //only if waiting to be greeted
        if (waitingToBeGreeted && other.tag == "Player")
        {
            //now wait to be interacted with
            timer = 0;
            timerOn = true;
            //start greeting process
            //waitingToBeGreeted = false;
            //other.GetComponent<Player>().;

            //need to update to pass guest (and assign)
            state.BeginNewGreeting(this);
            SeatAllocator.instance.targetGuest = this;
            
        }
        else if (!waitingToBeGreeted && other.tag == "Death")
            Death();
        
        
    }

    public void GreetedCorrectly() {
        //show sprite image and greeting options
        seatIndex = SeatAllocator.instance.AssignSeat();
        GoToPoint(SeatAllocator.instance.chairs[seatIndex].transform.position);
        timerOn = true;
        timer = 0;
        waitingToBeGreeted = false;
    }

    public void GreetedIncorrectly() {
        Debug.Log("Wrong Greeting guest is leaving");
        Vector3 exitPosition = SeatAllocator.instance.exitPositions[Random.Range(0, SeatAllocator.instance.exitPositions.Length)].transform.position;
        GoToPoint(exitPosition);
        timerOn = false;
        waitingToBeGreeted = false;
        timer = 0;
    }

    public void OnDestroy()
    {
        if(!greeted)
            state.GuestLeftWithoutGreet();
        if (state.currentCharacter == this)
            state.EndGreeting();
    }

    public void GoToPoint(Vector3 position) {
        agent.SetDestination(position);
        anim.SetBool("walking", true);
        walking = true;
    }

    public void Death() {
        Debug.Log(gameObject.name + " Just died");
        Destroy(gameObject);
    }
}
