using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using System.Data.Services.Client;
using SilverlightGridServerPagingSortingAndFiltering.ServiceReference1;
using System.Linq.Dynamic;
using System.Windows.Threading;

namespace SilverlightGridServerPagingSortingAndFiltering
{
    public enum FilterFunction
    {
        Contains,
        EqualTo,
        GreaterThan,
        LessThan
    }

    public partial class Page : UserControl
    {
        string sortColumnName = "";
        SortingState sortColumnState = SortingState.None;
        string where, whereObjectQuery = "";
        int recordsToSkip, oldRecordsToSkip = 0;
        int pageSize = 10;

        public Page()
        {
            InitializeComponent();

            ComboBox1.ItemsSource = typeof(FilterFunction).GetFields().Where(fi => fi.IsLiteral).Select(fi => fi.Name);
            ComboBox2.ItemsSource = typeof(Customers).GetProperties().Select(pi => pi.Name);

            ComboBox1.SelectedIndex = 0;
            ComboBox2.SelectedIndex = 1;

            BeginExecute();
        }

        private void BeginExecute()
        {
            DataServiceContext context = new DataServiceContext(new Uri("WebDataService1.svc", UriKind.Relative));

            IQueryable<Customers> query = context.CreateQuery<Customers>("Customers");

            if (!String.IsNullOrEmpty(sortColumnName))
            {
                if (sortColumnState != SortingState.None)
                {
                    query = query.OrderBy(String.Format("{0} {1}", sortColumnName,
                        (sortColumnState == SortingState.Ascending) ? "asc" : "desc"));
                }
            }

            if (!String.IsNullOrEmpty(where))
            {
                query = query.Where(where);
            }

            query = query.Skip(recordsToSkip).Take(pageSize);

            ((DataServiceQuery<Customers>)query).BeginExecute(EndExecute, query);

            context.BeginExecute<int>(new Uri(String.Format("Count?where='{0}'", whereObjectQuery), UriKind.Relative), EndCountExecute, context);
        }

        private void EndExecute(IAsyncResult asyncResult)
        {
            DataServiceQuery<Customers> query = asyncResult.AsyncState as DataServiceQuery<Customers>;
            RadGridView1.ItemsSource = query.EndExecute(asyncResult).ToList();

            Dispatcher.BeginInvoke(() =>
            {
                RadGridView1.ItemsControl.SortingRequested += new EventHandler<SortingRequestedEventArgs>(ItemsControl_SortingRequested);
                if (!String.IsNullOrEmpty(sortColumnName))
                {
                    RadGridView1.Columns[sortColumnName].SortingState = sortColumnState;
                }
            });
        }

        private void EndCountExecute(IAsyncResult asyncResult)
        {
            DataServiceContext context = asyncResult.AsyncState as DataServiceContext;
            int count = context.EndExecute<int>(asyncResult).First();

            ScrollBar1.Maximum = count - 1;
        }

        void ItemsControl_SortingRequested(object sender, Telerik.Windows.Controls.SortingRequestedEventArgs e)
        {
            RadGridView1.ItemsControl.SortingRequested -= new EventHandler<SortingRequestedEventArgs>(ItemsControl_SortingRequested);
            
            if (e.SortOrder == SortingState.None)
            {
                e.SortOrder = SortingState.Ascending;
            }
            else if (e.SortOrder == SortingState.Ascending)
            {
                e.SortOrder = SortingState.Descending;
            }
            else
            {
                e.SortOrder = SortingState.None;
            }

            sortColumnName = e.SortPropertyName;
            sortColumnState = e.SortOrder;

            if (!String.IsNullOrEmpty(sortColumnName))
            {
                RadGridView1.Columns[sortColumnName].SortingState = sortColumnState;
            }

            e.Handled = true;

            BeginExecute();
        }

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            FilterFunction filterFunction = (FilterFunction)Enum.Parse(typeof(FilterFunction), ComboBox1.SelectedItem.ToString(), true);
            string filterValue = TextBox1.Text;
            string fieldName = ComboBox2.SelectedItem.ToString();

            if (!String.IsNullOrEmpty(filterValue))
            {
                if (filterFunction == FilterFunction.Contains)
                {
                    where = String.Format(@"{0}.Contains(""{1}"")", fieldName, filterValue);
                    whereObjectQuery = String.Format(@"it.{0} LIKE ""%{1}%""", fieldName, filterValue);
                }
                else if (filterFunction == FilterFunction.EqualTo)
                {
                    where = String.Format(@"{0} == ""{1}""", fieldName, filterValue);
                    whereObjectQuery = String.Format(@"it.{0} = ""{1}""", fieldName, filterValue);
                }
                else if (filterFunction == FilterFunction.GreaterThan)
                {
                    where = String.Format(@"{0} > ""{1}""", fieldName, filterValue);
                    whereObjectQuery = String.Format(@"it.{0} > ""{1}""", fieldName, filterValue);
                }
                else if (filterFunction == FilterFunction.LessThan)
                {
                    where = String.Format(@"{0} < ""{1}""", fieldName, filterValue);
                    whereObjectQuery = String.Format(@"it.{0} < ""{1}""", fieldName, filterValue);
                }
            }
            else
            {
                where = whereObjectQuery = "";
            }

            recordsToSkip = oldRecordsToSkip = 0;
            ScrollBar1.Value = 0d;

            BeginExecute();
        }

        void ScrollBar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            recordsToSkip = (int)Math.Round(e.NewValue);
            setTimeOut(delegate(object s, EventArgs args) 
            {
                if (recordsToSkip != oldRecordsToSkip)
                {
                    oldRecordsToSkip = recordsToSkip;
                    BeginExecute();
                 }
            }, 1000);
        }

        public void setTimeOut(EventHandler handler, int milliseconds)
        {
            DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, milliseconds);
            dispatcherTimer.Tick += delegate(object sender, EventArgs e)
            { 
                dispatcherTimer.Stop(); 
            };
            dispatcherTimer.Tick += handler;
            dispatcherTimer.Start();
        }
    }
}
