using NexusShell.Models;

namespace NexusShell.Services;

public sealed class NexusImageViewerService
{
    private IReadOnlyList<NexusPhotoItem> _items = [];
    private int _currentIndex = -1;

    public event EventHandler? StateChanged;

    public bool IsOpen { get; private set; }
    public bool ShowInfoPanel { get; private set; }
    public NexusImageZoomMode ZoomMode { get; private set; } = NexusImageZoomMode.Fit;
    public NexusPhotoItem? CurrentPhoto => _currentIndex >= 0 && _currentIndex < _items.Count ? _items[_currentIndex] : null;
    public bool CanGoPrevious => IsOpen && _currentIndex > 0;
    public bool CanGoNext => IsOpen && _currentIndex < _items.Count - 1;
    public string PositionLabel => _items.Count == 0 ? "0 / 0" : $"{_currentIndex + 1} / {_items.Count}";
    public string ZoomLabel => ZoomMode switch
    {
        NexusImageZoomMode.ActualSize => "100%",
        NexusImageZoomMode.Fill => "Fill",
        _ => "Fit",
    };

    public void Open(IReadOnlyList<NexusPhotoItem> items, int startIndex)
    {
        if (items.Count == 0)
        {
            return;
        }

        _items = items;
        _currentIndex = Math.Clamp(startIndex, 0, items.Count - 1);
        IsOpen = true;
        ShowInfoPanel = false;
        ZoomMode = NexusImageZoomMode.Fit;
        NotifyChanged();
    }

    public void Close()
    {
        IsOpen = false;
        ShowInfoPanel = false;
        _currentIndex = -1;
        NotifyChanged();
    }

    public void GoPrevious()
    {
        if (!CanGoPrevious)
        {
            return;
        }

        _currentIndex--;
        ZoomMode = NexusImageZoomMode.Fit;
        NotifyChanged();
    }

    public void GoNext()
    {
        if (!CanGoNext)
        {
            return;
        }

        _currentIndex++;
        ZoomMode = NexusImageZoomMode.Fit;
        NotifyChanged();
    }

    public void CycleZoomMode()
    {
        ZoomMode = ZoomMode switch
        {
            NexusImageZoomMode.Fit => NexusImageZoomMode.ActualSize,
            NexusImageZoomMode.ActualSize => NexusImageZoomMode.Fill,
            _ => NexusImageZoomMode.Fit,
        };
        NotifyChanged();
    }

    public void ToggleInfoPanel()
    {
        ShowInfoPanel = !ShowInfoPanel;
        NotifyChanged();
    }

    public void HandleMouseWheel(int delta)
    {
        if (delta > 0)
        {
            ZoomMode = NexusImageZoomMode.ActualSize;
        }
        else if (delta < 0)
        {
            ZoomMode = NexusImageZoomMode.Fit;
        }

        NotifyChanged();
    }

    private void NotifyChanged() => StateChanged?.Invoke(this, EventArgs.Empty);
}
