using FSI.Lib.MVVM;
using Microsoft.Extensions.Logging;
using NLog;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Data;
using System.Windows.Input;

namespace FSI.Lib.Guis.Rdp.Mgt
{
    public class ViewModel : MVVM.ViewModelBase
    {
        readonly IDataProvider _dataProvider;
        private string _search;
        private ICollectionView _collView;

        public ICommand RefreshCommand => new DelegateCommand(RefreshData);
        private ICommand _cmdQuickSearch;
        private ICommand _cmdOpen;

        public Logger _log;

        public ViewModel(IDataProvider dataProvider)
        {
            Datas = new ObservableCollection<Model>();
            _dataProvider = dataProvider;

            _cmdQuickSearch = new RelayCommand<object>(ExecuteQuickSearch, CanExecuteQuickSearch);
            _cmdOpen = new RelayCommand<object>(ExecuteOpen, CanExecuteOpen);

            _log = LogManager.GetCurrentClassLogger();
        }

        public ObservableCollection<Model> Datas { get; }
        public ObservableCollection<Model> FilteredData { get; set; }

        public Model SelectedData { get; set; }

        public IEnumerable<IInterface> InputData { get; set; }

        public string Exe { get; set; }
        public void Load()
        {
            var datas = _dataProvider.Load(InputData);
            Datas.Clear();

            if (datas != null)
            {
                foreach (Model data in datas)
                {
                    Datas.Add(data);
                }
            }

            FilteredData = new ObservableCollection<Model>(Datas);
            _collView = CollectionViewSource.GetDefaultView(FilteredData);
        }

        public string Search
        {
            get => _search;
            set
            {
                _search = value;

                _collView.Filter = e =>
                {
                    var item = (Model)e;

                    return ((item.Plant?.StartsWith(_search, StringComparison.OrdinalIgnoreCase) ?? false)
                                                || (item.SubPlant?.StartsWith(_search, StringComparison.OrdinalIgnoreCase) ?? false)
#if NET472
                                                || (item.Path?.Contains(_search) ?? false)
                                                || (item.DescriptionDtl?.Contains(_search) ?? false)
#elif NET6_0
                                                || (item.Host?.Contains(_search, StringComparison.OrdinalIgnoreCase) ?? false)
                                                || (item.DescriptionDtl?.Contains(_search, StringComparison.OrdinalIgnoreCase) ?? false)
#endif
                                                );
                };

                _collView.Refresh();
                FilteredData = new ObservableCollection<Model>(_collView.OfType<Model>().ToList());
                OnPropertyChanged();
            }
        }

        public void QuickSearch(string search)
        {
            Search = search + " ";
        }

        private void RefreshData(object obj)
        {
            Search = string.Empty;
        }

        private bool CanExecuteQuickSearch(object obj)
        {
            return true;
        }

        private void ExecuteQuickSearch(object obj)
        {
            QuickSearch(obj.ToString());
        }

        public ICommand CmdQuickSearch
        {
            get { return _cmdQuickSearch; }
            set => _cmdQuickSearch = value;
        }

        private bool CanExecuteOpen(object obj)
        {
            if (SelectedData.Host != null)
                return true;
            else
                return false;
        }

        private void ExecuteOpen(object obj)
        {

            Process process = new();
            process.StartInfo.FileName = Environment.ExpandEnvironmentVariables(Exe);
            process.StartInfo.WorkingDirectory =  Path.GetDirectoryName(Environment.ExpandEnvironmentVariables(Exe));
            process.StartInfo.Arguments = "/v:" + SelectedData.Host + " " + "/f";

            try
            {

                process.Start();
                _log.Info("Anwendung \"{0}\" wurde mit den Argumenten \"{1}\" gestartet", Exe, process.StartInfo.Arguments);
            }
            catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 740)
            {
                try
                {
                    process.StartInfo.UseShellExecute = true;
                    process.StartInfo.Verb = "runas";
                    process.Start();
                    _log.Info("Anwendung \"{0}\" wurde mit den Argumenten \"{1}\" als Admin gestartet", Exe, process.StartInfo.Arguments);
                }
                catch (Exception ex2)
                {
                   _log.Info("Anwendung konnte durch folgenden Fehler \"{0}\" nicht gestartet werden.", ex2.Message);
                }
            }

        }

        public ICommand CmdOpen
        {
            get { return _cmdOpen; }
            set => _cmdOpen = value;
        }
    }

    public class DataProvider : IDataProvider
    {
        public IEnumerable<Model> Load(IEnumerable<IInterface> datas)
        {
            var newDatas = new ObservableCollection<Model>();

            foreach (IInterface data in datas)
            {
                Model newData = new();
                
                newData.Plant = data.Plant;
                newData.SubPlant = data.SubPlant;
                newData.Description = data.Description;
                newData.Host = data.Host;

                newDatas.Add(newData);
            }

            newDatas = new ObservableCollection<Model>(newDatas.OrderBy(i => i.DescriptionDtl));
            return newDatas;
        }
    }
}
