#if USING_NETCODE_GO

using UnityEngine;
using System.Collections.Generic;
using Unity.Netcode.Components;


namespace SimplifyXR {

    /// <summary>
    /// Share rigidbody of NetworkObject over network.
    /// </summary>
    [DirectiveCategory(DirectiveCategories.Action, DirectiveSubCategory.Networking,
        prettyName = "Share Network Rigidbody",
        directiveInfo = "This <i>action</i> shares the rigidbody of a Networked Object.")]
    //[ExecuteInEditMode]
    public class ShareNetworkRigidbody : Actions
    {
        /// <summary>
        /// Select if sharing for more than one Rigidbody.
        /// </summary>
        #if UNITY_EDITOR
        [Tooltip("Select if sharing more than one Rigidbody")]
        #endif
        public bool UseListOfRigidbodies;

        /// <summary>
        /// The Rigidbody to share over the network.
        /// </summary>
        #if UNITY_EDITOR
        [Tooltip("The Rigidbody to share over the network.")]
        [Conditional("UseListOfRigidbodies", false, ComparisonType.Equals)]
        #endif
        public Rigidbody Rigidbody;

        /// <summary>
        /// The List of Rigidbodies to share over the network.
        /// </summary>
        #if UNITY_EDITOR
        [Tooltip("The List of Rigidbodies to share over the network.")]
        [Conditional("UseListOfRigidbodies", true, ComparisonType.Equals)]
        #endif
        public List<Rigidbody> Rigidbodies;

        public override List<KnobKeywords> ReceiveKeywords()
        {
            return new List<KnobKeywords> {
                new KnobKeywords("Rigidbody", typeof(Rigidbody)),
                new KnobKeywords("ListOfRigidbodies", typeof(List<Rigidbody>))
            };
        }

        public override List<KnobKeywords> SendKeywords()
        {
            return new List<KnobKeywords> {
                new KnobKeywords("Rigidbody", typeof(Rigidbody)),
                new KnobKeywords("ListOfRigidbodies", typeof(List<Rigidbody>))
            };
        }

        public override void Execute()
        {
            FindObjectPassed();
            if (CheckIfObjectExists())
            {
                SendData();
            }
            ThisActionCompleted();

        }

        void FindObjectPassed()
        {
            var objectPassed = GetPassableData();
            if (objectPassed == null) return;

            if (Rigidbodies.Count > 0 && UseListOfRigidbodies)
            {
                AddPassableData(new List<string> { "ListOfRigidbodies" },
                    new List<object> { Rigidbodies });
            }
            else if (Rigidbody != null && !UseListOfRigidbodies)
            {
                AddPassableData(new List<string> { "Rigidbody" },
                    new List<object> { Rigidbody });
            }
        }

        bool CheckIfObjectExists()
        {
            if ((!UseListOfRigidbodies && Rigidbody != null) || (UseListOfRigidbodies && Rigidbody != null))
            {
                GetGameObject();
                if (Rigidbodies != null)
                    return true;
            }
            else
                SimplifyXRDebug.SimplifyXRLog(SimplifyXRDebug.Type.AuthorError, "No Rigidbody specified or passed for {0}", SimplifyXRDebug.Args(this));

            return false;
        }

        void GetGameObject()
        {
            if (!UseListOfRigidbodies)
                ChangeGameObject(Rigidbody);
            else
            {
                foreach (Rigidbody r in Rigidbodies)
                    ChangeGameObject(r);
            }
        }

#if UNITY_EDITOR
        void OnValidate()
        {
            UnityEditor.EditorApplication.delayCall += () =>
            {
                if (!UseListOfRigidbodies)
                    ChangeGameObject(Rigidbody);
                else
                {
                    foreach (Rigidbody r in Rigidbodies)
                        ChangeGameObject(r);
                }
            };
        }
#endif

        void ChangeGameObject(Rigidbody rigid)
        {
            if (rigid != null)
            {
                AttachNetworkRigidbody(rigid);
            }
        }

        void AttachNetworkRigidbody(Rigidbody rigid)
        {
            rigid.gameObject.GetOrAddComponent<NetworkRigidbody>();
        }

        void SendData()
        {
            List<object> objects;
            if (!UseListOfRigidbodies)
                objects = new List<object> { Rigidbody, Rigidbodies};
            else
                objects = new List<object> { null, Rigidbodies, null };

            AddPassableData(new List<string> { "GameObject", "ListOfGameObjects", "Transform" }, objects);
        }
    }
}

#endif