// ============================================================================
// mb_clouseau - Visualizer Registry
// Uncovering clues with MusicBee Clouseau
//
// Tracks visualizer state, available visualizers, and state changes
// ============================================================================

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using MusicBeePlugin.Clouseau.Core;

namespace MusicBeePlugin.Clouseau.Introspection
{
    /// <summary>
    /// Tracks visualizer state and changes.
    /// </summary>
    public class VisualizerRegistry : IDisposable
    {
        private VisualizerState _currentState;
        private readonly ConcurrentQueue<VisualizerChange> _changeHistory;
        private readonly object _stateLock = new object();
        private const int MaxHistorySize = 100;
        private bool _disposed;

        /// <summary>
        /// Event raised when visualizer state changes.
        /// </summary>
        public event EventHandler<VisualizerChange> StateChanged;

        public VisualizerRegistry()
        {
            _changeHistory = new ConcurrentQueue<VisualizerChange>();
            _currentState = new VisualizerState
            {
                LastUpdated = DateTime.Now,
                AvailableVisualizers = new string[0]
            };
        }

        /// <summary>
        /// Gets the current visualizer state.
        /// </summary>
        public VisualizerState CurrentState
        {
            get
            {
                lock (_stateLock)
                {
                    return _currentState;
                }
            }
        }

        /// <summary>
        /// Gets the count of available visualizers.
        /// </summary>
        public int AvailableCount => _currentState?.AvailableVisualizers?.Length ?? 0;

        /// <summary>
        /// Updates the visualizer state from MusicBee API.
        /// </summary>
        public void UpdateState(string[] availableVisualizers, string defaultVisualizer,
            Plugin.WindowState defaultState, Plugin.WindowState currentState)
        {
            lock (_stateLock)
            {
                var oldState = _currentState;
                _currentState = new VisualizerState
                {
                    AvailableVisualizers = availableVisualizers ?? new string[0],
                    DefaultVisualizer = defaultVisualizer,
                    CurrentVisualizer = null, // Unknown from this API
                    DefaultWindowState = defaultState,
                    CurrentWindowState = currentState,
                    LastUpdated = DateTime.Now
                };

                // Check for changes
                if (oldState != null && oldState.CurrentWindowState != currentState)
                {
                    RecordChange(oldState.CurrentVisualizer, _currentState.CurrentVisualizer,
                        oldState.CurrentWindowState, currentState);
                }

                LogManager.Core.Trace($"Visualizer state updated: " +
                    $"{availableVisualizers?.Length ?? 0} available, Default={defaultVisualizer}, " +
                    $"State={currentState}");
            }
        }

        /// <summary>
        /// Records a visualizer show/change operation.
        /// </summary>
        public void RecordVisualizerShown(string visualizerName, Plugin.WindowState state)
        {
            lock (_stateLock)
            {
                var oldVisualizer = _currentState?.CurrentVisualizer;
                var oldState = _currentState?.CurrentWindowState ?? Plugin.WindowState.Off;

                if (_currentState != null)
                {
                    _currentState.CurrentVisualizer = visualizerName;
                    _currentState.CurrentWindowState = state;
                    _currentState.LastUpdated = DateTime.Now;
                }

                if (oldVisualizer != visualizerName || oldState != state)
                {
                    RecordChange(oldVisualizer, visualizerName, oldState, state);
                }

                LogManager.Core.Debug($"Visualizer shown: {visualizerName}, State={state}");
            }
        }

        /// <summary>
        /// Gets recent visualizer changes.
        /// </summary>
        public IReadOnlyList<VisualizerChange> GetChangeHistory(int count = 50)
        {
            var all = _changeHistory.ToArray();
            return all.Skip(Math.Max(0, all.Length - count)).ToList();
        }

        /// <summary>
        /// Gets visualizer registry summary.
        /// </summary>
        public VisualizerRegistrySummary GetSummary()
        {
            var state = CurrentState;
            var changes = _changeHistory.ToArray();

            return new VisualizerRegistrySummary
            {
                AvailableVisualizers = state?.AvailableVisualizers ?? new string[0],
                DefaultVisualizer = state?.DefaultVisualizer,
                CurrentVisualizer = state?.CurrentVisualizer,
                CurrentWindowState = state?.CurrentWindowState ?? Plugin.WindowState.Off,
                TotalStateChanges = changes.Length,
                LastChange = changes.LastOrDefault()
            };
        }

        private void RecordChange(string fromVisualizer, string toVisualizer,
            Plugin.WindowState fromState, Plugin.WindowState toState)
        {
            var change = new VisualizerChange
            {
                Timestamp = DateTime.Now,
                FromVisualizer = fromVisualizer,
                ToVisualizer = toVisualizer,
                FromState = fromState,
                ToState = toState
            };

            _changeHistory.Enqueue(change);
            while (_changeHistory.Count > MaxHistorySize)
            {
                _changeHistory.TryDequeue(out _);
            }

            OnStateChanged(change);
        }

        protected virtual void OnStateChanged(VisualizerChange change)
            => StateChanged?.Invoke(this, change);

        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
            }
        }
    }

    /// <summary>
    /// Represents the current visualizer state.
    /// </summary>
    public class VisualizerState
    {
        public string[] AvailableVisualizers { get; set; }
        public string DefaultVisualizer { get; set; }
        public string CurrentVisualizer { get; set; }
        public Plugin.WindowState DefaultWindowState { get; set; }
        public Plugin.WindowState CurrentWindowState { get; set; }
        public DateTime LastUpdated { get; set; }
    }

    /// <summary>
    /// Represents a visualizer state change.
    /// </summary>
    public class VisualizerChange
    {
        public DateTime Timestamp { get; set; }
        public string FromVisualizer { get; set; }
        public string ToVisualizer { get; set; }
        public Plugin.WindowState FromState { get; set; }
        public Plugin.WindowState ToState { get; set; }

        public bool VisualizerChanged => FromVisualizer != ToVisualizer;
        public bool WindowStateChanged => FromState != ToState;
    }

    /// <summary>
    /// Summary of visualizer registry state.
    /// </summary>
    public class VisualizerRegistrySummary
    {
        public string[] AvailableVisualizers { get; set; }
        public string DefaultVisualizer { get; set; }
        public string CurrentVisualizer { get; set; }
        public Plugin.WindowState CurrentWindowState { get; set; }
        public int TotalStateChanges { get; set; }
        public VisualizerChange LastChange { get; set; }
    }
}
