using UnityEngine;
using System.Collections;

public class EnemyAI : MonoBehaviour {

    public DecisionTree root;
    public GameObject bananaPrefab;
    private Transform target;
    private Rigidbody2D Player;
    private Rigidbody2D Enemy;
    private Animator myAnimator;
    public float enemyHealth, original;
    public float playerHealth;
    public float playerHealthOriginal; // ***Maybe use playerstats maxhealth?
    public static bool LookRight = true;
    private bool set;
    private float speed = 1;
    private float attackSpeed;
    private float randomSpeed;
    float spaceBarCounter = 0; //check for how aggresive the player is being 
    private float coolDown = 0;
    private bool actionDelay = false;
    private float searchDelay = 0.2f;
    private float searchCoolDown = 0;
    public static bool isEnemyKicking = false;
    public static bool isEnemyPushing = false;
    private float kickCoolDown = 0;
    private float kickTimer;
    private float aggressiveTimer;
    private bool aggressiveCheck = false;
    private bool isAggressive = false;
    private bool isPlayerAttacking = false;
    private bool isPlayerBlocking = false;
    private bool isPlayerKicking = false;
    private bool isPlayerPushing = false;
    private float playerPushingTimer;
    private float throwCoolDown = 0;
    private float throwTimer;
    private bool canJump = false;
    private int playerPushingCounter = 0;
    private float randomActionCoolDown = 0;
    private float randomAction;
    private float randomAcioionSpeed;

    void Start() {

        throwTimer = 2;
        throwCoolDown = 1;
        playerPushingTimer = 2;
        aggressiveTimer = 3;
        kickTimer = 5;
        randomSpeed = Random.Range(0, 1f);
        attackSpeed = randomSpeed;
        randomAcioionSpeed = Random.Range(0, 2f);
        randomAction = randomAcioionSpeed;
        enemyHealth = Random.Range(50, 500);
        original = enemyHealth;
        playerHealth = PlayerStats.getHealth();
        playerHealthOriginal = playerHealth;


        root = new DecisionTree();
        //  Debug.Log("start");
        target = GameObject.FindGameObjectWithTag("Player").transform; //look at the player
        Player = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody2D>();
        myAnimator = GetComponent<Animator>(); //required for animation *******
        Enemy = GetComponent<Rigidbody2D>();
        BuildDecisionTree();

    }

    void Update() {
        AggressiveCoolDown();
        BlockCheck();
        AttackCheck();
        KickCheck();
        PushCheck();
        getPushed();
        throwCoolDown -= Time.deltaTime;
        coolDown -= Time.deltaTime;
        kickCoolDown -= Time.deltaTime;
        randomActionCoolDown -= Time.deltaTime;

        if (canJump == true) {
            playerPushingTimer -= Time.deltaTime;
            if (playerPushingTimer <= 0) {
                JumpPlayer();
                playerPushingTimer = 2;
                canJump = false;
            }
        }

        if (actionDelay == true) {
            searchCoolDown -= Time.deltaTime;
            if (searchCoolDown <= 0) {
                searchCoolDown = searchDelay;
                root.search();
            }

        }
        else {
            root.search();
            actionDelay = false;
        }

    }

    public void getPushed() {
        if (Vector3.Distance(transform.position, target.position) < 2f && isPlayerPushing == true) {
            myAnimator.SetBool("knockBack", true);
            myAnimator.SetBool("kick", false);
            myAnimator.SetBool("attack", false);
            myAnimator.SetBool("block", false);
            playerPushingCounter++;
            if (LookRight == true) {
                Enemy.AddForce(new Vector2(-500, 0));
            }
            else {
                Enemy.AddForce(new Vector2(500, 0));
            }

            if (playerPushingCounter >= 2) {
                playerPushingCounter = 0;
                canJump = true;
            }
        }
    }

