using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Windows;
using System.Windows.Input;
using Microsoft.CSharp.RuntimeBinder;
using Newtonsoft.Json;
using Valg.EVA.Skanning.Configuration;
using Valg.EVA.Skanning.Diagnostics;
using Valg.EVA.Skanning.Resources.Language;
using Valg.EVA.Skanning.Scan.ReadSoftEmulation.ScannerAccess;
using Valg.EVA.Skanning.UserInterfaceElements.Commands;
using Valg.EVA.Skanning.UserInterfaceElements.UserSettings;

namespace Valg.EVA.Skanning.Scan.Startup.SelectScannerModel
{
    public class UnsupportedScannerModel
    {
        public string Name { get; set; }
        public bool IsSelected { get; set; }
        public bool IsConnected { get; set; }
    }
    public class UnsupportedScannerModelSelectorWindowViewModel : INotifyPropertyChanged
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetActiveWindow();

        private readonly IUserSettingsProvider _settingsManager;
        private UnsupportedScannerModel _currentSelection;
        private IReadOnlyCollection<UnsupportedScannerModel> _scannerModelList;

        public UnsupportedScannerModelSelectorWindowViewModel()
        {
            _settingsManager = new UserSettingsProvider(new FileSystem());
            var current = _settingsManager.GetUserSettings().SelectedUnsupportedDriver;
            if (!string.IsNullOrWhiteSpace(current))
            {
                CurrentSelection = ScannerModelList.FirstOrDefault((model) => model.Name == current); 
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public ICommand SetScannerModelCommand => new RelayCommand(SetScannerModel);
        public ICommand ConfigureScanncerCommand => new RelayCommand(ConfigureScanner);

        public bool OkBtnEnabled => !string.IsNullOrEmpty(CurrentSelection?.Name);

        public bool ConfigButtonEnabled => SomethingIsSelected && IsWindowsAdmin;

        private static bool IsWindowsAdmin
        {
            get
            {
                var identity = WindowsIdentity.GetCurrent();
                var principal = new WindowsPrincipal(identity);
                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
        }

        private bool SomethingIsSelected => ScannerModels.Connected.Contains(CurrentSelection?.Name);

        public string TitleText => ScanLanguageString.SelectScanModelTitle;
        public string OkButtonText => ScanLanguageString.SelectScanModelOkButton;
        public string ExitButtonText => ScanLanguageString.Button_Cancel;
        public string ConfigButtonText => ScanLanguageString.ConfigureScanner;
        public string ConfigButtonTooltipText => ScanLanguageString.SelectUnsupportedScanner_ConfigTooltip;

        public Visibility SettingsButtonVisibility => Visibility.Hidden;
        public UnsupportedScannerModel CurrentSelection
        {
            get => _currentSelection;
            set
            {
                _currentSelection = value;
                OnPropertyChanged(nameof(CurrentSelection));
                OnPropertyChanged(nameof(OkBtnEnabled));
                OnPropertyChanged(nameof(ConfigButtonEnabled));
            }
        }

        public void SetScannerModel(object arg)
        {
            var model = (UnsupportedScannerModel)arg;

            EvaSkanningEventSource.Log.ScannerModelSelected(model.Name);
            

            SaveSelection(model.Name);
        }

        public void ConfigureScanner(object arg)
        {
            var model = (UnsupportedScannerModel)arg;
            using (var rpcClient = new RpcClient())
            {
                rpcClient.InitializeScanner(model.Name, ScannerConfig.DefaultIsisConfigFilename);
                rpcClient.ConfigureViaGui(GetActiveWindow());
            }
        }

        public void SaveSelection(string driverDescription)
        {
            UserSettings settings = _settingsManager.GetUserSettings();
            settings.EmulateScanner = false;
            settings.SelectedScannerModel = driverDescription;
            settings.SelectedUnsupportedDriver = driverDescription;
            _settingsManager.SaveUserSettings(settings);
        }

        public IReadOnlyCollection<UnsupportedScannerModel> ScannerModelList
        {
            get
            {
                if (_scannerModelList == null)
                {
                    Mouse.OverrideCursor = Cursors.Wait;
                    try
                    {
                        var installed = ScannerModels.Installed;
                        var connected = ScannerModels.Connected;
                        _scannerModelList = installed
                            
                            .Select(s => new UnsupportedScannerModel() { Name = s, IsConnected = connected.Contains(s) }).ToList();
                    }
                    finally
                    {
                        Mouse.OverrideCursor = null;
                    }
                }
                return _scannerModelList;
            }
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

