using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Linq;
using qmonlib.ui.Models.General;
using Quadarax.Foundation.Core.QMonitor;
using Quadarax.Foundation.Core.Value;
using ReactiveUI;

namespace qmonlib.ui.ViewModels.Navigator
{
    public class NavSearchViewModel : ReceiverViewModelBase
    {

        #region *** Private Fields ***
        private readonly ObservableCollection<MonGeneral> _allData;
        private readonly ConcurrentDictionary<string,CheckBoxListItem> _instancesCache = new ConcurrentDictionary<string, CheckBoxListItem>();
        private readonly IEqualityComparer<string> _eq = new StringPatternComparer();
        private string? _searchText;
        #endregion

        /// <summary>
        /// Filter pattern expression
        /// </summary>
        public string? SearchText
        {
            get => _searchText;
            set => this.RaiseAndSetIfChanged(ref _searchText, value);
        }

        /// <summary>
        /// List of general metadata (filtered by <see cref="SearchText"/>)
        /// </summary>
        public ObservableCollection<MonItemGeneral> DataFiltered
        {
            get
            {
                var instances = DataInstances;
                var dataInstances = _allData.Where(x =>
                    instances.Any(y =>
                        string.Equals(y.Name, x.InstanceIdentifier, StringComparison.InvariantCultureIgnoreCase) &&
                        y.IsChecked));
                Debug.WriteLine($"*DataFiltered.dataInstances cnt = {dataInstances.Count()}");
                var result = new ObservableCollection<MonItemGeneral>(
                    dataInstances.SelectMany(x => x.Items).Where(x => _eq.Equals(x.Name, SearchText))
                );
                Debug.WriteLine($"*DataFiltered cnt = {result.Count}");
                return result;
            } 
            set => throw new NotSupportedException();
        }

        /// <summary>
        /// List of general metadata source instances
        /// </summary>
        public ObservableCollection<CheckBoxListItem> DataInstances
        {
            get
            {
                var newInstances = _allData.Select(x => x.InstanceIdentifier).Distinct().Select(x => new CheckBoxListItem(x));
                foreach (var newInstance in newInstances)
                {
                    if (_instancesCache.ContainsKey(newInstance.Name))
                        continue;
                    
                    _instancesCache.TryAdd(newInstance.Name, newInstance);
                }

                return new ObservableCollection<CheckBoxListItem>(_instancesCache.Select(x=>x.Value));
            }
            set => throw new NotSupportedException();
        }
        public int DataInstancesCount
        {
            get => DataInstances.Count;
            set => throw new NotSupportedException();
        }

        public int DataInstancesSelectedCount
        {
            get => DataInstances.Count(x => x.IsChecked);
            set => throw new NotSupportedException();
        }

        /// <summary>
        /// Count of general metadata total count (not filtered)
        /// </summary>
        public int DataTotalCount
        {
            get => _allData.SelectMany(x=>x.Items).Count(); 
            set => throw new NotSupportedException();
        }
        /// <summary>
        /// Count of general metadata filtered count (what returns in <see cref="DataFiltered"/>
        /// </summary>
        public int DataFilteredCount
        {
            get => DataFiltered.Count;
            set => throw new NotSupportedException();
        }


        public NavSearchViewModel()
        {
            _allData = new ObservableCollection<MonGeneral>();

            // refresh handling subscriptions
            // SearchText
            this.WhenAnyValue(o => o.SearchText)
                .Subscribe(o => this.RaisePropertyChanged(nameof(DataFiltered)));
            this.WhenAnyValue(o => o.DataFiltered)
                .Subscribe(o => this.RaisePropertyChanged(nameof(DataFilteredCount)));

            // DataInstances
            this.WhenAnyValue(o => o.DataInstances)
                .Subscribe(o => this.RaisePropertyChanged(nameof(DataFiltered)));


            #if MOCKED
            var gen1 = new MonGeneral()
            {
                InstanceIdentifier = "inst1",
            };
            gen1.Items.Add(new MonItemGeneral() { Name = "Fee.Foo.Item1", Caption = "this is item1", ViewType = MonItemGeneral.MonViewType.Item });
            gen1.Items.Add(new MonItemGeneral() { Name = "Fee.Foo.Item2", Caption = "this is item2", ViewType = MonItemGeneral.MonViewType.List });
            gen1.Items.Add(new MonItemGeneral() { Name = "Fee.Foo.Item3", Caption = "this is item3", ViewType = MonItemGeneral.MonViewType.Item });
            var gen2 = new MonGeneral()
            {
                InstanceIdentifier = "inst2",
            };
            gen2.Items.Add(new MonItemGeneral() { Name = "Fee.Frr.Item1", Caption = "this is item1", ViewType = MonItemGeneral.MonViewType.Item });
            gen2.Items.Add(new MonItemGeneral() { Name = "Fee.Frr.Item2", Caption = "this is item2", ViewType = MonItemGeneral.MonViewType.Item });
            gen2.Items.Add(new MonItemGeneral() { Name = "Fee.Frr.Item3", Caption = "this is item3", ViewType = MonItemGeneral.MonViewType.Item });

            _allData.Add(gen1);
            _allData.Add(gen2);
            #endif
        }
    }
}
