using System;
using System.Collections.Generic;
using Windows.UI.Xaml.Data;
using System.Windows.Input;

namespace C1CollectionView
{
    public class ViewModel
    {
        C1.Xaml.C1CollectionView _view;
        ICommand _cmdAdd, _cmdInsert, _cmdRemove, _cmdRefresh;

        /// <summary>
        /// Initializes a new instance of a <see cref="ViewModel"/>.
        /// </summary>
        public ViewModel()
        {
            // create an observable list of customers
            var list = new System.Collections.ObjectModel.ObservableCollection<Customer>();
            for (int i = 0; i < 1000; i++)
                list.Add(new Customer());

            // create a C1CollectionView from the list 
            // (it supports sorting, filtering, and grouping)
            _view = new C1.Xaml.C1CollectionView(list);

            // sort and group customers by country
            _view.SortDescriptions.Add(new C1.Xaml.SortDescription("Country", C1.Xaml.ListSortDirection.Ascending));
            _view.GroupDescriptions.Add(new C1.Xaml.PropertyGroupDescription("Country"));

            // expose commands
            _cmdAdd = new AddCommand(this, false);
            _cmdInsert = new AddCommand(this, true);
            _cmdRemove = new RemoveCommand(this);
            _cmdRefresh = new RefreshCommand(this);
        }
        /// <summary>
        /// Gets the collection of customers.
        /// </summary>
        public C1.Xaml.IC1CollectionView Customers
        {
            get { return _view; }
        }
        /// <summary>
        /// Gets or sets a value that determines whether customers should be grouped by country.
        /// </summary>
        public bool GroupData
        {
            get { return _view.GroupDescriptions.Count > 0; }
            set
            {
                if (value)
                {
                    _view.GroupDescriptions.Add(new C1.Xaml.PropertyGroupDescription("Country"));
                }
                else
                {
                    _view.GroupDescriptions.Clear();
                }
            }
        }
        /// <summary>
        /// Gets or sets a value that determines whether customers should be filtered.
        /// </summary>
        public bool FilterData
        {
            get { return _view.Filter != null; }
            set
            {
                if (value)
                {
                    _view.Filter = MyFilter;
                }
                else
                {
                    _view.Filter = null;
                }
            }
        }
        bool MyFilter(object obj)
        {
            return ((Customer)obj).Active;
        }
        /// <summary>
        /// Gets a command that appends customers to the list.
        /// </summary>
        public ICommand AddCustomer { get { return _cmdAdd; } }
        /// <summary>
        /// Gets a command that inserts customers at the current position on the list.
        /// </summary>
        public ICommand InsertCustomer { get { return _cmdInsert; } }
        /// <summary>
        /// Gets a command that removes the selected customer from the list.
        /// </summary>
        public ICommand RemoveCustomer { get { return _cmdRemove; } }
        /// <summary>
        /// Gets a command that refreshes the view.
        /// </summary>
        public ICommand Refresh { get { return _cmdRefresh; } }
    }
    public class AddCommand : ICommand
    {
        ViewModel _vm;
        bool _addAtCursor;
        public AddCommand(ViewModel vm, bool addAtCursor)
        {
            _vm = vm;
            _addAtCursor = addAtCursor;
            _vm.Customers.CurrentChanged += (s, e) =>
                {
                    if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty);
                };
        }
        public bool CanExecute(object parameter)
        {
            return _addAtCursor == false || _vm.Customers.CurrentPosition > -1;
        }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter)
        {
            var newCustomer = new Customer();
            if (_addAtCursor)
            {
                var list = _vm.Customers.SourceCollection as System.Collections.IList;
                if (list != null)
                {
                    var index = list.IndexOf(_vm.Customers.CurrentItem);
                    list.Insert(index, newCustomer);
                }
            }
            else
            {
                _vm.Customers.Add(newCustomer);
            }
            _vm.Customers.Refresh();
            _vm.Customers.MoveCurrentTo(newCustomer);
        }
    }
    public class RemoveCommand : ICommand
    {
        ViewModel _vm;
        public RemoveCommand(ViewModel vm)
        {
            _vm = vm;
            _vm.Customers.CurrentChanged += (s, e) =>
            {
                if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty);
            };
        }
        public bool CanExecute(object parameter)
        {
            return _vm.Customers.CurrentPosition > -1;
        }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter)
        {
            var pos = _vm.Customers.CurrentPosition;
            _vm.Customers.Remove(_vm.Customers.CurrentItem);
            _vm.Customers.MoveCurrentToPosition(Math.Min(pos, _vm.Customers.Count - 1));
        }
    }
    public class RefreshCommand : ICommand
    {
        ViewModel _vm;
        public RefreshCommand(ViewModel vm)
        {
            _vm = vm;
        }
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter)
        {
            _vm.Customers.Refresh();
        }
    }
}
