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.Components;
using Bitrix.Configuration;
using Bitrix.DataLayer;
using Bitrix.DataTypes;
using Bitrix.IBlock;
using Bitrix.IO;
using Bitrix.Security;
using Bitrix.Services;
using Bitrix.Services.Text;
using Bitrix.UI;
using Bitrix.UI.Popup;

namespace Bitrix.IBlock.Components
{
	public partial class CatalogueElementDetailComponent : BXComponent
	{
		private BXIBlockElement element;
        private BXIBlock currentIBlock;

		public BXIBlockElement Element
		{
			get { return this.element; }
			set { this.element = value; }
		}

		public int ElementId
		{
			get
			{
                object rObj = null;
                if (ComponentCache.TryGetValue("ElementId", out rObj))
                    return (int)rObj;

                int id = Parameters.GetInt("ElementId", 0);
				ComponentCache["ElementId"] = id;
				return id;
			}

            internal set 
            {
                ComponentCache["ElementId"] = value;
            }

		}

		public string ElementCode
		{
			get { return Parameters.Get<string>("ElementCode", String.Empty); }
		}

		public string ElementName
		{
			set { ComponentCache["ElementName"] = value; }
			get
			{
				if (!ComponentCache.ContainsKey("ElementName"))
					return null;
				return ComponentCache.Get<string>("ElementName");
			}
		}

		public BXFile PreviewImage
		{
			get { return ComponentCache.Get("PreviewImage") as BXFile; }
			set { ComponentCache["PreviewImage"] = value; }
		}

		public BXFile DetailImage
		{
			get { return ComponentCache.Get("DetailImage") as BXFile; }
			set { ComponentCache["DetailImage"] = value; }
		}

		public int IBlockId
		{
			get
			{
				return Parameters.Get("IBlockId", 0);
			}
		}

		public List<string> ShowProperties
		{
			get { return Parameters.GetListString("Properties"); }
		}

		public string PropertyKeywordsCode
		{
			get
			{
				return Parameters.Get<string>("PropertyKeywords", "-");
			}
		}

		public string PropertyKeywordsValue
		{
			set { ComponentCache["PropertyKeywords"] = value; }
			get
			{
				if (!ComponentCache.ContainsKey("PropertyKeywords"))
					return null;
				return ComponentCache.Get<string>("PropertyKeywords");
			}
		}

		public string PropertyDescriptionCode
		{
			get
			{
				return Parameters.Get<string>("PropertyDescription", "-");
			}
		}

		public string PropertyDescriptionValue
		{
			set { ComponentCache["PropertyDescription"] = value; }
			get
			{
				if (!ComponentCache.ContainsKey("PropertyDescription"))
					return null;
				return ComponentCache.Get<string>("PropertyDescription");
			}
		}

		private List<ElementDetailProperty> properties;
		public List<ElementDetailProperty> Properties
		{
			get { return properties; }
			set { properties = value; }
		}

		public string IBlockName
		{
			set { ComponentCache["IBlockName"] = value; }
			get
			{
				if (!ComponentCache.ContainsKey("IBlockName"))
					return null;
				return ComponentCache.Get<string>("IBlockName");
			}
		}

		public int IBlockTypeId
		{
			set { ComponentCache["IBlockTypeID"] = value; }
			get { return ComponentCache.Get<int>("IBlockTypeID"); }
		}

		public string IBlockElementName
		{
			set { ComponentCache["IBlockElementName"] = value; }
			get { return ComponentCache.Get<string>("IBlockElementName"); }
		}

		public string iblockElementSectionId
		{
			get { return "IBlockElementMenuSection"; }
		}

		public string iblockElementButtonMenuId
		{
			get { return String.Format("IBlockElementButtonMenu_{0}", IBlockId); }
		}

		public string errorMessage = String.Empty;

