using System.Collections.Generic;
using System.Runtime.InteropServices;
using Decal.Interop.Input;

namespace Decal.DecalInput
{
    [ComVisible(true)]
    [Guid("F0A17A04-7F8F-4A17-A41D-8C297A1E929B")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(IInputBufferEvents))]
    [ProgId("DecalInput.InputBuffer")]
    public class InputBufferImpl : IInputBuffer
    {
        private object _tag;
        private readonly List<string> _commands = new List<string>();
        private bool _running;

        public event IInputBufferEvents_BeginEventHandler Begin;
        public event IInputBufferEvents_EndEventHandler End;
        public event IInputBufferEvents_EventEventHandler Event;

        public object Tag
        {
            get => _tag;
            set => _tag = value;
        }

        public void Add(string Command)
        {
            _commands.Add(Command);
        }

        public void Push(string Command)
        {
            _commands.Insert(0, Command);
        }

        public void Pop()
        {
            if (_commands.Count > 0)
                _commands.RemoveAt(_commands.Count - 1);
        }

        public bool CanRun => !_running && InputServiceImpl.Instance?.ActiveBuffer == null;

        public void Run()
        {
            if (!CanRun) return;
            _running = true;

            if (InputServiceImpl.Instance != null)
                InputServiceImpl.Instance.ActiveBuffer = this;

            Begin?.Invoke((InputBuffer)(object)this);
            // Actions would be processed in Render2D tick
        }

        public void Stop()
        {
            _running = false;

            if (InputServiceImpl.Instance?.ActiveBuffer == this)
                InputServiceImpl.Instance.ActiveBuffer = null;

            End?.Invoke((InputBuffer)(object)this);
            _commands.Clear();
        }

        internal void FireEvent(int eventId, object param)
        {
            Event?.Invoke((InputBuffer)(object)this, eventId, param);
        }
    }
}
