using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Services;
using System.Collections;
using System.Web.UI.WebControls;
using System.Web.UI;

namespace WebApplication1
{
    /// <summary>
    /// Summary description for NorthwindService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class NorthwindService : System.Web.Services.WebService
    {
        [WebMethod]
        public ResultData<Customer> GetCustomers(int startRowIndex, int maximumRows,
            string sortExpression, string filterExpression, string groupExpression)
        {
            return new MyLinqDataSource<Customer>()
            {
                ContextTypeName = "WebApplication1.NorthwindDataContext",
                TableName = "Customers",
                StartRowIndex = startRowIndex,
                MaximumRows = maximumRows,
                SortExpression = sortExpression,
                FilterExpression = filterExpression,
                GroupExpression = groupExpression
            }.GetData();
        }

        [WebMethod]
        public List<object> GetDistinctValues(string fieldName)
        {
            return new MyLinqDataSource<object>()
            {
                ContextTypeName = "WebApplication1.NorthwindDataContext",
                TableName = "Customers",
                Select = fieldName
            }.GetData().Data.Distinct().ToList();
        }
    }

    public class MyLinqDataSource<T> : LinqDataSource
    {
        public int StartRowIndex { get; set; }
        public int MaximumRows { get; set; }
        public string SortExpression { get; set; }
        public string FilterExpression { get; set; }
        public string GroupExpression { get; set; }

        public ResultData<T> GetData()
        {
            var view = (LinqDataSourceView)GetView("DefaultView");
            var args = new DataSourceSelectArguments();

            args.StartRowIndex = StartRowIndex;
            args.MaximumRows = MaximumRows;
            args.RetrieveTotalRowCount = true;

            if (!string.IsNullOrEmpty(SortExpression))
            {
                view.OrderBy = SortExpression;
            } 

            if (!string.IsNullOrEmpty(FilterExpression))
            {
                view.Where = FilterExpression;
            }

			//We are doing client side grouping, so just sort by the group key

			if (!string.IsNullOrEmpty(GroupExpression))
			{
				if (!string.IsNullOrEmpty(SortExpression))
				{
					view.OrderBy += ",";
				}
				view.OrderBy += this.GroupExpression;
			}

            var data = view.Select(args).Leaves<T>().ToList();

            return new ResultData<T>() { Count = args.TotalRowCount, Data = data };
        }
    }

    public class ResultData<T>
    {
        public int Count { get; set; }
        public List<T> Data { get; set; }
    }

    public static class IGroupingExtensions
    {
        public static IEnumerable Leaves(this IEnumerable groups)
        {
            foreach (var group in groups)
            {
                var item = group as IEnumerable;
                if (item != null && item.GetType() != typeof(string))
                {
                    foreach (var i in item.Leaves())
                    {
                        yield return i;
                    }
                }
                else
                {
                    yield return group;
                }
            }
        }

        public static IEnumerable<T> Leaves<T>(this IEnumerable group)
        {
             return group.Leaves().Cast<T>();
        }
    }
}
