using System;
using System.Collections.Generic;
using System.Linq;
using DatabaseEditor.BL;
using DatabaseEditor.BL.Attributes;
using DatabaseEditor.BL.Filters.Conditions;
using DatabaseEditor.BL.Filters.Operators;
using DatabaseEditor.BL.Interfaces;
using DatabaseEditor.BL.Models;
using GalaSoft.MvvmLight.CommandWpf;
using GalaSoft.MvvmLight.Ioc;

namespace DatabaseEditor.ViewModels
{
    public class SelectItemViewModel<TListModel> : ViewModelBase
        where TListModel : ItemModelBase
    {
        private readonly IItemsProvider<TListModel> _itemsProvider;
        private List<KeyValuePair<string, Type>> _searchableProperties;

        public SelectItemViewModel()
        {
            _itemsProvider = SimpleIoc.Default.GetInstance<IItemsProvider<TListModel>>(Guid.NewGuid().ToString());
            ItemsCollection = new VirtualizingCollection<TListModel>(_itemsProvider);
        }

        public VirtualizingCollection<TListModel> ItemsCollection { get; set; }

        public string SearchBoxText { get; set; }

        public RelayCommand SearchCommand => new RelayCommand(Search);

        public List<KeyValuePair<string, Type>> SearchableProperties
        {
            get
            {
                if (_searchableProperties == null)
                {
                    _searchableProperties =
                        typeof(TListModel).GetProperties()
                            .Where(property => Attribute.IsDefined(property, typeof(SearchablePropertyAttribute)))
                            .Select(property => new KeyValuePair<string, Type>(property.Name, property.PropertyType))
                            .ToList();
                }
                return _searchableProperties;
            }
        }

        public KeyValuePair<string, Type> SelectedProperty { get; set; }

        private void Search()
        {
            PropertyCondition<TListModel> condition = null;
            if (SelectedProperty.Value == typeof(string))
            {
                condition = new StringCondition<TListModel>(LogicOperator.AND, SelectedProperty.Key,
                    StringOperator.StartsWith, SearchBoxText);
            }
            if (SelectedProperty.Value == typeof(int))
            {
                if (Parser.IsParseable(SearchBoxText, typeof(int)))
                {
                    condition = new IntegerCondition<TListModel>(LogicOperator.AND, SelectedProperty.Key,
                        IntegerOperator.StartsWith, Int32.Parse(SearchBoxText));
                }
            }
            var conditions = new List<PropertyCondition<TListModel>> {condition};
            _itemsProvider.UseConditions(conditions);
            ReloadTable();
        }

        private void ReloadTable()
        {
            ItemsCollection = null; // to deselect item
            ItemsCollection = new VirtualizingCollection<TListModel>(_itemsProvider);
        }
    }
}