using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PLCIOPointTool.Services;
using TwinCAT;

namespace PLCIOPointTool.ViewModels;

public partial class StatusBarViewModel : ObservableObject, IDisposable
{
    private readonly IClientService _clientService;

    private bool disposedValue;

    #region ObservableProperty
    [ObservableProperty]
    private string _netID = "192.168.250.10.1.1";

    [ObservableProperty]
    private int _port = 851;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(CanConnect), nameof(CanDisconnect))]
    private bool _isConnected = false;

    [ObservableProperty]
    private string _status = ConnectionState.Disconnected.ToString();

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(ConnectCommand), nameof(DisconnectCommand))]
    private bool _isNotOperating = true;
    #endregion

    public StatusBarViewModel(IClientService clientService)
    {
        _clientService = clientService;
        _clientService.ConnectionStateChanged += OnConnectionStateChanged;
    }

    public bool CanConnect => !IsConnected;

    public bool CanDisconnect => IsConnected;

    [RelayCommand]
    private void Connect()
    {
        IsNotOperating = false;
        Task.Run(async () =>
        {
            await _clientService.ConnectAsync(NetID, Port);
            App.Current.Dispatcher.Invoke(() =>
            {
                IsNotOperating = true;
            });
        });

    }

    [RelayCommand]
    private void Disconnect()
    {
        IsNotOperating = false;
        Task.Run(async () =>
        {
            await _clientService.DisconnectAsync();
            App.Current.Dispatcher.Invoke(() =>
            {
                IsNotOperating = true;
            });
        });
    }

    private void OnConnectionStateChanged(object? sender, ConnectionState e)
    {
        IsConnected = e switch
        {
            ConnectionState.Disconnected => false,
            ConnectionState.Connected => true,
            _ => throw new NotImplementedException()
        };
        Status = e.ToString();
    }

    #region Dispose
    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects)
                _clientService.ConnectionStateChanged -= OnConnectionStateChanged;
            }
            // TODO: free unmanaged resources (unmanaged objects) and override finalizer
            // TODO: set large fields to null
            disposedValue = true;
        }
    }

    // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
    // ~StatusBarViewModel()
    // {
    //     // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
    //     Dispose(disposing: false);
    // }

    public void Dispose()
    {
        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
        Dispose(disposing: true);
        GC.SuppressFinalize(this);
    }
    #endregion
}
