// Alyios Automation Studio - Action Models
// Professional-grade automation action definitions

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;

namespace AlyiosAutomation.Models
{
    // Base action interface
    public interface IAutomationAction
    {
        string Id { get; set; }
        string Name { get; set; }
        string Description { get; }
        string Category { get; }
        bool Enabled { get; set; }
        Dictionary<string, object> Properties { get; set; }

        void Execute(AutomationContext context);
        Dictionary<string, object> Serialize();
        void Deserialize(Dictionary<string, object> data);
        IAutomationAction Clone();
        string GetDescription();
    }

    // Automation execution context
    public class AutomationContext
    {
        public Dictionary<string, object> Variables { get; set; }
        public Stack<object> Stack { get; set; }
        public bool ShouldStop { get; set; }
        public string LastError { get; set; }
        public List<string> Log { get; set; }

        public AutomationContext()
        {
            Variables = new Dictionary<string, object>();
            Stack = new Stack<object>();
            Log = new List<string>();
        }

        public void LogAction(string message)
        {
            Log.Add(string.Format("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss"), message));
        }
    }

    // Base action class
    public abstract class AutomationActionBase : IAutomationAction
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public abstract string Description { get; }
        public abstract string Category { get; }
        public bool Enabled { get; set; }
        public Dictionary<string, object> Properties { get; set; }

        protected AutomationActionBase()
        {
            Id = Guid.NewGuid().ToString();
            Enabled = true;
            Properties = new Dictionary<string, object>();
        }

        public abstract void Execute(AutomationContext context);
        public abstract Dictionary<string, object> Serialize();
        public abstract void Deserialize(Dictionary<string, object> data);
        public abstract IAutomationAction Clone();

        public virtual string GetDescription()
        {
            return Description;
        }
    }

    // Click action
    public class ClickAction : AutomationActionBase
    {
        public int X { get; set; }
        public int Y { get; set; }
        public string Button { get; set; }
        public int ClickCount { get; set; }
        public bool RelativeToWindow { get; set; }
        public string WindowTitle { get; set; }

        public override string Category { get { return "Mouse"; } }
        public override string Description
        {
            get
            {
                return string.Format("Click {0} at ({1}, {2}){3}",
                    Button, X, Y,
                    ClickCount > 1 ? string.Format(" x{0}", ClickCount) : "");
            }
        }

        public ClickAction()
        {
            Name = "Click";
            Button = "Left";
            ClickCount = 1;
        }

        public override void Execute(AutomationContext context)
        {
            if (!Enabled) return;
            context.LogAction(Description);
            Core.InputSimulator.Click(X, Y, Button, ClickCount);
        }

        public override Dictionary<string, object> Serialize()
        {
            return new Dictionary<string, object>
            {
                {"type", "click"},
                {"id", Id},
                {"name", Name},
                {"x", X},
                {"y", Y},
                {"button", Button},
                {"clicks", ClickCount},
                {"enabled", Enabled}
            };
        }

        public override void Deserialize(Dictionary<string, object> data)
        {
            if (data.ContainsKey("id")) Id = data["id"].ToString();
            if (data.ContainsKey("name")) Name = data["name"].ToString();
            X = Convert.ToInt32(data["x"]);
            Y = Convert.ToInt32(data["y"]);
            Button = data["button"].ToString();
            ClickCount = Convert.ToInt32(data["clicks"]);
            if (data.ContainsKey("enabled")) Enabled = Convert.ToBoolean(data["enabled"]);
        }

        public override IAutomationAction Clone()
        {
            return new ClickAction
            {
                X = X,
                Y = Y,
                Button = Button,
                ClickCount = ClickCount,
                Name = Name,
                Enabled = Enabled
            };
        }
    }

    // Type text action
    public class TypeTextAction : AutomationActionBase
    {
        public string Text { get; set; }
        public int DelayBetweenKeys { get; set; }

        public override string Category { get { return "Keyboard"; } }
        public override string Description
        {
            get
            {
                string preview = Text != null && Text.Length > 30 ? Text.Substring(0, 27) + "..." : Text;
                return string.Format("Type \"{0}\"", preview);
            }
        }

        public TypeTextAction()
        {
            Name = "Type Text";
            DelayBetweenKeys = 10;
        }

        public override void Execute(AutomationContext context)
        {
            if (!Enabled) return;
            string textToType = ReplaceVariables(Text, context);
            context.LogAction(string.Format("Type \"{0}\"", textToType));
            Core.InputSimulator.TypeText(textToType, DelayBetweenKeys);
        }

        string ReplaceVariables(string text, AutomationContext context)
        {
            if (string.IsNullOrEmpty(text)) return text;

            string result = text;
            foreach (var kvp in context.Variables)
            {
                string placeholder = "{" + kvp.Key + "}";
                if (result.Contains(placeholder))
                {
                    result = result.Replace(placeholder, kvp.Value.ToString());
                }
            }
            return result;
        }

        public override Dictionary<string, object> Serialize()
        {
            return new Dictionary<string, object>
            {
                {"type", "type"},
                {"id", Id},
                {"name", Name},
                {"text", Text},
                {"delay", DelayBetweenKeys},
                {"enabled", Enabled}
            };
        }

        public override void Deserialize(Dictionary<string, object> data)
        {
            if (data.ContainsKey("id")) Id = data["id"].ToString();
            if (data.ContainsKey("name")) Name = data["name"].ToString();
            Text = data["text"].ToString();
            if (data.ContainsKey("delay")) DelayBetweenKeys = Convert.ToInt32(data["delay"]);
            if (data.ContainsKey("enabled")) Enabled = Convert.ToBoolean(data["enabled"]);
        }

        public override IAutomationAction Clone()
        {
            return new TypeTextAction
            {
                Text = Text,
                DelayBetweenKeys = DelayBetweenKeys,
                Name = Name,
                Enabled = Enabled
            };
        }
    }

    // Press key action
    public class PressKeyAction : AutomationActionBase
    {
        public string Key { get; set; }
        public List<string> Modifiers { get; set; }

        public override string Category { get { return "Keyboard"; } }
        public override string Description
        {
            get
            {
                if (Modifiers != null && Modifiers.Count > 0)
                {
                    return string.Format("Press {0}+{1}", string.Join("+", Modifiers), Key);
                }
                return string.Format("Press {0}", Key);
            }
        }

        public PressKeyAction()
        {
            Name = "Press Key";
            Modifiers = new List<string>();
        }

        public override void Execute(AutomationContext context)
        {
            if (!Enabled) return;
            context.LogAction(Description);

            if (Modifiers.Count > 0)
            {
                string combo = string.Join("+", Modifiers) + "+" + Key;
                Core.InputSimulator.SendKeys(combo);
            }
            else
            {
                Core.InputSimulator.PressKey(Key);
            }
        }

        public override Dictionary<string, object> Serialize()
        {
            return new Dictionary<string, object>
            {
                {"type", "presskey"},
                {"id", Id},
                {"name", Name},
                {"key", Key},
                {"modifiers", Modifiers},
                {"enabled", Enabled}
            };
        }

        public override void Deserialize(Dictionary<string, object> data)
        {
            if (data.ContainsKey("id")) Id = data["id"].ToString();
            if (data.ContainsKey("name")) Name = data["name"].ToString();
            Key = data["key"].ToString();
            if (data.ContainsKey("modifiers"))
            {
                Modifiers = new List<string>((string[])data["modifiers"]);
            }
            if (data.ContainsKey("enabled")) Enabled = Convert.ToBoolean(data["enabled"]);
        }

        public override IAutomationAction Clone()
        {
            return new PressKeyAction
            {
                Key = Key,
                Modifiers = new List<string>(Modifiers),
                Name = Name,
                Enabled = Enabled
            };
        }
    }

    // Delay action
    public class DelayAction : AutomationActionBase
    {
        public int Milliseconds { get; set; }

        public override string Category { get { return "Flow"; } }
        public override string Description
        {
            get { return string.Format("Wait {0}ms", Milliseconds); }
        }

        public DelayAction()
        {
            Name = "Delay";
            Milliseconds = 1000;
        }

        public DelayAction(int milliseconds)
        {
            Name = "Delay";
            Milliseconds = milliseconds;
        }

        public override void Execute(AutomationContext context)
        {
            if (!Enabled) return;
            context.LogAction(Description);
            System.Threading.Thread.Sleep(Milliseconds);
        }

        public override Dictionary<string, object> Serialize()
        {
            return new Dictionary<string, object>
            {
                {"type", "delay"},
                {"id", Id},
                {"name", Name},
                {"ms", Milliseconds},
                {"enabled", Enabled}
            };
        }

        public override void Deserialize(Dictionary<string, object> data)
        {
            if (data.ContainsKey("id")) Id = data["id"].ToString();
            if (data.ContainsKey("name")) Name = data["name"].ToString();
            Milliseconds = Convert.ToInt32(data["ms"]);
            if (data.ContainsKey("enabled")) Enabled = Convert.ToBoolean(data["enabled"]);
        }

        public override IAutomationAction Clone()
        {
            return new DelayAction
            {
                Milliseconds = Milliseconds,
                Name = Name,
                Enabled = Enabled
            };
        }
    }

    // Screenshot action
    public class ScreenshotAction : AutomationActionBase
    {
        public string FilePath { get; set; }
        public Rectangle Region { get; set; }
        public bool FullScreen { get; set; }

        public override string Category { get { return "Screen"; } }
        public override string Description
        {
            get { return string.Format("Screenshot to {0}", Path.GetFileName(FilePath)); }
        }

        public ScreenshotAction()
        {
            Name = "Screenshot";
            FullScreen = true;
        }

        public override void Execute(AutomationContext context)
        {
            if (!Enabled) return;
            context.LogAction(Description);
            Core.ScreenCapture.CaptureScreen(FilePath, FullScreen ? Rectangle.Empty : Region);
        }

        public override Dictionary<string, object> Serialize()
        {
            return new Dictionary<string, object>
            {
                {"type", "screenshot"},
                {"id", Id},
                {"name", Name},
                {"path", FilePath},
                {"fullscreen", FullScreen},
                {"enabled", Enabled}
            };
        }

        public override void Deserialize(Dictionary<string, object> data)
        {
            if (data.ContainsKey("id")) Id = data["id"].ToString();
            if (data.ContainsKey("name")) Name = data["name"].ToString();
            FilePath = data["path"].ToString();
            if (data.ContainsKey("fullscreen")) FullScreen = Convert.ToBoolean(data["fullscreen"]);
            if (data.ContainsKey("enabled")) Enabled = Convert.ToBoolean(data["enabled"]);
        }

        public override IAutomationAction Clone()
        {
            return new ScreenshotAction
            {
                FilePath = FilePath,
                FullScreen = FullScreen,
                Region = Region,
                Name = Name,
                Enabled = Enabled
            };
        }
    }

    // Set variable action
    public class SetVariableAction : AutomationActionBase
    {
        public string VariableName { get; set; }
        public string Value { get; set; }

        public override string Category { get { return "Variables"; } }
        public override string Description
        {
            get { return string.Format("Set {0} = {1}", VariableName, Value); }
        }

        public SetVariableAction()
        {
            Name = "Set Variable";
        }

        public override void Execute(AutomationContext context)
        {
            if (!Enabled) return;
            context.LogAction(Description);
            context.Variables[VariableName] = Value;
        }

        public override Dictionary<string, object> Serialize()
        {
            return new Dictionary<string, object>
            {
                {"type", "setvar"},
                {"id", Id},
                {"name", Name},
                {"varname", VariableName},
                {"value", Value},
                {"enabled", Enabled}
            };
        }

        public override void Deserialize(Dictionary<string, object> data)
        {
            if (data.ContainsKey("id")) Id = data["id"].ToString();
            if (data.ContainsKey("name")) Name = data["name"].ToString();
            VariableName = data["varname"].ToString();
            Value = data["value"].ToString();
            if (data.ContainsKey("enabled")) Enabled = Convert.ToBoolean(data["enabled"]);
        }

        public override IAutomationAction Clone()
        {
            return new SetVariableAction
            {
                VariableName = VariableName,
                Value = Value,
                Name = Name,
                Enabled = Enabled
            };
        }
    }

    // Action factory
    public static class ActionFactory
    {
        public static IAutomationAction CreateFromType(string type)
        {
            switch (type.ToLower())
            {
                case "click": return new ClickAction();
                case "type": return new TypeTextAction();
                case "presskey": return new PressKeyAction();
                case "delay": return new DelayAction();
                case "screenshot": return new ScreenshotAction();
                case "setvar": return new SetVariableAction();
                default: return null;
            }
        }

        public static IAutomationAction Deserialize(Dictionary<string, object> data)
        {
            if (!data.ContainsKey("type")) return null;

            var action = CreateFromType(data["type"].ToString());
            if (action != null)
            {
                action.Deserialize(data);
            }
            return action;
        }
    }
}