    public void JumpPlayer() {
        if (Vector3.Distance(transform.position, target.position) < 6f) {
            if (LookRight == true) {
                Enemy.AddForce(new Vector2(200, 1000));
            }
            else {
                Enemy.AddForce(new Vector2(-200, 1000));
            }
        }
    }

    public void AggressiveCoolDown() {
        if (Input.GetKeyDown(KeyCode.Space)) {
            spaceBarCounter++;
            // Debug.Log(spaceBarCounter);
            aggressiveCheck = true;
        }
        if (aggressiveCheck == true) {
            aggressiveTimer -= Time.deltaTime;
            // Debug.Log(agressiveTimer);
        }

        if (aggressiveTimer <= 0) {
            aggressiveCheck = false;
            spaceBarCounter = 0;
            aggressiveTimer = 5;
        }
    }

    public void BlockCheck() {
        isPlayerBlocking = ArenaCombatControl.block;
        Debug.Log(isPlayerBlocking + "Enemy");

        if (isPlayerBlocking == false) {
            myAnimator.SetBool("kick", false);
        }
    }

    public void AttackCheck() {
        isPlayerAttacking = ArenaCombatControl.attack;
    }

    public void KickCheck() {
        isPlayerKicking = ArenaCombatControl.kick;
    }

    public void HpCheck() {
        playerHealth = PlayerStats.curHealth;
    }

    public void PushCheck() {
        isPlayerPushing = ArenaCombatControl.push;
    }



    public void ChangeHealthBare(int damage) {
        GameObject healthbar = GameObject.Find("healthbarFulle");
        float newsize = healthbar.transform.localScale.x - ((damage / original) * 0.3f);
        healthbar.transform.localScale = new Vector3(newsize, 0.3f, 1f);
        if (enemyHealth <= 0) {
            healthbar.GetComponent<SpriteRenderer>().enabled = false;
        }

    }

    public void ApplyDamageE(int damage) {
        enemyHealth -= damage;
        if (enemyHealth <= 0) {
            Destroy(gameObject);
        }
    }


    public bool d_isPlayerAttacking() {
        if (isPlayerAttacking == true) {
            return true;
        }
        Debug.Log("Player Not Attacking");
        return false;
    }

    public bool d_isPlayerKicking() {
        if (isPlayerKicking == true) {
            return true;
        }
        return false;
    }


    public bool d_inAttackRange() {
        isEnemyKicking = false;
        isEnemyPushing = false;
        if (Vector3.Distance(transform.position, target.position) < 2f && Vector3.Distance(transform.position, target.position) > 1f) {
            myAnimator.SetBool("speed", false);
            return true;
        }

        else if (isAggressive == true) {
            myAnimator.SetBool("block", true);
            return true;
        }

        else {
            myAnimator.SetBool("kick", false);
            myAnimator.SetBool("attack", false);
            myAnimator.SetBool("block", false);
            myAnimator.SetBool("knockBack", false);

            // Debug.Log("In Zone- not");
            return false;
        }
    }

    public bool d_isPlayerTooClose() {

        if (Vector3.Distance(transform.position, target.position) < 1f) {
            myAnimator.SetBool("speed", true);
            return false;
        }
        else {
            return true;
        }
    }

    public bool d_isPlayerTooFar() {
        if (Vector3.Distance(transform.position, target.position) > 7.5f && Vector3.Distance(transform.position, target.position) < 12f) {
            return true;
        }
        else {
            return false;
        }
    }


    public bool d_isPlayerAggresive() {
        if (spaceBarCounter > 5 && aggressiveTimer > 0) {
            isAggressive = true;
            Debug.Log("Aggressive");
            return true;
        }

        else {
            isAggressive = false;
            Debug.Log("Not Aggresive");
            return false;
        }

    }

    public bool d_isPlayerBlocking() {
        if (isPlayerBlocking == true) {
            return true;
        }
        return false;
    }



