using System.Windows;

using Bloxstrap.Integrations;
using Bloxstrap.UI.Elements.ContextMenu;

namespace Bloxstrap.UI
{
    public class NotifyIconWrapper : IDisposable
    {
        // lol who needs properly structured mvvm and xaml when you have the absolute catastrophe that this is

        private bool _disposing = false;

        private readonly System.Windows.Forms.NotifyIcon _notifyIcon;
        private MenuContainer? _menuContainer;
        
        private ActivityWatcher? _activityWatcher;
        private DiscordRichPresence? _richPresenceHandler;

        EventHandler? _alertClickHandler;

        public NotifyIconWrapper()
        {
            App.Logger.WriteLine("NotifyIconWrapper::NotifyIconWrapper", "Initializing notification area icon");

            _notifyIcon = new()
            {
                Icon = Properties.Resources.IconBloxstrap,
                Text = App.ProjectName,
                Visible = true
            };

            _notifyIcon.MouseClick += MouseClickEventHandler;
        }

        #region Handler registers
        public void SetRichPresenceHandler(DiscordRichPresence richPresenceHandler)
        {
            if (_richPresenceHandler is not null)
                return;

            _richPresenceHandler = richPresenceHandler;
        }

        public void SetActivityWatcher(ActivityWatcher activityWatcher)
        {
            if (_activityWatcher is not null)
                return;

            _activityWatcher = activityWatcher;

            if (App.Settings.Prop.ShowServerDetails)
                _activityWatcher.OnGameJoin += (_, _) => Task.Run(OnGameJoin);
        }
        #endregion

        #region Context menu
        public void InitializeContextMenu()
        {
            if (_menuContainer is not null || _disposing)
                return;

            App.Logger.WriteLine("NotifyIconWrapper::InitializeContextMenu", "Initializing context menu");

            _menuContainer = new(_activityWatcher, _richPresenceHandler);
            _menuContainer.ShowDialog();
        }

        public void MouseClickEventHandler(object? sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button != System.Windows.Forms.MouseButtons.Right || _menuContainer is null)
                return;

            _menuContainer.Activate();
            _menuContainer.ContextMenu.IsOpen = true;
        }
        #endregion

        #region Activity handlers
        public async void OnGameJoin()
        {
            string serverLocation = await _activityWatcher!.GetServerLocation();

            ShowAlert(
                $"Connected to {_activityWatcher.ActivityServerType.ToString().ToLower()} server", 
                $"Located at {serverLocation}\nClick for more information", 
                10, 
                (_, _) => _menuContainer?.ShowServerInformationWindow()
            );
        }
        #endregion

        public void ShowAlert(string caption, string message, int duration, EventHandler? clickHandler)
        {
            string id = Guid.NewGuid().ToString()[..8];

            string LOG_IDENT = $"NotifyIconWrapper::ShowAlert.{id}";

            App.Logger.WriteLine(LOG_IDENT, $"Showing alert for {duration} seconds (clickHandler={clickHandler is not null})");
            App.Logger.WriteLine(LOG_IDENT, $"{caption}: {message.Replace("\n", "\\n")}");

            _notifyIcon.BalloonTipTitle = caption;
            _notifyIcon.BalloonTipText = message;

            if (_alertClickHandler is not null)
            {
                App.Logger.WriteLine(LOG_IDENT, "Previous alert still present, erasing click handler");
                _notifyIcon.BalloonTipClicked -= _alertClickHandler;
            }

            _alertClickHandler = clickHandler;
            _notifyIcon.BalloonTipClicked += clickHandler;

            _notifyIcon.ShowBalloonTip(duration);

            Task.Run(async () =>
            {
                await Task.Delay(duration * 1000);
             
                _notifyIcon.BalloonTipClicked -= clickHandler;

                App.Logger.WriteLine(LOG_IDENT, "Duration over, erasing current click handler");

                if (_alertClickHandler == clickHandler)
                    _alertClickHandler = null;
                else
                    App.Logger.WriteLine(LOG_IDENT, "Click handler has been overridden by another alert");
            });
        }

        public void Dispose()
        {
            if (_disposing)
                return;

            _disposing = true;

            App.Logger.WriteLine("NotifyIconWrapper::Dispose", "Disposing NotifyIcon");

            _menuContainer?.Dispatcher.Invoke(_menuContainer.Close);
            _notifyIcon?.Dispose();


            GC.SuppressFinalize(this);
        }
    }
}
