using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web.UI.WebControls;
using System.Collections;

namespace WcfService1
{
	// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
	public class Service1 : IService1
	{
		//public string GetData(int value)
		//{
		//    return string.Format("You entered: {0}", value);
		//}

		//public CompositeType GetDataUsingDataContract(CompositeType composite)
		//{
		//    if (composite == null)
		//    {
		//        throw new ArgumentNullException("composite");
		//    }
		//    if (composite.BoolValue)
		//    {
		//        composite.StringValue += "Suffix";
		//    }
		//    return composite;
		//}

		//[OperationContract]
		public ResultData<Customer> GetCustomers(int startRowIndex, int maximumRows,
			string sortExpression, string filterExpression, string groupExpression)
		{
			return new MyLinqDataSource<Customer>()
			{
				ContextTypeName = "WcfService1.NorthwindEntities",
				TableName = "Customers",
				StartRowIndex = startRowIndex,
				MaximumRows = maximumRows,
				SortExpression = sortExpression,
				FilterExpression = filterExpression,
				GroupExpression = groupExpression
			}.GetData();
		}

		//[OperationContract]
		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 System.Web.UI.DataSourceSelectArguments();

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

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

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

			if (!String.IsNullOrEmpty(GroupExpression))
			{
				GroupBy = String.Format("new({0})", GroupExpression);
			}

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

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

	[DataContract]
	public class ResultData<T>
	{
		[DataMember]
		public int Count { get; set; }
		[DataMember]
		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>();
		}
	}
}
