using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace FlexGridSamples
{
    public sealed partial class IncrementalLoading : UserControl
    {
        private GeneratorIncrementalLoadingClass<Employee> employees;

        public IncrementalLoading()
        {
            this.InitializeComponent();

            if (employees != null)
            {
                employees.CollectionChanged -= _employees_CollectionChanged;
            }

            employees = new GeneratorIncrementalLoadingClass<Employee>(1000, (count) =>
            {
                return new Employee() { Name = "Name" + count, Organization = "Organization" + count };
            });
            employees.CollectionChanged += _employees_CollectionChanged;

            employeesCVS.Source = employees;
            //fgEmployees.ItemsSource = employees;

            tbCollectionChangeStatus.Text = String.Empty;
        }

        void _employees_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            tbCollectionChangeStatus.Text = String.Format("Collection was changed. Count = {0}", employees.Count);
        }
    }

    // This class implements IncrementalLoadingBase. 
    // To create your own Infinite List, you can create a class like this one that doesn't have 'generator' or 'maxcount', 
    //  and instead downloads items from a live data source in LoadMoreItemsOverrideAsync.
    public class GeneratorIncrementalLoadingClass<T> : IncrementalLoadingBase
    {
        public GeneratorIncrementalLoadingClass(uint maxCount, Func<int, T> generator)
        {
            _generator = generator;
            _maxCount = maxCount;
        }

        protected async override Task<IList<object>> LoadMoreItemsOverrideAsync(System.Threading.CancellationToken c, uint count)
        {
            uint toGenerate = System.Math.Min(count, _maxCount - _count);

            // Wait for work 
            await Task.Delay(10);

            // This code simply generates
            var values = from j in Enumerable.Range((int)_count, (int)toGenerate)
                         select (object)_generator(j);
            _count += toGenerate;

            return values.ToArray();
        }

        protected override bool HasMoreItemsOverride()
        {
            return _count < _maxCount;
        }

        #region State

        Func<int, T> _generator;
        uint _count = 0;
        uint _maxCount;

        #endregion
    }

    // More information on INotifyPropertyChanged can be found @ http://go.microsoft.com/fwlink/?LinkId=254639#change_notification
    // For another way to accomplish this, see SampleDataSource.cs and BindableBase.cs in the Grid Application C# project template.
    public class Employee : INotifyPropertyChanged //Implement INotifiyPropertyChanged interface to subscribe for property change notifications
    {
        private string _name;
        private string _organization;

        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }

        public string Organization
        {
            get { return _organization; }
            set
            {
                _organization = value;
                RaisePropertyChanged("Organization");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}