    public bool d_isPlayerHpLow() {
        if ((playerHealthOriginal / 2) > playerHealth) {
            Debug.Log("Player Half Health");
            return true;
        }
        Debug.Log("Player Full Health");
        return false;
    }


    public bool d_isHpLow() {
        if ((original / 2) > enemyHealth) {
            Debug.Log("Enemy Half Health");
            return true;
        }

        Debug.Log("Enemy Full Health");
        return false;
    }


    //makes a random decision with a 75% true return and a 25% false return
    public bool d_randomDecision75() {
        int x = Random.Range(1, 4);
        // Debug.Log(x);
        if (x == 1) {
            return false;
        }
        else return true;
    }

    public bool d_jumpOverPlayer() {
        Debug.Log("Jumped");
        if (Vector3.Distance(transform.position, target.position) > 3f && Vector3.Distance(transform.position, target.position) < 8f && playerPushingCounter >= 2) {
            Debug.Log("Jumped");
            playerPushingCounter = 0;
            return true;
        }
        return false;
    }


    // Actions
    public void a_attack() {
        actionDelay = true;
        myAnimator.SetFloat("speed", 0f);
        if (coolDown <= 0) {
            coolDown = attackSpeed;
            Debug.Log("attacking");
            myAnimator.SetBool("attack", true);
            Enemy.velocity = Vector2.zero;
        }
        else {
            myAnimator.SetBool("attack", false);
        }
    }

    public void a_jumpOverPlayer() {
        actionDelay = true;
        if (LookRight == true) {
            Debug.Log("Over Yo HEAD");
            Enemy.AddForce(new Vector2(100, 1000));
        }
        else {
            Debug.Log("Over Yo HEAD");
            Enemy.AddForce(new Vector2(-100, 1000));
        }
    }

    public void a_push() {
        actionDelay = true;
        Debug.Log("Pushing");
        isEnemyPushing = true;
    }

    public void a_superAttack() {
        myAnimator.SetFloat("speed", 0f);
        Debug.Log("attacking");
        myAnimator.SetBool("attack", true);
    }

    public void a_jumpBack() {
        actionDelay = true;
        if (LookRight == true) {
            Enemy.AddForce(new Vector2(-250, 500));
        }
        else {
            Enemy.AddForce(new Vector2(250, 500));
        }
    }

    public void a_jump() {
        actionDelay = true;
        Enemy.AddForce(new Vector2(0, 500));
    }

    public void a_block() {
        Debug.Log("Block");
        actionDelay = true;
        myAnimator.SetBool("attack", false);
        myAnimator.SetBool("block", true);
        Enemy.velocity = Vector2.zero;

    }

    public void a_kick() {
        actionDelay = true;
        if (kickCoolDown <= 0) {
            isEnemyKicking = true;
            kickCoolDown = kickTimer;
            Debug.Log("kicking");
            myAnimator.SetBool("kick", true);
            Enemy.velocity = Vector2.zero;
        }
        else {
            myAnimator.SetBool("kick", false);
            myAnimator.SetBool("attack", true);
        }


    }

    public void a_throw() {
        actionDelay = true;
        myAnimator.SetFloat("speed", 0f);
        if (throwCoolDown <= 0) {
            throwCoolDown = throwTimer;
            Debug.Log("throwing");
            myAnimator.SetBool("throw", true);
            Invoke("bananaToss", 0.2f);
        }
        else {
            myAnimator.SetBool("throw", false);
        }         
    }

    public void bananaToss() {
        Vector3 offset = transform.rotation * new Vector3(0.5f, 0.5f, 0); //fire from the front of the player
        Instantiate(bananaPrefab, transform.position + offset, transform.rotation);
    }

    public void a_randomAction() {
        Debug.Log("Action");
        float x = Random.Range(0, 250);

        actionDelay = true;
        if (randomActionCoolDown <= 0) {
            //Debug.Log(x);
            randomActionCoolDown = randomAction;

            if (x < 125) {
                a_block();
            }
            if (x > 225) {
                a_jumpBack();
            }

            if (x >= 125 && x <= 225) {
                a_attack();
            }
        }

    }

