using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using RadControlsMvcLoadOnDemand.Models;
using Telerik.Web.UI;

namespace RadControlsMvcLoadOnDemand.Controllers
{
	public class JsonParamFilter : ActionFilterAttribute
	{
		public string Param { get; set; }
		public Type TargetType { get; set; }

		public override void OnActionExecuting(ActionExecutingContext filterContext)
		{
			string contentType = filterContext.HttpContext.Request.ContentType;

			if (string.IsNullOrEmpty(contentType))
				return;

			if (!contentType.Contains("application/json"))
				return;

			string paramValue;
			using (var reader = new StreamReader(filterContext.HttpContext.Request.InputStream))
				paramValue = reader.ReadToEnd();

			var serializer = new JavaScriptSerializer();
			var rawResult = (IDictionary<string, object>) serializer.DeserializeObject(paramValue);
			
			var deserializeMethod = serializer.GetType()
				.GetMethod("ConvertToType")
				.MakeGenericMethod(TargetType);

			filterContext.ActionParameters[Param] = deserializeMethod.Invoke(serializer, new[] {rawResult[Param]});
		}
	}

	[HandleError]
	public class HomeController : Controller
	{
		public ActionResult Index()
		{
			ViewData["Message"] = "Welcome to ASP.NET MVC!";

			return View();
		}

		public ActionResult About()
		{
			return View();
		}

		[JsonParamFilter(Param = "context", TargetType = typeof (RadComboBoxContext))]
		public JsonResult LoadItems(RadComboBoxContext context)
		{
			//The RadComboBoxData object contains all required information for load on demand:
			// - the items 
			// - are there more items in case of paging
			// - status message to be displayed (which is optional)
			RadComboBoxData result = new RadComboBoxData();
			NorthwindDataContext northwind = new NorthwindDataContext();

			//Get all items from the Customers table. This query will not be executed untill the ToArray method is called.
			var allCustomers = from customer in northwind.Customers
			                   orderby customer.ContactName
			                   select new RadComboBoxItemData
			                          	{
			                          		Text = customer.ContactName
			                          	};


			//In case the user typed something - filter the result set
			string text = context.Text;
			if (!String.IsNullOrEmpty(text))
			{
				allCustomers = allCustomers.Where(item => item.Text.StartsWith(text));
			}
			//Perform the paging
			// - first skip the amount of items already populated
			// - take the next 10 items
			int numberOfItems = context.NumberOfItems;
			var customers = allCustomers.Skip(numberOfItems).Take(10);

			//This will execute the database query and return the data as an array of RadComboBoxItemData objects
			result.Items = customers.ToArray();

			int endOffset = numberOfItems + customers.Count();
			int totalCount = allCustomers.Count();

			//Check if all items are populated (this is the last page)
			if (endOffset == totalCount)
				result.EndOfItems = true;

			//Initialize the status message
			result.Message = String.Format("Items <b>1</b>-<b>{0}</b> out of <b>{1}</b>",
			                               endOffset, totalCount);
			//Return the result - make sure it is anonymous object with a single "d" property. This is vital for ASP.NET Ajax
			return Json(new {d = result});
		}

		[JsonParamFilter(Param = "node", TargetType = typeof (RadTreeNodeData))]
		public JsonResult LoadNodes(RadTreeNodeData node)
		{
			NorthwindDataContext northwind = new NorthwindDataContext();

			var nodes = from employee in northwind.Employees
			            where employee.Employee1.LastName == node.Text
			            select new RadTreeNodeData
			                   	{
			                   		Text = employee.LastName,
			                   		ExpandMode =
			                   			employee.Employees.Count > 0 ? TreeNodeExpandMode.WebService : TreeNodeExpandMode.ClientSide
			                   	};

			return Json(new {d = nodes.ToArray()});
		}
	}
}