using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Windows.Input;
using Newtonsoft.Json;
using Prism.Events;
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 ScannerModelSelectorWindowViewModelNyt : INotifyPropertyChanged
    {
        private readonly IUserSettingsProvider _settingsManager;
        
        private ScannerListItem _currentScannerListItem;
        private bool _dontShowSelectScannerModel;
        private readonly EventAggregator _eventAggregator;

        public ScannerModelSelectorWindowViewModelNyt(EventAggregator eventAggregator)
        {
            _eventAggregator = eventAggregator;
            _settingsManager = new UserSettingsProvider(new FileSystem());
            SetPropertyValues();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public ICommand SetScannerModelCommand => new RelayCommand(ApplyScannerListSelection);
        public ICommand SelectUnsupportedScannerCommand => new RelayCommand(SelectUnsupportedScanner);
        public List<ScannerListItem> GetScannerListItems => GetScannerListItemsToPresent();

        public bool OkBtnEnabled => CurrentScannerListItem is ScannerModelItem || CurrentScannerListItem is EmulatorItem || CurrentScannerListItem is UnsupportedModelItem;

        public string SelectScanModelTitleText => ScanLanguageString.SelectScanModelTitle;
        public string SelectScanModelOkButtonText => ScanLanguageString.SelectScanModelOkButton;
        public string SelectScanModelExitButtonText => ScanLanguageString.Exit;
        public string SelectScanModelDontShowThisMessageAgainText => ScanLanguageString.SelectScanModelDontShowThisMessageAgain;
        public string SelectOtherScannerText => ScanLanguageString.SelectScanModelOthers;

        public ScannerListItem CurrentScannerListItem
        {
            get => _currentScannerListItem;
            set
            {
                _currentScannerListItem = value;
                OnPropertyChanged(nameof(CurrentScannerListItem));
                OnPropertyChanged(nameof(OkBtnEnabled));
            }
        }

        public void ApplyScannerListSelection(object arg)
        {
            var model = (ScannerListItem)arg;

            if (model is ScannerModelItem smi)
            {
                EvaSkanningEventSource.Log.ScannerModelSelected(smi.ModelName);
                

            }

            SaveSettings();
        }

        public void SelectUnsupportedScanner(object arg)
        {
            var scannerModelSelectorWindow = new SelectScannerModel.UnsupportedScannerModelSelectorWindow();
            
            _eventAggregator.GetEvent<BeforeShowSubDialogEvent>().Publish(scannerModelSelectorWindow);

            var scannerSelectionIsOk = scannerModelSelectorWindow.ShowDialog().GetValueOrDefault();
            if (scannerSelectionIsOk)
            {
                _eventAggregator.GetEvent<RequestCloseScannerSelectorWindowEvent>().Publish();
            }
            
        }

        public bool DontShowSelectScannerModel
        {
            get => _dontShowSelectScannerModel;
            set
            {
                _dontShowSelectScannerModel = value;
                OnPropertyChanged(nameof(DontShowSelectScannerModel));
            }
        }

        public void SaveSettings()
        {
            var settings = _settingsManager.GetUserSettings();
            settings.ShowSelectScannerModel = !DontShowSelectScannerModel;
            settings.EmulateScanner = _currentScannerListItem is EmulatorItem;
            settings.SelectedScannerModel = _currentScannerListItem is ScannerModelItem smi ? smi.ModelName : "";
            settings.SelectedUnsupportedDriver = _currentScannerListItem is UnsupportedModelItem umi ? umi.DriverName : "";
            _settingsManager.SaveUserSettings(settings);
        }

        private List<ScannerListItem> GetScannerListItemsToPresent()
        {
            var installed = ScannerModels.Installed;
            var supported = ScannerModels.Supported;
            var current = GetCurrentScannerModelFromUserSettings();
            var installedAndSupported = supported.Where(s => installed.Contains(s)).ToArray();

            var listToPresent = new List<ScannerListItem>();
            if (current != null)
            {
                listToPresent.Add(current);
                CurrentScannerListItem = current;
            }

            listToPresent.AddRange(installedAndSupported.Where(s => !s.Equals(current?.ToString()))
                .OrderBy(s => s)
                .Select((s, i) => new ScannerModelItem() { ModelName = s }));
            
            
            listToPresent.Add(new SeparatorItem());
            var emulatorItem = new EmulatorItem();
            listToPresent.Add(emulatorItem);
            if (_settingsManager.GetUserSettings().EmulateScanner)
            {
                CurrentScannerListItem = emulatorItem;
            }

            return listToPresent;
        }

        private ScannerListItem GetCurrentScannerModelFromUserSettings()
        {
            UserSettings settings = _settingsManager.GetUserSettings();
            if (!string.IsNullOrEmpty(settings.SelectedScannerModel))
            {
                return new ScannerModelItem() { ModelName = settings.SelectedScannerModel };
            }
            if (!string.IsNullOrEmpty(settings.SelectedUnsupportedDriver))
            {
                return new UnsupportedModelItem() { DriverName = settings.SelectedUnsupportedDriver }; 
            }
            return null;
        }

        private void SetPropertyValues()
        {
            var settings = _settingsManager.GetUserSettings();
            if (settings.ShowSelectScannerModel)
            {
                DontShowSelectScannerModel = false;
            }
            else
            {
                var model = settings.SelectedScannerModel;
                DontShowSelectScannerModel = ScannerModels.Connected.Contains(model);               
            }
        }

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

