using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommonFroms
{
    public class UndoRedoManager
    {
        private Stack<Command> cmd_undo_list = new Stack<Command>();
        private Stack<Command> cmd_redo_list = new Stack<Command>();

        public bool CanUndo { get { return cmd_undo_list.Count > 0; } }
        public bool CanRedo { get { return cmd_redo_list.Count > 0; } }
        public int UndoCount { get { return cmd_undo_list.Count; } }
        public int RedoCount { get { return cmd_redo_list.Count; } }


        public Command Execute(Action<object> redo, Action<object> undo, object state = null, string text = null)
        {
            var cmd = new Command(redo, undo, state);
            cmd.Text = text;
            cmd.Execute();
            cmd_undo_list.Push(cmd);
            return cmd;
        }
        public void Undo()
        {
            if (cmd_undo_list.Count > 0)
            {
                var cmd = cmd_undo_list.Pop();
                cmd.UnExecute();
                cmd_redo_list.Push(cmd);
            }
        }
        public void Redo()
        {
            if (cmd_redo_list.Count > 0)
            {
                var cmd = cmd_redo_list.Pop();
                cmd.Execute();
                cmd_undo_list.Push(cmd);
            }
        }
    }

    public class Command
    {
        public readonly object state;
        public readonly Action<object> Redo;
        public readonly Action<object> Undo;
        public string Text;

        internal Command(Action<object> redo, Action<object> undo, object st)
        {
            this.Redo = redo;
            this.Undo = undo;
            this.state = st;
        }
        internal void Execute()
        {
            this.Redo(this.state);
        }
        internal void UnExecute()
        {
            this.Undo(state);
        }
    }
}