using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

using Bitrix;
using Bitrix.DataLayer;
using Bitrix.DataTypes;
using Bitrix.IBlock;
using Bitrix.Services;
using Bitrix.Services.Text;

public partial class BXCustomTypeIBlockElementReference : BXCustomType
{
	public override string Title
	{
		get
		{
			return GetMessage("Title");
		}
	}

	public override string Description
	{
		get
		{
			return GetMessage("Description");
		}
	}

	public override SqlDbType DbType
	{
		get
		{
			return SqlDbType.Int;
		}
	}


	public override string TypeName
	{
		get
		{
			return "Bitrix.IBlock.ElementId";
		}
	}

	public override Control Settings
	{
		get
		{
			return LoadControl("settings.ascx");
		}
	}

	public override Control Edit
	{
		get
		{
			return LoadControl("edit.ascx");
		}
	}

	public override BXCustomTypePublicView CreatePublicView()
	{
		return new PublicView();
	}

	public override Control GetFilter(BXCustomField field)
	{
		throw new Exception("The method or operation is not implemented.");
	}

	public override Control AdvancedSettings
	{
		get
		{
			throw new Exception("The method or operation is not implemented.");
		}
	}

	public override BXCustomTypePublicEdit CreatePublicEditor()
	{
		return new PublicEditor(this);
	}

	class PublicEditor : BXCustomTypePublicEdit
	{
		private BXCustomType type;
		private BXCustomField field;
		private BXCustomProperty property;
		private List<int> propertyValues;

		private bool required;
		private int iblockId;

		private string[] postValues;

		public PublicEditor(BXCustomType type)
		{
			this.type = type;
		}

		public override void Init(BXCustomField currentField)
		{
			field = currentField;
			if (field == null)
				return;

			BXParamsBag<object> settings = new BXParamsBag<object>(currentField.Settings);
			required = field.Mandatory;
			iblockId = settings.ContainsKey("IBlockId") ? (int)settings["IBlockId"] : 0;
		}

		public override void Load(BXCustomProperty currentProperty)
		{
			if (field == null)
				return;

			property = currentProperty;

			if (property == null || property.Values == null || property.Values.Count < 1)
				return;

			if (field.Multiple)
			{
				propertyValues = new List<int>();
				foreach (object value in property.Values)
				{
					if (value is int)
						propertyValues.Add((int)value);
				}
			}
			else if (property.Value is int)
			{
				propertyValues = new List<int>(1);
				propertyValues.Add((int)property.Value);
			}
		}

		public override string Render(string formFieldName, string uniqueID)
		{
			if (field == null)
				return String.Empty;

			string dropDownStart = "<select name=\"{0}\" id=\"{1}\" class=\"bx-custom-field custom-field-ibelement\" size=\"{2}\"{3}>";
			string dropDownOption = "<option value=\"{0}\"{1}>{2}</option>";
			string dropDownEnd = "</select>";

			BXIBlockElementCollection elements = BXIBlockElement.GetList(
				new BXFilter(
					new BXFilterItem(BXIBlockElement.Fields.IBlock.ID, BXSqlFilterOperators.Equal, iblockId),
					new BXFilterItem(BXIBlockElement.Fields.IBlock.Active, BXSqlFilterOperators.Equal, "Y")
				),
				new BXOrderBy(
					new BXOrderByPair(BXIBlockElement.Fields.Sort, BXOrderByDirection.Asc),
					new BXOrderByPair(BXIBlockElement.Fields.Name, BXOrderByDirection.Asc)
				),
				null,
				null,
				BXTextEncoder.HtmlTextEncoder
			);

			StringBuilder result = new StringBuilder();

			result.AppendFormat(
				dropDownStart,
				HttpUtility.HtmlEncode(formFieldName),
				HttpUtility.HtmlEncode(uniqueID),
				field.Multiple ? 5 : 1,
				field.Multiple ? " multiple=\"multiple\"" : String.Empty
			);

			if (!field.Multiple)
				result.AppendFormat(dropDownOption, 0, String.Empty, HttpUtility.HtmlEncode(BXLoc.GetMessage(type, "ValueNotSet")));

			foreach (BXIBlockElement element in elements)
			{
				result.AppendFormat(
					dropDownOption,
					element.Id,
					propertyValues != null && propertyValues.Contains(element.Id) ? " selected=\"selected\"" : String.Empty,
					element.Name
				);
			}

			result.Append(dropDownEnd);

			return result.ToString();
		}