    public void a_randomBlock() {

        float x = Random.Range(0, 250);

        actionDelay = true;
        if (randomActionCoolDown <= 0) {
            //Debug.Log(x);
            randomActionCoolDown = randomAction;

            if (x < 125) {
                a_block();
            }
            if (x >= 125 && x <= 200) {
                a_jumpBack();
            }

            if (x > 200) {
                a_jumpOverPlayer();
            }
        }

    }

    public void a_randomAttack() {

        float x = Random.Range(0, 250);

        actionDelay = true;
        if (randomActionCoolDown <= 0) {
            //Debug.Log(x);
            randomActionCoolDown = randomAction;

            if (x < 125) {
                a_attack();
            }
            if (x >= 125 && x <= 200) {
                a_kick();
            }

            if (x > 200) {
                a_push();
            }
        }
    }

    public void a_disarmSheild() {
        actionDelay = true;
        float x = Random.Range(0, 3);
        if (x == 1) {
            a_kick();
        }

        else {
            a_randomAttack();
        }

    }


    //template for a 'poison' special attack. Will slowly and gradually drain players health over time.
    public void poison() {
        Debug.Log("Performing Poison Attack");

    }

    public void a_moveToPlayer() {
        Debug.Log("moving");
        //rotate to look at the player
        //transform.LookAt(target.position);
        myAnimator.SetFloat("speed", 1); // This should probbaly reflect the actual speed
        transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);

