using System;
using UnityEngine.Playables;
using UnityEngine.Timeline;
namespace UnityEditor.Timeline
{
    /// 
    /// A context for the Timeline window (RO)
    /// 
    /// 
    /// The SequenceContext represents a state of the Timeline window, and is used to interact with .
    /// 
    public readonly struct SequenceContext : IEquatable
    {
        /// 
        /// The director associated with the Timeline window in the context. (RO)
        /// 
        public PlayableDirector director { get; }
        /// 
        /// The  associated with the Timeline window in the context. (RO)
        /// 
        /// In a SubTimeline context, the clip is the  that hosts the SubTimeline in the parent Timeline.
        /// In the root context, the clip is .
        public TimelineClip clip { get; }
        /// 
        /// Initializes and returns an instance of SequenceContext.
        /// 
        /// The PlayableDirector associated with the context. Must be a valid PlayableDirector reference. 
        /// The TimelineClip reference that controls the sequence. Specify  to specify that the sequence is the root. If non-null, the clip must be part of a valid .
        ///   is null.
        ///  The  is not part of a .
        ///  The  is part of a track but not part of a .
        public SequenceContext(PlayableDirector director, TimelineClip clip)
        {
            if (director == null)
                throw new ArgumentNullException(nameof(director));
            var parentTrack = clip?.GetParentTrack();
            if (clip != null && parentTrack == null)
                throw new ArgumentException("The provided clip must be part of a track", nameof(clip));
            if (clip != null && parentTrack.timelineAsset == null)
                throw new ArgumentException("The provided clip must be part of a Timeline.", nameof(clip));
            this.director = director;
            this.clip = clip;
            m_Valid = true;
        }
        /// 
        /// Assesses the validity of a SequenceContext.
        /// 
        /// To be valid, a SequenceContext must contain a valid PlayableDirector reference.
        ///   if the SequenceContext is valid, otherwise
        public bool IsValid() => m_Valid;
        /// 
        /// Equality operator overload.
        /// 
        /// The first object to compare
        /// The second object to compare
        ///  if operands are equal,  otherwise.
        public static bool operator ==(SequenceContext left, SequenceContext right) => left.Equals(right);
        /// 
        /// Inequality operator overload.
        /// 
        /// The first object to compare
        /// The second object to compare
        ///  if operands are not equal,  otherwise.
        public static bool operator !=(SequenceContext left, SequenceContext right) => !left.Equals(right);
        /// Indicates whether the current object is equal to another object of the same type.
        /// An object to compare with this object.
        /// 
        ///  if the current object is equal to the  parameter; otherwise, .
        public bool Equals(SequenceContext other)
        {
            return Equals(director, other.director) && Equals(clip, other.clip);
        }
        /// Indicates whether the current object is equal to another object of indeterminate type.
        /// An object to compare with this object.
        /// 
        ///  if the current object is equal to the  parameter; otherwise, .
        public override bool Equals(object obj)
        {
            return obj is SequenceContext other && Equals(other);
        }
        /// Hash function for SequenceContext.
        /// 
        /// Hash code for the SequenceContext.
        /// 
        public override int GetHashCode()
        {
            unchecked
            {
                return ((director != null ? director.GetHashCode() : 0) * 397) ^ (clip != null ? clip.GetHashCode() : 0);
            }
        }
        internal static SequenceContext Invalid = new SequenceContext();
        readonly bool m_Valid;
    }
}