		protected void Page_Load(object sender, EventArgs e)
		{
			if (IsCached(((BXPrincipal)Page.User).GetAllRoles(true)))
			{
				SetTemplateCachedData();
				return;
			}

			BXIBlock iblock = null;
			bool badParams = false;

			if (IBlockId <= 0)
			{
				badParams = true;
				errorMessage = GetMessage("EmptyIBlockCode");
			}
			else if (ElementId <= 0 && String.IsNullOrEmpty(ElementCode))
			{
				badParams = true;
				errorMessage = GetMessage("ElementNotFound");
			}
			else
			{
				iblock = BXIBlock.GetById(IBlockId, BXTextEncoder.HtmlTextEncoder);
				if (iblock == null)
				{
					badParams = true;
					errorMessage = GetMessage("WrongIBlockCode");
				}
			}

			BXIBlockElementCollection elementCollection = null;
			if (!badParams)
			{
				IBlockName = iblock.Name;
				IBlockTypeId = iblock.TypeId;
				IBlockElementName = iblock.ElementName;

				BXFilter elementFilter = new BXFilter(
					new BXFilterItem(BXIBlockElement.Fields.Active, BXSqlFilterOperators.Equal, "Y"),
					new BXFilterItem(BXIBlockElement.Fields.CheckPermissions, BXSqlFilterOperators.Equal, "Y"),
					new BXFilterItem(BXIBlockElement.Fields.IBlock.ID, BXSqlFilterOperators.Equal, IBlockId)
					//new BXFilterItem(BXIBlockElement.Fields.Sections.Section.ActiveGlobal, BXSqlFilterOperators.Equal, "Y")
				);

				if (!String.IsNullOrEmpty(ElementCode))
				{
					elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.Code, BXSqlFilterOperators.Equal, ElementCode));

					if (ElementId > 0)
						elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.ID, BXSqlFilterOperators.Equal, ElementId));
				}
				else
					elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.ID, BXSqlFilterOperators.Equal, ElementId));

				elementCollection = BXIBlockElement.GetList(elementFilter, null, null, null, BXTextEncoder.HtmlTextEncoder);
				if (elementCollection == null || elementCollection.Count == 0)
				{
					badParams = true;
					errorMessage = GetMessage("ElementNotFound");
				}
			}

			if (badParams)
			{
				AbortCache();

				ScriptManager ajax = ScriptManager.GetCurrent(Page);
				if (!IsComponentDesignMode && BXConfigurationUtility.ShowMode == BXShowMode.View && (ajax == null || !ajax.IsInAsyncPostBack))
				{
					BXError404Manager.Set404Status(Response);
					BXPublicPage bitrixPage = Page as BXPublicPage;
					if (bitrixPage != null && Parameters.GetBool("SetPageTitle", true) && !String.IsNullOrEmpty(errorMessage))
						bitrixPage.Title = errorMessage;
				}

				IncludeComponentTemplate();
				return;
			}

			element = elementCollection[0];
			ElementId = element.Id;
			ElementName = element.Name;
			PreviewImage = element.PreviewImageId > 0 ? element.PreviewImage : null;
			DetailImage = element.DetailImageId > 0 ? element.DetailImage : null;
            currentIBlock = iblock;

			Dictionary<string, BXCustomField> iblockCustomFields = new Dictionary<string, BXCustomField>(iblock.CustomFields.Count);
			foreach (BXCustomField field in iblock.CustomFields)
				iblockCustomFields[field.CorrectedName] = field;

			//Properties
			List<ElementDetailProperty> elementProperties = new List<ElementDetailProperty>();
			foreach (KeyValuePair<string, BXCustomProperty> elementProperty in element.Properties)
			{
				ElementDetailProperty property = new ElementDetailProperty();
				property.Name = elementProperty.Value.UserLikeName;
				property.Property = elementProperty.Value;

				string correctedName = elementProperty.Value.Name.ToUpper();
				property.Code = correctedName;
				if (iblockCustomFields.ContainsKey(correctedName))
					property.Field = iblockCustomFields[correctedName];

				property.Values = elementProperty.Value.Values;
				property.DisplayValue = GetCustomProperty(property.Property, property.Field, "&nbsp;/&nbsp;");
				elementProperties.Add(property);


				if (string.Equals(PropertyKeywordsCode, elementProperty.Key, StringComparison.InvariantCultureIgnoreCase))
					PropertyKeywordsValue = GetCustomProperty(property.Property, property.Field, ", ");
				
				if (string.Equals(PropertyDescriptionCode, elementProperty.Key, StringComparison.InvariantCultureIgnoreCase))
					PropertyDescriptionValue = GetCustomProperty(property.Property, property.Field, ", ");
			}

			Properties = elementProperties;

			SetTemplateCachedData();
			IncludeComponentTemplate();
		}

		private void SetTemplateCachedData()
		{
			BXPublicPage bitrixPage = Page as BXPublicPage;
			if (bitrixPage != null && !IsComponentDesignMode)
			{
				if (Parameters.Get<bool>("SetPageTitle", true) && ElementName != null)
					bitrixPage.BXTitle = BXTextEncoder.HtmlTextEncoder.Decode(ElementName);

				if (PropertyDescriptionValue != null)
					bitrixPage.Keywords["description"] = PropertyDescriptionValue;

				if (PropertyKeywordsValue != null)
					bitrixPage.Keywords["keywords"] = PropertyKeywordsValue;
			}
		}

		private string GetCustomProperty(BXCustomProperty property, BXCustomField field, string separator)
		{
			BXCustomTypePublicView view = BXCustomTypeManager.GetCustomType(field.CustomTypeId).CreatePublicView();
			view.Init(property, field);
			return view.GetHtml(separator);
		}

		//Создаем секцию и кнопку для выпадающего меню в панели администратора
		public override void CreatePublicPanelMenu(BXPublicPanelMenuSectionList sectionList)
		{
			if (!Parameters.Get<bool>("AddAdminPanelButtons") || Element == null)
				return;

			if (sectionList == null)
				throw new ArgumentNullException("sectionList");

			if (!BXIBlock.IsUserCanOperate(IBlockId, BXIBlock.Operations.IBlockAdminRead) ||
				!BXIBlock.IsUserCanOperate(IBlockId, BXIBlock.Operations.IBlockModifyElements))
				return;

			//Создаем секцию
			BXPublicPanelMenuSection iblockElementSection = sectionList.FindByID(iblockElementSectionId);
			if (iblockElementSection == null)
			{
				BXPublicPanelMenuSectionInfo sectionInfo = new BXPublicPanelMenuSectionInfo(iblockElementSectionId, 100);
				iblockElementSection = new BXPublicPanelMenuSection(sectionInfo);
				sectionList.Add(iblockElementSection);
			}

			//Создаем кнопку
			BXPublicPanelMenu elementEditMenu = iblockElementSection.FindByID(iblockElementButtonMenuId);
			if (elementEditMenu == null)
			{
				elementEditMenu = new BXPublicPanelMenu();
				elementEditMenu.ID = iblockElementButtonMenuId;
				elementEditMenu.BackgroundImagePath = BXPath.Combine(BXComponentManager.GetFolder(Name), "/images/iblock.gif");
				elementEditMenu.Caption = BXTextEncoder.HtmlTextEncoder.Decode(IBlockName);
				elementEditMenu.Hint = BXTextEncoder.HtmlTextEncoder.Decode(IBlockName);
				elementEditMenu.ShowMode = BXShowMode.NonView;
				iblockElementSection.Add(elementEditMenu);
			}
		}

		//Заполняем выпадающее меню пунктами "редактировать элемент" и "добавить элемент"
		public override void PopulatePublicPanelMenu(BXPublicPanelMenuSectionList sectionList)
		{
			if (!Parameters.Get<bool>("AddAdminPanelButtons") || Element == null)
				return;

			if (sectionList == null)
				throw new ArgumentNullException("sectionList");

			if (!BXIBlock.IsUserCanOperate(IBlockId, BXIBlock.Operations.IBlockAdminRead) ||
				!BXIBlock.IsUserCanOperate(IBlockId, BXIBlock.Operations.IBlockModifyElements))
				return;

			BXPublicPanelMenuSection iblockElementSection = sectionList.FindByID(iblockElementSectionId);
			if (iblockElementSection == null)
				return;

			BXPublicPanelMenu elementEditMenu = iblockElementSection.FindByID(iblockElementButtonMenuId);
			if (elementEditMenu == null)
				return;

			if (elementEditMenu.PopupMenu == null)
				elementEditMenu.PopupMenu = new BXPopupMenuV2();

			BXPopupMenuItem[] menuItems = GetMenuItems();
			for (int menuIndex = 0; menuIndex < menuItems.Length; menuIndex++)
			{
				bool itemExists = false;
				foreach (BXPopupMenuBaseItem item in elementEditMenu.PopupMenu.Items)
				{
					if (item.ID == menuItems[menuIndex].ID)
					{
						itemExists = true;
						break;
					}
				}

				if (!itemExists)
					elementEditMenu.PopupMenu.AddItem(menuItems[menuIndex]);
			}
		}

		public BXPopupMenuItem[] GetMenuItems()
		{
			BXPopupMenuItem[] menuItems = new BXPopupMenuItem[2];

			menuItems[0] = new BXPopupMenuItem();
			menuItems[0].BackgroundImagePath = BXPath.Combine(BXComponentManager.GetFolder(Name), "/images/edit_element.gif");
			menuItems[0].ID = String.Format("element_edit_{0}", ElementId);
            menuItems[0].Text = (currentIBlock != null)
                ? BXHtmlTextEncoder.HtmlTextEncoder.Decode(currentIBlock.CaptionsInfo.ChangeElement)
                :String.Format(GetMessageRaw("EditElementMenuItem"), String.IsNullOrEmpty(IBlockElementName) ? GetMessageRaw("IBlockElementName") : BXTextEncoder.HtmlTextEncoder.Decode(IBlockElementName.ToLower()));
			menuItems[0].ClientClickScript =
				String.Format(
					"jsUtils.Redirect(arguments, '{0}?type_id={3}&iblock_id={2}&section_id={4}&id={1}&{5}={6}')",
					VirtualPathUtility.ToAbsolute("~/bitrix/admin/IBlockElementEdit.aspx"),
					ElementId,
					IBlockId,
					IBlockTypeId,
					Element != null && Element.Sections.Count > 0 ? Element.Sections[0].SectionId : 0,
					BXConfigurationUtility.Constants.BackUrl,
					UrlEncode(BXSefUrlManager.CurrentUrl.PathAndQuery)
				);

			menuItems[1] = new BXPopupMenuItem();
            menuItems[1].Text = (currentIBlock!=null) 
                ? BXHtmlTextEncoder.HtmlTextEncoder.Decode(currentIBlock.CaptionsInfo.AddElement) 
                : String.Format(GetMessageRaw("CreateElementMenuItem"), String.IsNullOrEmpty(IBlockElementName) ? GetMessageRaw("IBlockElementName") : BXTextEncoder.HtmlTextEncoder.Decode(IBlockElementName.ToLower()));
			menuItems[1].ID = String.Format("element_new_{0}", IBlockId);
			menuItems[1].BackgroundImagePath = BXPath.Combine(BXComponentManager.GetFolder(Name), "/images/new_element.gif");
			menuItems[1].ClientClickScript =
				String.Format(
					"jsUtils.Redirect(arguments, '{0}?type_id={2}&iblock_id={1}&section_id={3}&{4}={5}')",
					VirtualPathUtility.ToAbsolute("~/bitrix/admin/IBlockElementEdit.aspx"),
					IBlockId,
					IBlockTypeId,
					Element != null && Element.Sections.Count > 0 ? Element.Sections[0].SectionId : 0,
					BXConfigurationUtility.Constants.BackUrl,
					UrlEncode(BXSefUrlManager.CurrentUrl.PathAndQuery)
				);

			return menuItems;
		}

		//Создаем контекстное меню
		public override BXComponentPopupMenuInfo PopupMenuInfo
		{
			get
			{
				BXComponentPopupMenuInfo info = base.PopupMenuInfo;

				if (Element != null && BXIBlock.IsUserCanOperate(IBlockId, BXIBlock.Operations.IBlockAdminRead) &&
					BXIBlock.IsUserCanOperate(IBlockId, BXIBlock.Operations.IBlockModifyElements))
				{
					info.CreateCustomPopupMenuItems = delegate(BXShowMode showMode)
					{
						if (showMode != BXShowMode.View)
							return GetMenuItems();
						else
							return null;
					};
				}
				return info;
			}
		}

		protected override void PreLoadComponentDefinition()
		{
			Title = GetMessageRaw("Title");
			Description = GetMessageRaw("Description");
			Icon = "images/cat_detail.gif";

			Group = new BXComponentGroup("catalogue", GetMessageRaw("Group"), 100, BXComponentGroup.Content);

			ParamsDefinition.Add(BXParametersDefinition.Cache);

			ParamsDefinition.Add(
				"IBlockTypeId",
				new BXParamSingleSelection(
					GetMessageRaw("InfoBlockType"),
					String.Empty,
					BXCategory.Main
				)
			);

			ParamsDefinition.Add(
				"IBlockId",
				new BXParamSingleSelection(
					GetMessageRaw("InfoBlockCode"),
					String.Empty,
					BXCategory.Main
				)
			);

			ParamsDefinition.Add(
				"ElementId",
				new BXParamText(
					GetMessageRaw("ElementID_1"),
					"0",
					BXCategory.Main
				));

			ParamsDefinition.Add(
				"ElementCode",
				new BXParamText(
				GetMessageRaw("ElementCode"),
				String.Empty,
				BXCategory.Main
			));

			ParamsDefinition.Add(
				"Properties",
				new BXParamMultiSelection(
					GetMessageRaw("Properties"),
					"-",
					BXCategory.AdditionalSettings
				));

			ParamsDefinition.Add(
				"PropertyKeywords",
				new BXParamSingleSelection(
					GetMessageRaw("SetPageKeywordsFromProperty"),
					"-",
					BXCategory.AdditionalSettings
				));
			ParamsDefinition.Add(
				"PropertyDescription",
				new BXParamSingleSelection(
					GetMessageRaw("SetPageDescriptionFromProperty"),
					"-",
					BXCategory.AdditionalSettings
				));

			ParamsDefinition.Add(
				"AddAdminPanelButtons",
				new BXParamYesNo(
					GetMessageRaw("AddButtonsForThisComponentToAdminPanel"),
					false,
					BXCategory.AdditionalSettings
				));
			ParamsDefinition.Add(
				"SetPageTitle",
				new BXParamYesNo(
					GetMessageRaw("SetPageTitle"),
					true,
					BXCategory.AdditionalSettings
				));
		}

		protected override void LoadComponentDefinition()
		{
			List<BXParamValue> types = new List<BXParamValue>();
			types.Add(new BXParamValue(GetMessageRaw("SelectIBlockType"), "-"));
			BXIBlockTypeCollection typeCollection = BXIBlockType.GetList(null, new BXOrderBy(new BXOrderByPair(BXIBlockType.Fields.Sort, BXOrderByDirection.Asc)), null, null, BXTextEncoder.EmptyTextEncoder);
			foreach (BXIBlockType t in typeCollection)
				types.Add(new BXParamValue(t.Translations[BXLoc.CurrentLocale].Name, t.Id.ToString()));

			ParamsDefinition["IBlockTypeId"].Values = types;
			ParamsDefinition["IBlockTypeId"].RefreshOnDirty = true;

			BXFilter iblockFilter = new BXFilter();
			if (Parameters.ContainsKey("IBlockTypeId"))
			{
				int typeId;
				int.TryParse(Parameters["IBlockTypeId"], out typeId);
				if (typeId > 0)
					iblockFilter.Add(new BXFilterItem(BXIBlock.Fields.Type.ID, BXSqlFilterOperators.Equal, typeId));
			}
			if (!string.IsNullOrEmpty(DesignerSite))
				iblockFilter.Add(new BXFilterItem(BXIBlock.Fields.Sites.SiteId, BXSqlFilterOperators.Equal, DesignerSite));

			List<BXParamValue> iblocks = new List<BXParamValue>();
			iblocks.Add(new BXParamValue(GetMessageRaw("SelectIBlockID"), "-"));

			BXIBlockCollection iblockCollection = BXIBlock.GetList(iblockFilter, new BXOrderBy(new BXOrderByPair(BXIBlock.Fields.Sort, BXOrderByDirection.Asc)), null, null, BXTextEncoder.EmptyTextEncoder);
			foreach (BXIBlock b in iblockCollection)
				iblocks.Add(new BXParamValue(b.Name, b.Id.ToString()));

			ParamsDefinition["IBlockId"].Values = iblocks;
			ParamsDefinition["IBlockId"].RefreshOnDirty = true;

			int selectedIblockId = 0;
			if (Parameters.ContainsKey("IBlockId"))
				int.TryParse(Parameters["IBlockId"], out selectedIblockId);

			List<BXParamValue> properties = new List<BXParamValue>();
			properties.Add(new BXParamValue(GetMessageRaw("NotSelected"), "-"));
			if (selectedIblockId > 0)
			{
				BXCustomFieldCollection customFields = BXIBlock.GetCustomFields(selectedIblockId);
				foreach (BXCustomField customField in customFields)
					properties.Add(new BXParamValue(BXTextEncoder.HtmlTextEncoder.Decode(customField.EditFormLabel), customField.Name.ToUpper()));
			}

			ParamsDefinition["Properties"].Values = properties;

			ParamsDefinition["PropertyKeywords"].Values = properties;
			ParamsDefinition["PropertyDescription"].Values = properties;
		}

		public class ElementDetailProperty
		{
			BXCustomField field;
			public BXCustomField Field
			{
				set { field = value; }
				get { return field; }
			}

			BXCustomProperty property;
			public BXCustomProperty Property
			{
				set { property = value; }
				get { return property; }
			}

			private string name;
			public string Name
			{
				set { name = value; }
				get { return name; }
			}

			private string code;
			public string Code
			{
				get { return code; }
				set { code = value; }
			}

			private List<object> values;
			public List<object> Values
			{
				get { return values; }
				set { values = value; }
			}

			private string displayValue;
			public string DisplayValue
			{
				get { return displayValue; }
				set { displayValue = value; }
			}
		}
	}

	public partial class CatalogueElementDetailTemplate : BXComponentTemplate<CatalogueElementDetailComponent>
	{
		protected override void Render(HtmlTextWriter writer)
		{
			if (IsComponentDesignMode && Component.Element == null)
				writer.Write(BXLoc.GetMessage(Component, "YouHaveToAdjustTheComponent"));
			else
				base.Render(writer);
		}
	}
}
