using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Telerik.Web.UI;

namespace Telerik.Web.Examples.Scheduler.AdvancedFormTemplate
{
	public partial class ResourceControls : UserControl
	{
		private object _selectedValue;
		private string _type;


		protected Appointment Appointment
		{
			get
			{
				SchedulerFormContainer container = (SchedulerFormContainer) BindingContainer;
				return container.Appointment;
			}
		}

		protected RadScheduler Owner
		{
			get
			{
				return Appointment.Owner;
			}
		}


		[Bindable(BindableSupport.Yes, BindingDirection.TwoWay)]
		public object Value
		{
			get
			{
				if (ResourceValue.SelectedValue != "NULL")
				{
					return DeserializeResourceKey(ResourceValue.SelectedValue);
				}
				else
				{
					return null;
				}
			}

			set
			{
				_selectedValue = value;
			}
		}

		[Bindable(BindableSupport.Yes, BindingDirection.OneWay)]
		public string Label
		{
			get
			{
				return ResourceLabelLiteral.Text;
			}

			set
			{
				ResourceLabelLiteral.Text = value;
			}
		}

		[Bindable(BindableSupport.Yes, BindingDirection.OneWay)]
		public string Type
		{
			get
			{
				return _type;
			}

			set
			{
				_type = value;
			}
		}


		protected void Page_Load(object sender, EventArgs e)
		{
			if (ResourceValue.Items.Count == 0)
			{
				PopulateResources();
				MarkSelectedResource();
			}
		}

		/// <summary>
		/// Populates the resource options.
		/// </summary>
		private void PopulateResources()
		{
			foreach (Resource res in GetResources(Type))
			{
				ResourceValue.Items.Add(new ListItem(res.Text, SerializeResourceKey(res.Key)));
			}
		}

		/// <summary>
		/// Marks (selects) the resource currently associated with the appointment.
		/// </summary>
		private void MarkSelectedResource()
		{
			ResourceValue.Items.Insert(0, new ListItem("-", "NULL"));

			Resource res = Appointment.Resources.GetResourceByType(Type);
			if (res != null)
			{
				ResourceValue.SelectedValue = SerializeResourceKey(res.Key);
			}
		}

		/// <summary>
		/// Gets a list of the resources of the specified type.
		/// </summary>
		/// <param name="resType">Type of the resources to search for.</param>
		/// <returns>A list of the resources of the specified type.</returns>
		private IEnumerable<Resource> GetResources(string resType)
		{
			List<Resource> availableResources = new List<Resource>();
			IEnumerable<Resource> resources = Owner.Provider.GetResourcesByType(Owner, resType);

			foreach (Resource res in resources)
			{
				if (IncludeResource(res))
				{
					availableResources.Add(res);
				}
			}

			return availableResources;
		}

		/// <summary>
		/// Returns a boolean value, indicating if a resource should be included in the list.
		/// You can use this method to define your custom filtering logic.
		/// </summary>
		/// <param name="res">The resource to filter.</param>
		/// <returns>A boolean value, indicating if a resource should be included in the list.</returns>
		private bool IncludeResource(Resource res)
		{
			return res.Available || ResourceIsInUse(res);
		}

		/// <summary>
		/// Returns a boolean value, indicating if a resource is already assigned to the appointment.
		/// </summary>
		/// <param name="res">The resource to check.</param>
		/// <returns>A boolean value, indicating if a resource is already assigned to the appointment.</returns>
		private bool ResourceIsInUse(Resource res)
		{
			foreach (Resource appRes in Appointment.Resources)
			{
				if (res == appRes)
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// Serializes a resource key using LosFormatter.
		/// </summary>
		/// <remarks>
		///	The resource keys need to be serialized as they can be arbitrary objects.
		/// </remarks>
		/// <param name="key">The key to serialize.</param>
		/// <returns>The serialized key.</returns>
		private string SerializeResourceKey(object key)
		{
			LosFormatter output = new LosFormatter();
			StringWriter writer = new StringWriter();
			output.Serialize(writer, key);
			return writer.ToString();
		}

		/// <summary>
		/// Deserializes a resource key using LosFormatter.
		/// </summary>
		/// <remarks>
		///	The resource keys need to be serialized as they can be arbitrary objects.
		/// </remarks>
		/// <param name="key">The key to deserialize.</param>
		/// <returns>The deserialized key.</returns>
		private object DeserializeResourceKey(string key)
		{
			LosFormatter input = new LosFormatter();
			return input.Deserialize(key);
		}
	}
}