using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
using Windows.ApplicationModel.Resources;
using NixExampleWinUI.ViewModels;
using NixUniversalSDK;
using Microsoft.UI.Xaml.Data;
using NixExampleWinUI.Helpers;

namespace NixExampleWinUI.Views;

public sealed partial class SettingsPage : Page
{
    private static readonly ResourceLoader Loader = ResourceLoader.GetForViewIndependentUse();

    public SettingsViewModel ViewModel
    {
        get;
    }

    public SettingsPage()
    {
        ViewModel = App.GetService<SettingsViewModel>();
        InitializeComponent();
    }

    #region Navigation
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        ViewModel.AddDeviceEvents();        
        base.OnNavigatedTo(e);    
    }
    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        ViewModel.RemoveDeviceEvents();
        base.OnNavigatedFrom(e);
    }
    #endregion

    #region Nix device settings
    private void SetDeviceToggleSwitchesEnabled(bool enabled)
    {
        RgbToggle.IsEnabled = enabled;
        HapticToggle.IsEnabled = enabled;
        TileNormalizationToggle.IsEnabled = enabled;
        TemperatureCompensationToggle.IsEnabled = enabled;
    }

    private async void RgbToggle_Toggled(object sender, RoutedEventArgs e)
    {
        // Ignore this event if the toggle switch already matches the backing value (prevents race condition)
        if (RgbToggle.IsOn == ViewModel.IsRgbEnabled) { return; }

        if (ViewModel.Device is IDeviceCompat device)
        {
            // Prevent other settings from being changed while device comms are active
            SetDeviceToggleSwitchesEnabled(false);

            // Set the device value
            _ = await device.SetRgbFeedbackEnabledAsync(RgbToggle.IsOn);

            // Re-enable device setting toggles
            SetDeviceToggleSwitchesEnabled(true);
        }

        // Ensure that on-screen value is in sync
        ViewModel.SyncRgbSetting();
    }

    private async void HapticToggle_Toggled(object sender, RoutedEventArgs e)
    {
        // Ignore this event if the toggle switch already matches the backing value (prevents race condition)
        if (HapticToggle.IsOn == ViewModel.IsHapticEnabled) { return; }

        if (ViewModel.Device is IDeviceCompat device)
        {
            // Prevent other settings from being changed while device comms are active
            SetDeviceToggleSwitchesEnabled(false);

            // Set the device value
            _ = await device.SetHapticFeedbackEnabledAsync(HapticToggle.IsOn);

            // Re-enable device setting toggles
            SetDeviceToggleSwitchesEnabled(true);
        }

        // Ensure that on-screen value is in sync
        ViewModel.SyncHapticSetting();

    }

    private async void TileNormalizationToggle_Toggled(object sender, RoutedEventArgs e)
    {
        // Ignore this event if the toggle switch already matches the backing value (prevents race condition)
        if (TileNormalizationToggle.IsOn == ViewModel.IsTileEnabled) { return; }

        if (ViewModel.Device is IDeviceCompat device)
        {
            // Prevent other settings from being changed while device comms are active
            SetDeviceToggleSwitchesEnabled(false);

            // Set the device value
            _ = await device.SetFieldCalibrationEnabledAsync(TileNormalizationToggle.IsOn);

            // Re-enable device setting toggles
            SetDeviceToggleSwitchesEnabled(true);
        }

        // Ensure that on-screen value is in sync
        ViewModel.SyncTileSetting();
    }

    private async void TemperatureCompensationToggle_Toggled(object sender, RoutedEventArgs e)
    {
        // Ignore this event if the toggle switch already matches the backing value (prevents race condition)
        if (TemperatureCompensationToggle.IsOn == ViewModel.IsTempCompEnabled) { return; }

        if (ViewModel.Device is IDeviceCompat device)
        {
            // Prevent other settings from being changed while device comms are active
            SetDeviceToggleSwitchesEnabled(false);

            // Set the device value
            _ = await device.SetTemperatureCompensationEnabledAsync(TemperatureCompensationToggle.IsOn);

            // Re-enable device setting toggles
            SetDeviceToggleSwitchesEnabled(true);
        }

        // Ensure that on-screen value is in sync
        ViewModel.SyncTemperatureSetting();
    }

    private async void CalibrateButton_Click(object sender, RoutedEventArgs e)
    {
        var dialog = new CalibrateContentDialog()
        {
            XamlRoot = this.XamlRoot
        };
        _ = await dialog.ShowAsync();
    }

    private async void DeviceDetailsButton_Click(object sender, RoutedEventArgs e)
    {
        if (ViewModel.Device is not null)
        {
            // Create info dialog
            var dialog = new InfoListContentDialog()
            {
                XamlRoot = this.XamlRoot,
                Title = Loader.GetString("TitleDeviceInfo")
            };

            // Override `ItemsSource` in the dialog's ListView, instead of
            // setting the items property directly. This allows the list to
            // update on device property changes (e.g. - battery level)
            var binding = new Binding()
            {
                Source = ViewModel,
                Path = new PropertyPath(nameof(ViewModel.DeviceInfoList)),
                Mode = BindingMode.OneWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
            };
            dialog.InfoListView.SetBinding(ListView.ItemsSourceProperty, binding);
            await dialog.ShowAsync();
        }
    }

    private void DisconnectConfirmButton_Click(object sender, RoutedEventArgs e)
    {
        // Send disconnect command
        ViewModel.Device?.Disconnect();

        // Dismiss the flyout
        if (DisconnectButton.Flyout is Flyout f) { f.Hide(); }
    }
    #endregion

    #region License info
    private async void LicenseInfoButton_Click(object sender, RoutedEventArgs e)
    {
        // Create info dialog
        var dialog = new InfoListContentDialog(items: LicenseManagerHelper.GetLicenseInfoList())
        {
            XamlRoot = this.XamlRoot,
            Title = Loader.GetString("TitleLicenseInfo"),
        };
        await dialog.ShowAsync();
    }

    private async void LicenseChangeButton_Click(object sender, RoutedEventArgs e)
    {
        var dialog = new ActivateLicenseContentDialog()
        {
            XamlRoot = this.XamlRoot
        };
        _ = await dialog.ShowAsync();
    }
    #endregion
}