using UnityEngine.Playables;
namespace UnityEngine.Timeline
{
    /// 
    /// Playable that controls the active state of a GameObject.
    /// 
    public class ActivationControlPlayable : PlayableBehaviour
    {
        /// 
        /// The state of a GameObject's activeness when a PlayableGraph stops.
        /// 
        public enum PostPlaybackState
        {
            /// 
            /// Set the GameObject to active when the PlayableGraph stops.
            /// 
            Active,
            /// 
            /// Set the GameObject to inactive when the [[PlayableGraph]] stops.
            /// 
            Inactive,
            /// 
            /// Revert the GameObject to the active state it was before the [[PlayableGraph]] started.
            /// 
            Revert
        }
        enum InitialState
        {
            Unset,
            Active,
            Inactive
        }
        /// 
        /// The GameObject to control.
        /// 
        public GameObject gameObject = null;
        /// 
        public PostPlaybackState postPlayback = PostPlaybackState.Revert;
        InitialState m_InitialState;
        /// 
        /// Creates a ScriptPlayable with an ActivationControlPlayable behaviour attached
        /// 
        /// PlayableGraph that will own the playable
        /// The GameObject that triggered the graph build
        /// The state to leave the gameObject after the graph is stopped
        /// Returns a playable that controls activation of a game object
        public static ScriptPlayable Create(PlayableGraph graph, GameObject gameObject, ActivationControlPlayable.PostPlaybackState postPlaybackState)
        {
            if (gameObject == null)
                return ScriptPlayable.Null;
            var handle = ScriptPlayable.Create(graph);
            var playable = handle.GetBehaviour();
            playable.gameObject = gameObject;
            playable.postPlayback = postPlaybackState;
            return handle;
        }
        /// 
        /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
        /// 
        /// The playable this behaviour is attached to.
        /// The information about this frame
        public override void OnBehaviourPlay(Playable playable, FrameData info)
        {
            if (gameObject == null)
                return;
            gameObject.SetActive(true);
        }
        /// 
        /// This function is called when the Playable play state is changed to PlayState.Paused.
        /// 
        /// The playable this behaviour is attached to.
        /// The information about this frame
        public override void OnBehaviourPause(Playable playable, FrameData info)
        {
            // OnBehaviourPause can be called if the graph is stopped for a variety of reasons
            //  the effectivePlayState will test if the pause is due to the clip being out of bounds
            if (gameObject != null && info.effectivePlayState == PlayState.Paused)
            {
                gameObject.SetActive(false);
            }
        }
        /// 
        /// This function is called during the ProcessFrame phase of the PlayableGraph.
        /// 
        /// The playable this behaviour is attached to.
        /// A FrameData structure that contains information about the current frame context.
        /// unused
        public override void ProcessFrame(Playable playable, FrameData info, object userData)
        {
            if (gameObject != null)// && !gameObject.activeSelf)
                gameObject.SetActive(true);
        }
        /// 
        /// This function is called when the PlayableGraph that owns this PlayableBehaviour starts.
        /// 
        /// The playable this behaviour is attached to.
        public override void OnGraphStart(Playable playable)
        {
            if (gameObject != null)
            {
                if (m_InitialState == InitialState.Unset)
                    m_InitialState = gameObject.activeSelf ? InitialState.Active : InitialState.Inactive;
            }
        }
        /// 
        /// This function is called when the Playable that owns the PlayableBehaviour is destroyed.
        /// 
        /// The playable this behaviour is attached to.
        public override void OnPlayableDestroy(Playable playable)
        {
            if (gameObject == null || m_InitialState == InitialState.Unset)
                return;
            switch (postPlayback)
            {
                case PostPlaybackState.Active:
                    gameObject.SetActive(true);
                    break;
                case PostPlaybackState.Inactive:
                    gameObject.SetActive(false);
                    break;
                case PostPlaybackState.Revert:
                    gameObject.SetActive(m_InitialState == InitialState.Active);
                    break;
            }
        }
    }
}