using System;
using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Mail.WinUI;

namespace Wino.Services;

public class StatePersistenceService : ObservableObject, IStatePersistanceService
{
    public event EventHandler<string?>? StatePropertyChanged;

    private const string OpenPaneLengthKey = nameof(OpenPaneLengthKey);
    private const string MailListPaneLengthKey = nameof(MailListPaneLengthKey);
    private const string AppModeTitleKey = nameof(AppModeTitle);

    private readonly IConfigurationService _configurationService;

    public StatePersistenceService(IConfigurationService configurationService)
    {
        _configurationService = configurationService;

        _openPaneLength = _configurationService.Get(OpenPaneLengthKey, 340d);
        _mailListPaneLength = _configurationService.Get(MailListPaneLengthKey, 420d);
        _appModeTitle = _configurationService.Get(AppModeTitleKey, "Wino Mail");
        _calendarDisplayType = EnsureValidCalendarDisplayType(_configurationService.Get(nameof(CalendarDisplayType), CalendarDisplayType.Week));
        _dayDisplayCount = _configurationService.Get(nameof(DayDisplayCount), 1);

        PropertyChanged += ServicePropertyChanged;
    }

    private void ServicePropertyChanged(object? sender, PropertyChangedEventArgs e) => StatePropertyChanged?.Invoke(this, e?.PropertyName ?? string.Empty);

    private WinoApplicationMode applicationMode = WinoApplicationMode.Mail;

    public WinoApplicationMode ApplicationMode
    {
        get => applicationMode;
        set => SetProperty(ref applicationMode, value);
    }

    private bool isEventDetailsVisible;

    public bool IsEventDetailsVisible
    {
        get => isEventDetailsVisible;
        set
        {
            if (SetProperty(ref isEventDetailsVisible, value))
            {
                IsReaderNarrowed = value;
                IsReadingMail = value;
            }
        }
    }

    private bool isReadingMail;

    public bool IsReadingMail
    {
        get => isReadingMail;
        set => SetProperty(ref isReadingMail, value);
    }

    private bool shouldShiftMailRenderingDesign;

    public bool ShouldShiftMailRenderingDesign
    {
        get { return shouldShiftMailRenderingDesign; }
        set { shouldShiftMailRenderingDesign = value; }
    }

    private bool isReaderNarrowed;

    public bool IsReaderNarrowed
    {
        get => isReaderNarrowed;
        set => SetProperty(ref isReaderNarrowed, value);
    }

    private string coreWindowTitle = string.Empty;

    public string CoreWindowTitle
    {
        get => coreWindowTitle;
        set
        {
            if (SetProperty(ref coreWindowTitle, value))
            {
                UpdateAppCoreWindowTitle();
            }
        }
    }

    private string _appModeTitle;

    public string AppModeTitle
    {
        get => _appModeTitle;
        set
        {
            if (SetProperty(ref _appModeTitle, value))
            {
                _configurationService.Set(AppModeTitleKey, value);
                UpdateAppWindowTitle();
            }
        }
    }

    private double _openPaneLength;
    public double OpenPaneLength
    {
        get => _openPaneLength;
        set
        {
            if (SetProperty(ref _openPaneLength, value))
            {
                _configurationService.Set(OpenPaneLengthKey, value);
            }
        }
    }

    private double _mailListPaneLength;
    public double MailListPaneLength
    {
        get => _mailListPaneLength;
        set
        {
            if (SetProperty(ref _mailListPaneLength, value))
            {
                _configurationService.Set(MailListPaneLengthKey, value);
            }
        }
    }

    private CalendarDisplayType _calendarDisplayType;
    public CalendarDisplayType CalendarDisplayType
    {
        get => _calendarDisplayType;
        set
        {
            var validValue = EnsureValidCalendarDisplayType(value);

            if (SetProperty(ref _calendarDisplayType, validValue))
            {
                _configurationService.Set(nameof(CalendarDisplayType), validValue);
            }
        }
    }

    private int _dayDisplayCount;
    public int DayDisplayCount
    {
        get => _dayDisplayCount;
        set
        {
            if (SetProperty(ref _dayDisplayCount, value))
            {
                _configurationService.Set(nameof(DayDisplayCount), value);
            }
        }
    }

    private void UpdateAppCoreWindowTitle()
    {
        OnPropertyChanged(nameof(CoreWindowTitle));
    }

    private void UpdateAppWindowTitle()
    {
        if (WinoApplication.MainWindow != null)
        {
            WinoApplication.MainWindow.Title = AppModeTitle;
        }
    }

    private static CalendarDisplayType EnsureValidCalendarDisplayType(CalendarDisplayType displayType)
    {
        return Enum.IsDefined(typeof(CalendarDisplayType), displayType)
            ? displayType
            : CalendarDisplayType.Week;
    }
}
