using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XNode;
using RPGCreationKit.BehaviourTree;
using RPGCreationKit.AI;
using RPGCreationKit.BehaviourTree.Data;

namespace RPGCreationKit.BehaviourTree
{
    /// <summary>
    /// Allows the Invoking of a method with the attribute [BT_AIInvokable] from a BehaviourTree
    /// </summary>
    [CreateNodeMenu("RPGCK_BehaviourTree/Actions/AI/Set Property", order = 1)]
    [System.Serializable]
    public class AI_SetPropertyNode : BTNode
    {
        public string ComponentToSet = "RckAI";
        public string PropertyToSet = "";

        public bool useVariable = true;
        public BTVariable storedValue;

        public BTParameter instantValue;

        // Use this for initialization
        protected override void Init()
        {
            base.Init();
        }

        // Return the correct value of an output port when requested
        public override object GetValue(NodePort port)
        {
            return null; // Replace this
        }

        public override void OnStart()
        {
            STARTED = true;

            if(useVariable)
                storedValue = BTReference.SolveReference(this.graph as RPGCK_BT, storedValue.name);
            else
            {
                switch(instantValue.parameterType)
                {
                    case BTParameterType.INT:
                        // Create a storedValue from instantreference
                        BT_Int newbtInt = CreateInstance<BT_Int>();
                        newbtInt.Name = "TEMP_BT_INT";
                        newbtInt.value = instantValue.intValue;

                        storedValue = newbtInt;
                        break;

                    case BTParameterType.FLOAT:
                        // Create a storedValue from instantreference
                        BT_Float newBTFloat = CreateInstance<BT_Float>();
                        newBTFloat.Name = "TEMP_BT_FLOAT";
                        newBTFloat.value = instantValue.floatValue;

                        storedValue = newBTFloat;
                        break;

                    case BTParameterType.BOOL:
                        // Create a storedValue from instantreference
                        BT_Bool newBTBool = CreateInstance<BT_Bool>();
                        newBTBool.Name = "TEMP_BT_BOOL";
                        newBTBool.value = instantValue.boolValue;

                        storedValue = newBTBool;
                        break;
                }
            }
        }

        public override NodeState Execute()
        {
            if (m_NodeState == NodeState.Success || m_NodeState == NodeState.Failure)
                if (hasEvaluated == true)
                    return m_NodeState;

            if (!STARTED)
                OnStart();

            // Check if a storedValue exists
            if (storedValue == null)
            {
                Debug.Log("BehaviourTree : Tried to GetField but no storedValue was assigned. Node fails.");
                m_NodeState = NodeState.Failure;
                hasEvaluated = true;
                return m_NodeState;
            }

            var component = (this.graph as RPGCK_BT).owner.GetComponent<RckAI>();

            // Check if component exists
            if (component == null)
            {
                Debug.Log("BehaviourTree : Tried to GetField but the given Component: \"RckAI\" was not found. Node fails.");
                m_NodeState = NodeState.Failure;
                hasEvaluated = true;
                return m_NodeState;
            }

            var field = component.GetType().GetProperty(PropertyToSet);

            field.SetValue(component, storedValue.GetValue());

            m_NodeState = NodeState.Success;
            hasEvaluated = true;
            return m_NodeState;
        }


        public override void OnRemoveConnection(NodePort port)
        {
            base.OnRemoveConnection(port);
            indexInSequence = -1;
        }

        public override void ReEvaluate()
        {
            if (m_NodeState != NodeState.Running)
                base.ReEvaluate();
        }
    }
}