using System;
using System.Collections.Generic;
using UnityEditor.Timeline.Actions;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using Object = UnityEngine.Object;
namespace UnityEditor.Timeline
{
    /// 
    /// Provides methods that record the state of a timeline, and its components, prior to modification.
    /// 
    /// 
    /// The methods in this class are not required when adding or deleting tracks, clips, or markers.
    /// Use methods in the UnityEngine.Timeline namespace, such as 
    /// or , to apply the appropriate
    /// Undo calls when using the Editor.
    /// 
    public static class UndoExtensions
    {
        /// 
        /// Records changes to all items contained in an action context.
        /// 
        /// The action context to record into the Undo system.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        public static void RegisterContext(ActionContext context, string undoTitle)
        {
            using (var undo = new UndoScope(undoTitle))
            {
                undo.Add(context.tracks);
                undo.Add(context.clips, true);
                undo.Add(context.markers);
            }
        }
        /// 
        /// Records changes to timeline asset properties.
        /// This method does not record changes to tracks or clips.
        /// 
        /// The timeline asset being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        public static void RegisterTimeline(TimelineAsset asset, string undoTitle)
        {
            using (var undo = new UndoScope(undoTitle))
                undo.AddObject(asset);
        }
        /// 
        /// Records all timeline changes including changes to tracks, clips, and markers.
        /// 
        /// The timeline asset being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        public static void RegisterCompleteTimeline(TimelineAsset asset, string undoTitle)
        {
            if (asset == null)
                return;
            using (var undo = new UndoScope(undoTitle))
            {
                undo.AddObject(asset);
                undo.Add(asset.flattenedTracks);
                foreach (var t in asset.flattenedTracks)
                {
                    undo.Add(t.GetClips(), true);
                    undo.Add(t.GetMarkers());
                }
            }
        }
        /// 
        /// Records changes to tracks and clips but not to markers nor PlayableAssets attached to clips.
        /// 
        /// The timeline track being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        public static void RegisterTrack(TrackAsset asset, string undoTitle)
        {
            using (var undo = new UndoScope(undoTitle))
                undo.AddObject(asset);
        }
        /// 
        /// Records changes to tracks. This includes changes
        /// to clips on these tracks, but not changes to markers nor PlayableAssets attached to clips.
        /// 
        /// The timeline track being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        public static void RegisterTracks(IEnumerable tracks, string undoTitle)
        {
            using (var undo = new UndoScope(undoTitle))
                undo.Add(tracks);
        }
        /// 
        /// Records changes to a clip.
        /// 
        /// The timeline clip being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        /// Set this value to true to record changes to the attached playable asset.
        public static void RegisterClip(TimelineClip clip, string undoTitle, bool includePlayableAsset = true)
        {
            using (var undo = new UndoScope(undoTitle))
            {
                undo.AddClip(clip, includePlayableAsset);
            }
        }
        /// 
        /// Records changes to a PlayableAsset.
        /// 
        /// The PlayableAsset being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        public static void RegisterPlayableAsset(PlayableAsset asset, string undoTitle)
        {
            using (var undo = new UndoScope(undoTitle))
                undo.AddObject(asset);
        }
        /// 
        /// Records changes to clips.
        /// 
        /// The timeline clips being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        /// Set this value to true to also record changes to attached playable assets.
        public static void RegisterClips(IEnumerable clips, string name, bool includePlayableAssets = true)
        {
            using (var undo = new UndoScope(name))
                undo.Add(clips, includePlayableAssets);
        }
        /// 
        /// Records changes to a timeline marker.
        /// 
        /// The timeline marker being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        public static void RegisterMarker(IMarker marker, string undoTitle)
        {
            using (var undo = new UndoScope(undoTitle))
            {
                if (marker is Object o)
                    undo.AddObject(o);
                else if (marker != null)
                    undo.AddObject(marker.parent);
            }
        }
        /// 
        /// Records changes to timeline markers.
        /// 
        /// The timeline markers being modified.
        /// The title of the action that appears in the undo history. For example, this title is shown in the Undo menu.
        public static void RegisterMarkers(IEnumerable markers, string undoTitle)
        {
            using (var undo = new UndoScope(undoTitle))
                undo.Add(markers);
        }
        /// 
        /// This class provides an object which prevents the creation of undos for all Timeline operations. Undos are restored when the object is disposed.
        /// 
        /// 
        /// Use this class to procedurally create or modify TimelineAssets when undos are not needed.
        /// If multiple DisableTimelineUndoScope instances are created, undos are only restored after all instances are disposed.
        ///
        /// It is recommended to use this object within a using scope.
        /// 
        /// 
        /// 
        /// var timelineAsset = new TimelineAsset();
        /// using (new DisableTimelineUndoScope())
        /// {
        ///     //Creates a track without generating an undo
        ///     timelineAsset.CreateTrack();
        /// }
        /// 
        /// 
        internal sealed class DisableTimelineUndoScope : IDisposable
        {
            TimelineUndo.DisableUndoScope m_DisableScope;
            /// 
            /// Creates a new DisableTimelineUndoScope object which prevents undos from being created by Timeline operations.
            /// 
            public DisableTimelineUndoScope()
            {
                m_DisableScope = new TimelineUndo.DisableUndoScope();
            }
            /// 
            /// Disposes the DisableTimelineUndoScope object.
            /// 
            public void Dispose()
            {
                m_DisableScope.Dispose();
            }
        }
    }
}