using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TaskCharakterAnimation : MonoBehaviour
{
    public GameObject walkAroundObject;
    public GameObject player;
    public float radiusAroundObject;

    private Animator anim;
    private Transform currentTransform;
    private float currentDistance;

    //When changing walking/standing/happy booleans -> the state-variables in the animationController must also be changed
    //For change of the task-character movements, maybe the transitions in the animationController have also to be adjusted
    private float walkingTime = 5;
    private bool walking = true;
    private float standingTime = 3;
    private bool standing = false;
    private float timer = 0;
    private bool rotate = false;
    private float nextRotation = 0;
    private float rotationUnits = 0;
    private float rotationTime = 2;
    private bool happy = false;

    private static bool playerInTalkingZone = false;

    // Start is called before the first frame update
    void Start()
    {
        anim = GetComponent<Animator>();
        currentTransform = GetComponent<Transform>();
        CommunicationEvents.PushoutFactEvent.AddListener(startHappy);
        CommunicationEvents.PushoutFactEndEvent.AddListener(stopHappy);
    }

    // Update is called once per frame
    void Update()
    {
        //Do nothing else than the animation if animationController is in happy-State
        if (happy)
            return;

        RaycastHit hit;
        Ray ray = new Ray(player.transform.position, player.transform.forward);
        int layerMask = LayerMask.GetMask("TalkingZone"); //only hit TalkingZone

        //If Player is in TalkingZone: TaskCharacter should look to the Player, stop walking and enable enter-key for talking
        if (Physics.Raycast(ray, out hit, 5f, layerMask))
        {
            this.walking = false;
            this.standing = true;
            this.timer = 0;
            rotate = false;
            //Change boolean for switching to Standing-State in AnimationController
            anim.SetBool("standing", true);
            //Enable enter-key for talking for Charakter-Dialog
            setPlayerInTalkingZone(true);

            //Face walkAroundObject to Player (but only on y-Axis, so ignore x-and z-axis)
            currentTransform.LookAt(new Vector3(player.transform.position.x, currentTransform.position.y, player.transform.position.z));

            return;
        }
        else {
            //disable enter-key for talking
            setPlayerInTalkingZone(false);
        }

        this.timer += Time.deltaTime;

        if (rotate)
        {
            if (this.timer <= rotationTime)
            {
                //Change to random direction after standing-state
                currentTransform.RotateAround(currentTransform.position, Vector3.up, rotationUnits);
            }
            else {
                //After rotating: Change to Walking-State
                rotate = false;
                this.timer = 0;
                //Change boolean for switching to Walking-State in AnimationController
                anim.SetBool("standing", false);
            }
        }
        else
        {
            //If walking-time is over -> Change to standing-state
            if (walking && !standing)
            {
                if (this.timer >= this.walkingTime)
                {
                    this.walking = false;
                    this.standing = true;
                    this.timer = 0;
                    //Change boolean for switching to Standing-State in AnimationController
                    anim.SetBool("standing", true);
                }

            }
            else
            {
                //If standingTime is over: Change to walking-state, but before set rotate=true for rotating before walking
                if (this.timer >= this.standingTime)
                {
                    this.standing = false;
                    this.walking = true;
                    this.timer = 0;

                    //Calculate distance from tree, so that the TaskCharacter only walks in a specific radius around the tree
                    //so that the player always knows where he is
                    currentDistance = (currentTransform.position - walkAroundObject.transform.position).magnitude;
                    //Turn on the radius-edges around the radiusAroundObject
                    if (currentDistance > radiusAroundObject)
                    {
                        //Rotate Towards tree if radiusAroundObject is out of radius
                        //Rotate randomly between +/-5° towards the radiusAroundObject
                        int temp = Random.Range(0, 5);
                        int positive = (int)Random.Range(0, 2);
                        //Calculate NextRotation towards radiusAroundObject
                        nextRotation = Vector3.Angle(currentTransform.forward, (walkAroundObject.transform.position-currentTransform.position).normalized);

                        if (positive == 0)
                            nextRotation -= temp;
                        else
                            nextRotation += temp;
                    }
                    else
                    {
                        //Rotate Character randomly if radiusAroundObject is inside the radius
                        //Rotate inside the range of -180° and 180° because a normal human would turn e.g. -60° instead of 240°
                        nextRotation = Random.Range(0, 180);
                        int positive = (int)Random.Range(0, 2);
                        if (positive == 0)
                            nextRotation *= -1;
                    }

                    rotationUnits = nextRotation / (rotationTime/Time.deltaTime);
                    rotate = true;
                }
            }
        }
    }

    public void startHappy(Fact startFact)
    {
        //Set Variable in animationController to change the state
        anim.SetBool("solved", true);
        happy = true;
    }

    public void stopHappy(Fact startFact) {
        //Set Variable in animationController to change the state
        anim.SetBool("solved", false);
        happy = false;
        resetToStart();
    }

    public void resetToStart() {
        //On Reset: Player must go into walking state, because it could be that after the happy/running-animation the player is 
        //out of radius and rotates -> AnimationController StateMachine always changes into walking-state after hyppAnimation
        walking = false;
        standing = true;
        rotate = false;
        nextRotation = 0;
        rotationUnits = 0;
        playerInTalkingZone = false;
        timer = 0;
    }

    //Static Method for CharacterDialog
    public static bool getPlayerInTalkingZone() {
        return playerInTalkingZone;
    }

    //Static Method for CharacterDialog
    public static void setPlayerInTalkingZone(bool value) {
        playerInTalkingZone = value;
    }

}