        if (target.transform.position.x <= transform.position.x) //players spot in world space as opposed to enemy "self" spot 
        {
            LookRight = false;
            transform.rotation = new Quaternion(0, 180, 0, 0); // flips enemy around to face the player on x axis only
        }
        else if (target.transform.position.x >= transform.position.x) //players spot in world space as opposed to enemy "self" spot
        {
            LookRight = true;
            transform.rotation = new Quaternion(0, 0, 0, 0); // flips enemy around to face the player on x axis only }
        }
    }

    public void a_moveFromPlayer() {
        Debug.Log("movingAWAY");
        //rotate to look at the player
        //transform.LookAt(target.position);
        myAnimator.SetFloat("speed", 1); // This should probbaly reflect the actual speed
        transform.position = Vector2.MoveTowards(transform.position, target.position, -speed * Time.deltaTime);

        if (target.transform.position.x <= transform.position.x) //players spot in world space as opposed to enemy "self" spot 
        {
            transform.rotation = new Quaternion(0, 180, 0, 0); // flips enemy around to face the player on x axis only
        }
        else if (target.transform.position.x >= transform.position.x) //players spot in world space as opposed to enemy "self" spot
        {
            transform.rotation = new Quaternion(0, 0, 0, 0); // flips enemy around to face the player on x axis only }
        }
    }




    public void BuildDecisionTree() {

        //Actions
        DecisionTree RandomAction = new DecisionTree();
        RandomAction.setAction(a_randomAction);

        DecisionTree RandomBlock = new DecisionTree();
        RandomBlock.setAction(a_randomBlock);

        DecisionTree Push = new DecisionTree();
        Push.setAction(a_push);

        DecisionTree Kick = new DecisionTree();
        Kick.setAction(a_kick);

        DecisionTree DisarmShield = new DecisionTree();
        DisarmShield.setAction(a_disarmSheild);

        DecisionTree JumpBack = new DecisionTree();
        JumpBack.setAction(a_jumpBack);

        DecisionTree Block = new DecisionTree();
        Block.setAction(a_block);

        DecisionTree MoveToPlayer = new DecisionTree();
        MoveToPlayer.setAction(a_moveToPlayer);

        DecisionTree Attack = new DecisionTree();
        Attack.setAction(a_attack);

        DecisionTree MoveAway = new DecisionTree();
        MoveAway.setAction(a_moveFromPlayer);

        DecisionTree JumpOverPlayer = new DecisionTree();
        JumpOverPlayer.setAction(a_jumpOverPlayer);

        DecisionTree Throw = new DecisionTree();
        Throw.setAction(a_throw);

        // Decisions
        DecisionTree isPlayerBlocking = new DecisionTree();
        isPlayerBlocking.setDecision(d_isPlayerBlocking);
        isPlayerBlocking.setLeft(DisarmShield);
        isPlayerBlocking.setRight(Attack);

        DecisionTree JumpPlayer = new DecisionTree();
        JumpPlayer.setDecision(d_jumpOverPlayer);
        JumpPlayer.setLeft(JumpOverPlayer);
        JumpPlayer.setRight(RandomAction);

        DecisionTree GettingAttacked = new DecisionTree();
        GettingAttacked.setDecision(d_isPlayerAttacking);
        GettingAttacked.setLeft(RandomBlock);
        GettingAttacked.setRight(JumpPlayer);

        DecisionTree PlayerHP = new DecisionTree();
        PlayerHP.setDecision(d_isPlayerHpLow);
        PlayerHP.setLeft(Attack);
        PlayerHP.setRight(GettingAttacked);

        DecisionTree PlayerHP2 = new DecisionTree();
        PlayerHP2.setDecision(d_isPlayerHpLow);
        PlayerHP2.setLeft(Attack);
        PlayerHP2.setRight(MoveAway);

        DecisionTree PlayerHP3 = new DecisionTree();
        PlayerHP3.setDecision(d_isPlayerHpLow);
        PlayerHP3.setLeft(Attack);
        PlayerHP3.setRight(isPlayerBlocking);

        DecisionTree EnemyHP = new DecisionTree();
        EnemyHP.setDecision(d_isHpLow);
        EnemyHP.setLeft(PlayerHP2);
        EnemyHP.setRight(PlayerHP3);

        DecisionTree JumpPlayer2 = new DecisionTree();
        JumpPlayer2.setDecision(d_jumpOverPlayer);
        JumpPlayer2.setLeft(JumpOverPlayer);
        JumpPlayer2.setRight(EnemyHP);

        DecisionTree GettingAttacked2 = new DecisionTree();
        GettingAttacked2.setDecision(d_isPlayerAttacking);
        GettingAttacked2.setLeft(RandomAction);
        GettingAttacked2.setRight(JumpPlayer2);

        //Random Action Trees
        DecisionTree Random01 = new DecisionTree();
        Random01.setDecision(d_randomDecision75);
        Random01.setLeft(PlayerHP);
        Random01.setRight(RandomAction);

        //Random Action Trees
        DecisionTree Random02 = new DecisionTree();
        Random02.setDecision(d_randomDecision75);
        Random02.setLeft(GettingAttacked2);
        Random02.setRight(RandomAction);

        DecisionTree Aggressiveness = new DecisionTree();
        Aggressiveness.setDecision(d_isPlayerAggresive);
        Aggressiveness.setLeft(Random01);
        Aggressiveness.setRight(Random02);

        DecisionTree IsPlayerTooFar = new DecisionTree();
        IsPlayerTooFar.setDecision(d_isPlayerTooFar);
        IsPlayerTooFar.setLeft(Throw);
        IsPlayerTooFar.setRight(MoveToPlayer);

        DecisionTree IsPlayerTooClose = new DecisionTree();
        IsPlayerTooClose.setDecision(d_isPlayerTooClose);
        IsPlayerTooClose.setLeft(IsPlayerTooFar);
        IsPlayerTooClose.setRight(MoveAway);

      

        root.setDecision(d_inAttackRange);
        root.setLeft(Aggressiveness);
        root.setRight(IsPlayerTooClose);

    }


}