		protected override bool Validate(string formFieldName, ICollection<string> errors)
		{
			if (field == null)
				return false;

			postValues = HttpContext.Current.Request.Form.GetValues(formFieldName);
			if (postValues == null || postValues.Length < 1)
			{
				if (propertyValues != null)
					propertyValues.Clear();

				if (required)
				{
					errors.Add(String.Format(HttpUtility.HtmlEncode(BXLoc.GetMessage(type, "FieldMustBeFilled")), field.EditFormLabel));
					return false;
				}

				return true;
			}

			if (!field.Multiple)
				postValues = new string[] { postValues[0] };

			bool success = true;
			propertyValues = new List<int>(postValues.Length);
			foreach (string value in postValues)
			{
				int elementId;
				if (!int.TryParse(value, out elementId))
				{
					success = false;
					break;
				}

				if (elementId < 1)
					continue;

				BXIBlockElementCollection element = BXIBlockElement.GetList(
					new BXFilter(
						new BXFilterItem(BXIBlockElement.Fields.IBlock.ID, BXSqlFilterOperators.Equal, iblockId),
						new BXFilterItem(BXIBlockElement.Fields.Active, BXSqlFilterOperators.Equal, "Y"),
						new BXFilterItem(BXIBlockElement.Fields.ID, BXSqlFilterOperators.Equal, elementId)
					),
					null
				);

				if (element == null || element.Count != 1)
				{
					success = false;
					break;
				}

				propertyValues.Add(elementId);
			}

			if (!success)
				errors.Add(String.Format(HttpUtility.HtmlEncode(BXLoc.GetMessage(type, "IncorrectValue")), field.EditFormLabel));
			else if (required && propertyValues.Count < 1)
			{
				errors.Add(String.Format(HttpUtility.HtmlEncode(BXLoc.GetMessage(type, "FieldMustBeFilled")), field.EditFormLabel));
				success = false;
			}

			return success;
		}

		protected override void Save(string formFieldName, BXCustomPropertyCollection storage)
		{
			if (field == null)
				return;

			property = new BXCustomProperty(field.Name, field.Id, type.DbType, field.Multiple, propertyValues);
			storage[field.Name] = property;
		}
	}
	class PublicView : BXCustomTypePublicView
	{
		private Dictionary<int, BXIBlockElement> elements;
		private Dictionary<int, BXIBlockElement> BuildElements()
		{
			Dictionary<int, BXIBlockElement> elements = new Dictionary<int, BXIBlockElement>();
			BXFilter filter = new BXFilter();

			if (property.IsMultiple)
				filter.Add(new BXFilterItem(BXIBlockElement.Fields.ID, BXSqlFilterOperators.In, property.Values));
			else
				filter.Add(new BXFilterItem(BXIBlockElement.Fields.ID, BXSqlFilterOperators.Equal, property.Value));

			if (field != null)
			{
				int iblockId = field.Settings.GetInt("IBlockId");
				if (iblockId > 0)
					filter.Add(new BXFilterItem(BXIBlockElement.Fields.IBlock.ID, BXSqlFilterOperators.Equal, iblockId));
			}

			BXIBlockElementCollection elementCollection = BXIBlockElement.GetList(
				filter,
				new BXOrderBy(new BXOrderByPair(BXIBlockElement.Fields.ID, BXOrderByDirection.Asc)),
				null,
				null,
				BXTextEncoder.EmptyTextEncoder
			);

			foreach (BXIBlockElement e in elementCollection)
				elements[e.Id] = e;

			return elements;
		}

		public override string GetHtml(string uniqueId, string separatorHtml)
		{
			if (property == null || property.Values.Count == 0)
				return string.Empty;

			elements = elements ?? BuildElements();

			StringBuilder s = new StringBuilder();
			foreach (object value in property.Values)
			{
				if (value == null)
					continue;

				BXIBlockElement e;
				if (!elements.TryGetValue((int)value, out e))
					continue;

				if (s.Length > 0)
					s.Append(separatorHtml);

				s.Append(HttpUtility.HtmlEncode(e.Name ?? ""));

			}
			return s.ToString();
		}
		public override void Render(string uniqueId, string separatorHtml, HtmlTextWriter writer)
		{
			if (property == null || property.Values.Count == 0)
				return;

			elements = elements ?? BuildElements();

			bool separate = false;
			foreach (object value in property.Values)
			{
				if (value == null)
					continue;

				BXIBlockElement e;
				if (!elements.TryGetValue((int)value, out e))
					continue;

				if (separate)
					writer.Write(separatorHtml);
				else
					separate = true;

				writer.WriteEncodedText(e.Name);
			}
		}
		public override bool IsEmpty
		{
			get
			{
				if (property == null || property.Values.Count == 0)
					return true;

				elements = elements ?? BuildElements();

				foreach (object value in property.Values)
				{
					if (value == null)
						continue;

					if (elements.ContainsKey((int)value))
						return false;
				}
				return true;
			}
		}
	}
}
