#if USING_XRI

using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

namespace SimplifyXR
{
    public enum XRInteractorEvent
    {
        HoverEntered,
        HoverExited,
        SelectEntered,
        SelectExited
    }

    [Serializable]
    public class XRInteractorPair
    {
        [Required, Tooltip("The interactor object"), SerializeField]
        public XRBaseInteractor interactor;

        [Conditional("interactor", null, ComparisonType.NotEqual),
            Tooltip("The interactor event to listen to"), SerializeField]
        public XRInteractorEvent interactorEvent;
    }
    /// <summary>
    /// Initiates a sequence based on an interactor event trigger
    /// </summary>
    [DirectiveCategory(DirectiveCategories.Initiator, DirectiveSubCategory.UserInteraction, prettyName = "XR Interactor Event", directiveLibrary = DirectiveLibrary.XRI, directiveInfo = "This initiator starts a sequence when a <b>XR Interactor Event</b> is <b>detected.</b>")]

    public class XRInteractorInitiator : EventInitiator, ICanToggle
    {
        [Tooltip("Listen to multiple interactions")]
        public bool listenToMultiple;

        [Required, Tooltip("The interactor object"),
            Conditional("listenToMultiple", false, ComparisonType.Equals)]
        public XRBaseInteractor interactor;

        [Conditional("interactor", null, ComparisonType.NotEqual),
            Conditional("listenToMultiple", true, ComparisonType.NotEqual),
            Tooltip("The interactor event to listen to")]
        public XRInteractorEvent interactorEvent;

        [Conditional("listenToMultiple", true, ComparisonType.Equals),
            Tooltip("The interactor event to listen to")]
        public List<XRInteractorPair> interactors;

        [HideInInspector]
        public string eventFieldInfoName;

#if UNITY_EDITOR
        [Tooltip("If we should be listening for events. Can be toggled with ModifyToggle.")]
#endif
        public bool listening = true;

        public override List<KnobKeywords> ReceiveKeywords()
        {
            return new List<KnobKeywords>();
        }

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

        #region interactor event handlers

        void RegisterEventHandler(XRBaseInteractor interactor, XRInteractorEvent interactorEvent, bool register = true)
        {
            if (interactor != null)
            {
                switch (interactorEvent)
                {
                    case XRInteractorEvent.HoverEntered:
                        if (register) interactor.hoverEntered.AddListener(SingleTypeInitiate);
                        if (!register) interactor.hoverEntered.RemoveListener(SingleTypeInitiate);
                        break;
                    case XRInteractorEvent.HoverExited:
                        if (register) interactor.hoverExited.AddListener(SingleTypeInitiate);
                        if (!register) interactor.hoverExited.RemoveListener(SingleTypeInitiate);
                        break;
                    case XRInteractorEvent.SelectEntered:
                        if (register) interactor.selectEntered.AddListener(SingleTypeInitiate);
                        if (!register) interactor.selectEntered.RemoveListener(SingleTypeInitiate);
                        break;
                    case XRInteractorEvent.SelectExited:
                        if (register) interactor.selectExited.AddListener(SingleTypeInitiate);
                        if (!register) interactor.selectExited.RemoveListener(SingleTypeInitiate);
                        break;
                }
            }
        }
        #endregion

        protected new void Awake()
        {
            base.Awake();
            if (enabled) RegisterEvents(true);
        }

        protected void RegisterEvents(bool register)
        {
            if (!listenToMultiple)
            {
                RegisterEventHandler(interactor, interactorEvent, register);
            }
            else
            {
                foreach (XRInteractorPair interactorPair in interactors)
                {
                    RegisterEventHandler(interactorPair.interactor, interactorEvent, register);
                }
            }
        }

        protected new void OnDestroy()
        {
            base.OnDestroy();
            RegisterEvents(false);
        }

        public void SingleTypeInitiate(BaseInteractionEventArgs args)
        {
            //If we are listening, go ahead and process the event
            if (listening)
            {
                SendData(args);
                base.Initiate();
            }
           
        }

        void SendData(BaseInteractionEventArgs args)
        {
            Debug.Log("[" + this.name + "]: " + "XRInteractorInitiator -> " + "SendData -> " + interactorEvent.ToString() + "," + args.interactorObject.transform.name + "," + args.interactableObject.transform.name + ")");
            AddPassableData(new List<string> { "BaseInteractionEvent" }, new List<object> { args });
        }

        #region ICanToggle implementation
        string IModify<ICanToggle>.ModifyObjectName { get { return "Listen"; } }

        public void SetTrue()
        {
            listening = true;
        }

        public void SetFalse()
        {
            listening = false;
        }

        public void Toggle()
        {
            listening = !listening;
        }
        #endregion
    }
}
#endif

