using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Autofac;
using Ion.Sdk.DemoApp.Framework;
using Ion.Sdk.Ici;
using Ion.Sdk.Ici.Communication;
using Command = Ion.Sdk.DemoApp.Framework.Command;

namespace Ion.Sdk.DemoApp.Views
{
    /// <summary>
    /// Interaction logic for UploadLicense.xaml
    /// </summary>
    public partial class UploadLicenseDialog : UserControl, IConnectedDialog, IProgressReporter, IDisposable
    {

        private readonly ViewModel viewModel;
        private readonly IMessagingService messagingService;
        public event EventHandler Closed;

        public Command CloseCommand { get; }
        public Command UploadCommand { get; }

        public UploadLicenseDialog(ViewModel viewModel, IMessagingService messagingService)
        {
            this.messagingService = messagingService;

            CloseCommand = Command.Create(parameter => Closed?.Invoke(this, EventArgs.Empty));
            UploadCommand = Command.CreateAsync(UploadLicense);

            InitializeComponent();

            Root.DataContext = this.viewModel = viewModel;
        }

        public void Use(ProgressIndicator progress) => viewModel?.Use(progress);

        public void Dispose()
        {
            viewModel?.Dispose();
        }

        #region -=IConnectedDialog members=-

        string IConnectedDialog.Port
        {
            get => viewModel.Port;
            set => viewModel.Port = value;
        }

        int IConnectedDialog.BaudRate
        {
            get => viewModel.BaudRate;
            set => viewModel.BaudRate = value;
        }

        #endregion

        private async Task UploadLicense(object parameter)
        {
            if (await viewModel.UploadLicense())
            {
                await CloseCommand.Execute(parameter);
                messagingService.Show(new Message { Text = "License successfully uploaded." });
            }
            else
            {
                messagingService.Show(new CriticalMessage { Text = "License failed to upload." });
            }
        }

        #region -=ViewModels=-

        public class ViewModel : BindableObject, IProgressReporter, IDisposable
        {
            private ProgressIndicator progress = new ProgressIndicator();
            private string licenseKey = string.Empty;

            public string Port { get; set; }
            public int BaudRate { get; set; }

            public string LicenseKey
            {
                get => licenseKey;
                set => Set(ref licenseKey, value);
            }

            public async Task<bool> UploadLicense()
            {
                if (string.IsNullOrEmpty(Port))
                    throw new InvalidOperationException("Port not set.");
                if (BaudRate == 0)
                    throw new InvalidOperationException("BaudRate not set.");

                if (string.IsNullOrEmpty(licenseKey)) return false;

                progress.IsBusy = true;
                try
                {
                    using (var instrument = Channel.Serial.Open(Port, BaudRate))
                    {
                        instrument.Use(progress);
                        return await instrument.UploadLicense(licenseKey);
                    }
                }
                finally
                {
                    progress.IsBusy = false;
                }
            }

            public void Use(ProgressIndicator progress)
                => this.progress = progress ?? this.progress;

            public void Dispose()
            {
                progress = null;
            }
        }

        #endregion
    }
}
