using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using GalaxyBudsClient.Generated.I18N;
using GalaxyBudsClient.Model;
using GalaxyBudsClient.Platform.Model;
using GalaxyBudsClient.Utils.Extensions;
using Keys = GalaxyBudsClient.Platform.Model.Keys;

namespace GalaxyBudsClient.Interface.ViewModels.Dialogs;

public partial class HotkeyEditorDialogViewModel : ViewModelBase
{
    public HotkeyEditorDialogViewModel() : this(null) {}

    public HotkeyEditorDialogViewModel(Hotkey? hotkey)
    {
        hotkey ??= Hotkey.Empty;
            
        ModifierCtrl = hotkey.Modifier.Contains(ModifierKeys.Control);
        ModifierAlt = hotkey.Modifier.Contains(ModifierKeys.Alt);
        ModifierShift = hotkey.Modifier.Contains(ModifierKeys.Shift);
        ModifierWin = hotkey.Modifier.Contains(ModifierKeys.Win);
        Key1 = hotkey.Keys.FirstOrDefault();
        Action = hotkey.Action;
        VerifyAndMakeHotkey();
            
        PropertyChanged += OnPropertyChanged;
    }
        
    [Reactive] private bool _modifierCtrl;
    [Reactive] private bool _modifierAlt;
    [Reactive] private bool _modifierShift;
    [Reactive] private bool _modifierWin;
    [Reactive] private Keys? _key1;
    [Reactive] private Event? _action;
    [Reactive] private string _hotkeyPreview = Strings.HotkeyEditInvalid;
        
    public static IEnumerable<Event> ActionSource =>
        EventExtensions.GetValues().Where(EventDispatcher.CheckDeviceSupport);

    public Hotkey? Hotkey => VerifyAndMakeHotkey();
        
    private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case nameof(ModifierShift):  
            case nameof(ModifierWin):
            case nameof(ModifierAlt):
            case nameof(ModifierCtrl):
            case nameof(Key1):
            case nameof(Action):
                VerifyAndMakeHotkey();
                break;
        }
    }

    private Hotkey? VerifyAndMakeHotkey()
    {
        if (Key1 is null or Keys.None)
        {
            HotkeyPreview = Strings.HotkeyEditInvalid;
            return null;
        }
        if (Action is null or Event.None)
        {
            HotkeyPreview = Strings.HotkeyEditInvalidAction;
            return null;
        }

        var modifier = new List<ModifierKeys>();
        var keys = new List<Keys> { Key1.Value };

        if (ModifierCtrl)
            modifier.Add(ModifierKeys.Control);
        if (ModifierAlt)
            modifier.Add(ModifierKeys.Alt);
        if (ModifierWin)
            modifier.Add(ModifierKeys.Win);
        if (ModifierShift)
            modifier.Add(ModifierKeys.Shift);
                    
        if (modifier.Count < 1)
        {
            HotkeyPreview = Strings.HotkeyEditInvalidMod;
            return null;
        }
            
        HotkeyPreview = keys.AsHotkeyString(modifier);
        return new Hotkey
        {
            Modifier = modifier,
            Keys = keys,
            Action = Action.Value
        };
    }
}
