using System;
using System.Data;
using System.Configuration;
using System.Collections;
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 Bitrix.UI;
using Bitrix.Components;
using Bitrix.Services;
using Bitrix.IBlock;
using Bitrix.DataLayer;
using Bitrix.Services.Text;
using System.Collections.Generic;
using Bitrix;
using Bitrix.DataTypes;
using Bitrix.Components.Editor;
using Bitrix.Modules;
using Bitrix.Security;
using System.Text;
using Bitrix.IO;
using System.Collections.Specialized;

namespace Bitrix.IBlock.Components
{
	public partial class CatalogueComponent : BXComponent
	{
		public int IBlockId
		{
			get { return Parameters.Get<int>("IBlockId"); }
		}

		public string SectionIdVariable
		{
			get { return Parameters.Get<string>("SectionIdVariable", "section_id"); }
		}

		public string ElementIdVariable
		{
			get { return Parameters.Get<string>("ElementIdVariable", "element_id"); }
		}

		public string PageIdVariable
		{
			get { return Parameters.Get<string>("PageIdVariable", "page"); }
		}

		public string ShowAllVariable
		{
			get { return Parameters.Get<string>("ShowAllVariable", "showall"); }
		}

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

		public string ElementDetailTemplate
		{
			get { return Parameters.Get<string>("ElementDetailTemplate", "/#SectionId#/item-#ElementId#/"); }
		}

		public string ElementListTemplate
		{
			get { return Parameters.Get<string>("ElementListTemplate", "/#SectionId#/"); }
		}

		public string CommonListPageTemplate
		{
			get { return Parameters.Get<string>("CommonListPageTemplate", "/page-#pageId#"); }
		}

		public string CommonListShowAllTemplate
		{
			get { return Parameters.Get<string>("CommonListShowAllTemplate", "/all"); }
		}

		public string SectionListPageTemplate
		{
			get { return Parameters.Get<string>("SectionListPageTemplate", "/#SectionId#/page-#pageId#"); }
		}

		public string SectionListShowAllTemplate
		{
			get { return Parameters.Get<string>("SectionListShowAllTemplate", "/#SectionId#/all"); }
		}

		public string RootSectionTitle
		{
			get { return Parameters.GetString("RootSectionTitle", ""); }
		}

		private string menuItemPermisson = String.Empty;
		public string MenuItemPermisson
		{
			set { menuItemPermisson = value; }
			get { return menuItemPermisson; }
		}

		protected void Page_Load(object sender, EventArgs e)
		{
			string page = "index";
			if (EnableSef)
			{
				BXParamsBag<string> urlToPage = new BXParamsBag<string>();

				urlToPage["index.page"] = CommonListPageTemplate;
				urlToPage["index.all"] = CommonListShowAllTemplate;
				urlToPage["list"] = ElementListTemplate;
				urlToPage["list.page"] = SectionListPageTemplate;
				urlToPage["list.all"] = SectionListShowAllTemplate;
				urlToPage["detail"] = ElementDetailTemplate;

				//string code = MapVariable(SefFolder, urlToPage, ComponentCache, "index");
				string code = BXSefUrlUtility.MapVariable(SefFolder, urlToPage, ComponentCache, "index", null, null);

				int position = code.IndexOf('.');
				if (position > 0)
					page = code.Substring(0, position);
				else
					page = code;

				ParseVariableAliases(ComponentCache);

				if (page == "list" && (ComponentCache.Get<int>("SectionId") > 0 || !String.IsNullOrEmpty(ComponentCache.GetString("SectionCode"))))
				{
					
					ComponentCache["PagingIndexTemplate"] = CombineLink(SefFolder, ElementListTemplate);
					ComponentCache["PagingPageTemplate"] = CombineLink(SefFolder, SectionListPageTemplate);
					ComponentCache["PagingShowAllTemplate"] = CombineLink(SefFolder, SectionListShowAllTemplate);
				}
				else
				{
					ComponentCache["PagingIndexTemplate"] = CombineLink(SefFolder, String.Empty);
					ComponentCache["PagingPageTemplate"] = CombineLink(SefFolder, CommonListPageTemplate);
					ComponentCache["PagingShowAllTemplate"] = CombineLink(SefFolder, CommonListShowAllTemplate);
				}

				ComponentCache["IndexTemplate"] = CombineLink(SefFolder, String.Empty);
				ComponentCache["ShowAll"] = (code == "index.all" || code == "list.all" ? "y" : "n");
				ComponentCache["SectionElementListUrl"] = CombineLink(SefFolder, ElementListTemplate);
				ComponentCache["ElementDetailUrl"] = CombineLink(SefFolder, ElementDetailTemplate);
			}
			else
			{
				int sectionId = 0, elementId = 0;
				if (Request[ElementIdVariable] != null && int.TryParse(Request[ElementIdVariable], out elementId) && elementId > 0)
					page = "detail";
				else if (Request[SectionIdVariable] != null && int.TryParse(Request[SectionIdVariable], out sectionId) && sectionId > 0)
					page = "list";
				else
					page = "index";

				BXParamsBag<string> variableAlias = new BXParamsBag<string>();
				variableAlias["SectionId"] = SectionIdVariable;
				variableAlias["ElementId"] = ElementIdVariable;
				variableAlias["PageId"] = PageIdVariable;
				variableAlias["ShowAll"] = ShowAllVariable;

				MapVariable(variableAlias, ComponentCache);

				string filePath = BXSefUrlManager.CurrentUrl.AbsolutePath;
				if (page == "list")
				{
					ComponentCache["PagingIndexTemplate"] = String.Format("{0}?{1}={2}", filePath, SectionIdVariable, sectionId);
					ComponentCache["PagingPageTemplate"] = String.Format("{0}?{1}={2}&{3}=#PageId#", filePath, SectionIdVariable, sectionId, PageIdVariable);
					ComponentCache["PagingShowAllTemplate"] = String.Format("{0}?{1}={2}&{3}=y", filePath, SectionIdVariable, sectionId, ShowAllVariable);
				}
				else
				{
					ComponentCache["PagingIndexTemplate"] = filePath;
					ComponentCache["PagingPageTemplate"] = String.Format("{0}?{1}=#PageId#", filePath, PageIdVariable);
					ComponentCache["PagingShowAllTemplate"] = String.Format("{0}?{1}=y", filePath, ShowAllVariable);
				}

				ComponentCache["IndexTemplate"] = filePath;
				ComponentCache["SectionElementListUrl"] = String.Format("{0}?{1}=#SectionId#", filePath, SectionIdVariable);
				ComponentCache["ElementDetailUrl"] = String.Format("{0}?{1}=#SectionId#&{2}=#ElementId#", filePath, SectionIdVariable, ElementIdVariable);
			}
			
			if (page == "index" && Parameters.Get<bool>("ShowTopElements", false))
				page = "index_top";

			string rootSectionTitle = RootSectionTitle;
			if (string.IsNullOrEmpty(rootSectionTitle))
				rootSectionTitle = Page.Title;
			ComponentCache["RootSectionTitle"] = rootSectionTitle;

			IncludeComponentTemplate(page);
		}

		public override void ProcessMessage(BXCommand cmd, bool executionContext, string executionVirtualPath)
		{
			#region Search
			if (cmd.Action == "Bitrix.Search.ProvideUrl")
			{
				if (cmd.Parameters.Get<string>("moduleId") != "iblock")
					return;

				if (IBlockId < 0 || cmd.Parameters.Get<int>("itemGroup") != IBlockId)
					return;

				int elementId = cmd.Parameters.Get("itemId", -1);
				if (elementId < 0)
					return;

				BXFilter elementFilter = new BXFilter(
					new BXFilterItem(BXIBlockElement.Fields.Active, BXSqlFilterOperators.Equal, "Y"),
					new BXFilterItem(BXIBlockElement.Fields.IBlock.ID, BXSqlFilterOperators.Equal, IBlockId),
					new BXFilterItem(BXIBlockElement.Fields.ID, BXSqlFilterOperators.Equal, elementId)
				);

				BXIBlockElementCollection element = BXIBlockElement.GetList(elementFilter, null);
				if (element != null && element.Count < 1)
					return;

				BXIBlockElement iblockElement = element[0];
				int replaceSectionId = 0;
				if (iblockElement.Sections.Count != 0)
					replaceSectionId = iblockElement.Sections[0].SectionId;

				string url;
				if (EnableSef)
				{
					string replaceSectionCode = String.Empty;
					if (ElementDetailTemplate.Contains("#SECTION_CODE#") || ElementDetailTemplate.Contains("#SectionCode#"))
					{
						BXIBlockSection elementSection = BXIBlockSection.GetById(replaceSectionId);
						if (elementSection != null)
							replaceSectionCode = elementSection.Code;
					}

					BXParamsBag<object> replaceItems = new BXParamsBag<object>();
					replaceItems.Add("IblockId", iblockElement.IBlockId);
					replaceItems.Add("IBLOCK_ID", iblockElement.IBlockId);
					replaceItems.Add("ELEMENT_ID", iblockElement.Id);
					replaceItems.Add("ElementId", iblockElement.Id);
					replaceItems.Add("ElementCode", iblockElement.Code);
					replaceItems.Add("ELEMENT_CODE", iblockElement.Code);
					replaceItems.Add("SectionId", replaceSectionId);
					replaceItems.Add("SECTION_ID", replaceSectionId);
					replaceItems.Add("SectionCode", replaceSectionCode);
					replaceItems.Add("SECTION_CODE", replaceSectionCode);

					//url = MakeLink(SefFolder, ElementDetailTemplate, replaceItems);
					url = CombineLink(SefFolder, BXSefUrlUtility.MakeLink(ElementDetailTemplate, replaceItems));
				}
				else
				{
					url = String.Format("{0}?{1}={2}&{3}={4}", VirtualPathUtility.ToAbsolute(executionVirtualPath), SectionIdVariable, replaceSectionId, ElementIdVariable, elementId);
				}

				cmd.AddCommandResult("bitrix:catalogue@" + executionVirtualPath, new BXCommandResult(BXCommandResultType.Ok, url));
			}
			#endregion

			if (cmd.Action == "Bitrix.Main.GeneratePublicMenu")
			{
				//return;
				//Совпадает ли тип меню в параметрах компонента с типом, который запрашивает система.
				if (!Parameters.Get("GenerateMenuType", "left").Equals(cmd.Parameters.Get<string>("menuType"), StringComparison.InvariantCultureIgnoreCase))
					return;

				//Генерируем меню только для тех адресов, которые выводит сам компонент.
				if (!EnableSef && !executionVirtualPath.Equals(cmd.Parameters.Get<string>("uriPath"), StringComparison.InvariantCultureIgnoreCase))
					return;
				else if (EnableSef && !cmd.Parameters.Get<string>("uriPath").StartsWith(Bitrix.IO.BXPath.ToVirtualRelativePath(SefFolder.TrimStart('\\', '/')) + "/", StringComparison.InvariantCultureIgnoreCase))
					return;

				if (IBlockId < 0)
					return;

				BXParamsBag<object> request = new BXParamsBag<object>();
				if (EnableSef)
				{
					BXParamsBag<string> urlToPage = new BXParamsBag<string>();
					urlToPage["index.page"] = CommonListPageTemplate;
					urlToPage["index.all"] = CommonListShowAllTemplate;
					urlToPage["list"] = ElementListTemplate;
					urlToPage["list.page"] = SectionListPageTemplate;
					urlToPage["list.all"] = SectionListShowAllTemplate;
					urlToPage["detail"] = ElementDetailTemplate;

					//MapVariable(SefFolder, urlToPage, request, "index", BXUri.ToRelativeUri(cmd.Parameters.Get<string>("uri")));
					Uri url = new Uri(BXUri.ToAbsoluteUri(cmd.Parameters.Get<string>("uri")));
					BXSefUrlUtility.MapVariable(SefFolder, urlToPage, request, "index", url, null);

					ParseVariableAliases(request);
				}
				else
				{
					BXParamsBag<string> variableAlias = new BXParamsBag<string>();
					variableAlias["SectionId"] = SectionIdVariable;
					variableAlias["ElementId"] = ElementIdVariable;
					variableAlias["PageId"] = PageIdVariable;
					variableAlias["ShowAll"] = ShowAllVariable;

					MapVariable(variableAlias, request, BXUri.ToRelativeUri(cmd.Parameters.Get<string>("uri")));
				}

				#region Menu Item Permission
				string permissionCacheKey = "catalogue-" + IBlockId.ToString() + "-menu-permission";
				if ((menuItemPermisson = (string)BXCacheManager.MemoryCache.Get(permissionCacheKey)) == null)
				{
					menuItemPermisson = String.Empty;
					StringBuilder menuItemRoles = new StringBuilder();

					BXRoleCollection iblockRoles = BXRoleManager.GetAllRolesForOperation("IBlockRead", "iblock", IBlockId.ToString());
					foreach (BXRole role in iblockRoles)
					{
						//Если доступно всем
						if (role.RoleName == "Guest")
						{
							menuItemRoles = null;
							break;
						}
						//Если доступно группе User, значит достаточно проверить только для этой группы
						else if (role.RoleName == "User")
						{
							menuItemRoles = null;
							menuItemPermisson = "User";
							break;
						}
						else
						{
							menuItemRoles.Append(role.RoleName);
							menuItemRoles.Append(";");
						}
					}

					if (menuItemRoles != null && menuItemRoles.Length > 0)
						menuItemPermisson = menuItemRoles.ToString();

					BXCacheManager.MemoryCache.Insert(permissionCacheKey, menuItemPermisson);
				}
				#endregion

				int elementId = 0, sectionId = 0;
				string elementCode = String.Empty, sectionCode = String.Empty;

				elementId = request.Get<int>("ElementId", elementId);
				sectionId = request.Get<int>("SectionId", sectionId);
				elementCode = request.Get<string>("ElementCode", elementCode);
				sectionCode = request.Get<string>("SectionCode", sectionCode);

				string parentLevelUri = null;
				List<BXPublicMenuItem> menuList = null;

				//Указан идентификатор или символьный код
				if (elementId > 0 || !String.IsNullOrEmpty(elementCode))
				{
					BXFilter elementFilter = new BXFilter(
						new BXFilterItem(BXIBlockElement.Fields.IBlock.ID, BXSqlFilterOperators.Equal, IBlockId),
						new BXFilterItem(BXIBlockElement.Fields.Active, BXSqlFilterOperators.Equal, "Y")
					);

					if (elementId > 0)
						elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.ID, BXSqlFilterOperators.Equal, elementId));
					if (!String.IsNullOrEmpty(elementCode))
						elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.Code, BXSqlFilterOperators.Equal, elementCode));
					if (sectionId > 0)
						elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.Sections.Section.SectionId, BXSqlFilterOperators.Equal, sectionId));
					if (!String.IsNullOrEmpty(sectionCode))
						elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.Sections.Section.Code, BXSqlFilterOperators.Equal, sectionCode));

					BXIBlockElementCollection element = BXIBlockElement.GetList(elementFilter, null);
					if (element != null && element.Count > 0)
					{
						BXIBlockElement.BXInfoBlockElementSectionCollection sections = element[0].Sections;
						if (sections != null && sections.Count > 0)
						{
							BXParamsBag<object> replaceItems = new BXParamsBag<object>();
							replaceItems["SECTION_ID"] = sections[0].SectionId;
							replaceItems["SectionId"] = replaceItems["SECTION_ID"];
							replaceItems["SECTION_CODE"] = GetSectionCode(sections[0].SectionId);
							replaceItems["SectionCode"] = replaceItems["SECTION_CODE"];

							parentLevelUri = MakeMenuUri(executionVirtualPath, replaceItems); //Меню строится для раздела, к которому привязан элемент
						}
					}
				}

				//Если ничего не указано выводим все дерево
				Dictionary<string, BXPublicMenu.BXLoadMenuCommandParameter> menuTree = new Dictionary<string, BXPublicMenu.BXLoadMenuCommandParameter>();
				if (parentLevelUri == null && menuList == null)
				{
					BXIBlockSectionCollection sectionsList = BXIBlockSection.GetList(
						new BXFilter(
							new BXFilterItem(BXIBlockSection.Fields.Active, BXSqlFilterOperators.Equal, "Y"),
							new BXFilterItem(BXIBlockSection.Fields.ActiveGlobal, BXSqlFilterOperators.Equal, "Y"),
							new BXFilterItem(BXIBlockSection.Fields.IBlock.ID, BXSqlFilterOperators.Equal, IBlockId)
						),
						new BXOrderBy(
							new BXOrderByPair(BXIBlockSection.Fields.LeftMargin, BXOrderByDirection.Asc)
						),
						null,
						null,
						BXTextEncoder.EmptyTextEncoder
					);

					int previousDepthLevel = 1;
					int previousSectionId = 0;
					Dictionary<int, MenuSectionTree> sectionTree = new Dictionary<int, MenuSectionTree>();
					foreach (BXIBlockSection section in sectionsList)
					{
						BXParamsBag<object> replaceItems = new BXParamsBag<object>();
						replaceItems["SECTION_ID"] = section.Id;
						replaceItems["SECTION_CODE"] = section.Code ?? String.Empty;
						replaceItems["SectionId"] = replaceItems["SECTION_ID"];
						replaceItems["SectionCode"] = replaceItems["SECTION_CODE"];

						sectionTree[section.Id] = new MenuSectionTree();
						string url = MakeMenuUri(executionVirtualPath, replaceItems);
						sectionTree[section.Id].url = url;
						sectionTree[section.Id].sectionId = section.SectionId;

						//Если предыдущий раздел не имеет дочерних разделов, то устанавливаем у него parentLevelUrl
						if (previousSectionId > 0 && section.DepthLevel <= previousDepthLevel)
							sectionTree[previousSectionId].parentLevelUrl = sectionTree[sectionTree[previousSectionId].sectionId].url;
						previousDepthLevel = section.DepthLevel;
						previousSectionId = section.Id;

						BXPublicMenuItem menuItem = new BXPublicMenuItem();
						menuItem.Title = section.Name;
						menuItem.Links.Add(url);
						menuItem.Sort = section.LeftMargin;

						menuItem.ConditionType = ConditionType.Group;
						menuItem.Condition = menuItemPermisson;

						if (!sectionTree.ContainsKey(section.SectionId))
						{
							sectionTree[section.SectionId] = new MenuSectionTree();
							sectionTree[section.SectionId].menuItems = new List<BXPublicMenuItem>();

							if (section.SectionId < 1)
								sectionTree[section.SectionId].url = EnableSef ? SefFolder : BXUri.ToAppRelativeUri(executionVirtualPath);
						}

						if (sectionTree[section.SectionId].menuItems == null)
							sectionTree[section.SectionId].menuItems = new List<BXPublicMenuItem>();

						sectionTree[section.SectionId].menuItems.Add(menuItem);
					}

					//Последний элемент не может иметь дочерних элементов, поэтому указываем parentLevelUrl
					if (sectionTree.ContainsKey(previousSectionId) && sectionTree.ContainsKey(sectionTree[previousSectionId].sectionId))
						sectionTree[previousSectionId].parentLevelUrl = sectionTree[sectionTree[previousSectionId].sectionId].url;

					foreach (KeyValuePair<int, MenuSectionTree> sectionItem in sectionTree)
					{
						if (!menuTree.ContainsKey(sectionItem.Value.url))
						{
							menuTree.Add(
								sectionItem.Value.url,
								new BXPublicMenu.BXLoadMenuCommandParameter(sectionItem.Value.menuItems, true, sectionItem.Value.parentLevelUrl)
							);
						}
					}
				}

				if (menuTree.Count > 0)
					cmd.AddCommandResult("bitrix:catalogue@" + executionVirtualPath, new BXCommandResult(BXCommandResultType.Ok, menuTree));
				else if (menuList != null || parentLevelUri != null)
				{
					BXPublicMenu.BXLoadMenuCommandParameter menuResult = new BXPublicMenu.BXLoadMenuCommandParameter(menuList, true, parentLevelUri);
					cmd.AddCommandResult("bitrix:catalogue@" + executionVirtualPath, new BXCommandResult(BXCommandResultType.Ok, menuResult));
				}
			}
		}

		private void ParseVariableAliases(BXParamsBag<object> result)
		{
			string[,] variableAlias = {
					{"SectionId", "SECTION_ID"},
					{"SectionCode", "SECTION_CODE"},
					{"ElementId", "ELEMENT_ID"},
					{"ElementCode", "ELEMENT_CODE"},
					{"IblockId", "IBLOCK_ID"}
				};

			for (int i = 0, length = variableAlias.GetLength(0); i < length; i++)
				if (result.ContainsKey(variableAlias[i, 1]))
					result[variableAlias[i, 0]] = result.Get<string>(variableAlias[i, 1], String.Empty);
		}

		private class MenuSectionTree
		{
			public string parentLevelUrl = null;
			public List<BXPublicMenuItem> menuItems;
			public string url;
			public int sectionId;
		}

		private List<BXPublicMenuItem> ExtractMenuItemsFromCollection(BXIBlockSectionCollection sectionsList, string executionVirtualPath)
		{
			if (sectionsList == null || sectionsList.Count < 1)
				return null;

			List<BXPublicMenuItem> menuList = new List<BXPublicMenuItem>();
			foreach (BXIBlockSection section in sectionsList)
			{
				BXPublicMenuItem menuItem = new BXPublicMenuItem();
				menuItem.Title = section.Name;

				BXParamsBag<object> replaceItems = new BXParamsBag<object>();
				replaceItems["SECTION_ID"] = section.Id;
				replaceItems["SECTION_CODE"] = section.Code ?? String.Empty;
				replaceItems["SectionId"] = replaceItems["SECTION_ID"];
				replaceItems["SectionCode"] = replaceItems["SECTION_CODE"];

				menuItem.Links.Add(MakeMenuUri(executionVirtualPath, replaceItems));
				menuItem.Sort = section.LeftMargin;
				menuItem.ConditionType = ConditionType.Group;
				menuItem.Condition = menuItemPermisson;
				menuList.Add(menuItem);
			}

			return menuList;
		}

		private string MakeMenuUri(string executionVirtualPath, BXParamsBag<object> replaceItems)
		{
			string url;

			replaceItems["IBLOCK_ID"] = IBlockId;
			replaceItems["IblockId"] = IBlockId;

			if (EnableSef)
			{
				if (SefFolder == "/" || SefFolder == String.Empty)
					url = Bitrix.IO.BXPath.TrimStart(ElementListTemplate);					
				else
					url = Bitrix.IO.BXPath.Trim(SefFolder) + "/" + Bitrix.IO.BXPath.TrimStart(ElementListTemplate);

				url = BXPath.Combine(BXPath.Trim(SefFolder), BXPath.Trim(ElementListTemplate));	

				url = BXSefUrlUtility.MakeLink(url, replaceItems);
				//url = MakeLink(url, replaceItems);
			}
			else
				url = MakeLink(String.Format("{0}?{1}=#SectionId#", BXUri.ToAppRelativeUri(executionVirtualPath), SectionIdVariable), replaceItems);

			return url;
		}

		private string GetSectionCode(int sectionId)
		{
			string sectionCode = String.Empty;

			if (sectionId > 0 && EnableSef && (ElementListTemplate.Contains("#SECTION_CODE#") || ElementListTemplate.Contains("#SectionCode#")))
			{
				BXIBlockSectionCollection section = BXIBlockSection.GetList(
					new BXFilter(
						new BXFilterItem(BXIBlockSection.Fields.ActiveGlobal, BXSqlFilterOperators.Equal, "Y"),
						new BXFilterItem(BXIBlockSection.Fields.Active, BXSqlFilterOperators.Equal, "Y"),
						new BXFilterItem(BXIBlockSection.Fields.ID, BXSqlFilterOperators.Equal, sectionId),
						new BXFilterItem(BXIBlockSection.Fields.IBlock.ID, BXSqlFilterOperators.Equal, IBlockId)
					),
					null
				);

				if (section != null && section.Count > 0)
					sectionCode = section[0].Code;
			}

			return sectionCode;
		}

		protected override void PreLoadComponentDefinition()
		{
			Title = GetMessageRaw("Title");
			Description = GetMessageRaw("Description");
			Group = new BXComponentGroup("catalogue", GetMessage("Group"), 100, BXComponentGroup.Content);
			Icon = "images/catalog.gif";

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

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

			BXCategory listSettings = BXCategory.ListSettings;
			ParamsDefinition.Add(
				"ListSortBy",
				new BXParamSingleSelection(
					GetMessageRaw("SortBy"),
					"Id",
					listSettings
				)
			);

			ParamsDefinition.Add(
				"ListSortOrder",
				new BXParamSort(
					GetMessageRaw("SortOrder"),
					true,
					listSettings
				)
			);

			ParamsDefinition.Add(
				"ShowSubElements",
				new BXParamYesNo(
					GetMessageRaw("DisplaySubsectionElements"),
					true,
					listSettings
				));

			ParamsDefinition.Add(
				"ShowAllElementsOnIndex",
				new BXParamYesNo(
					GetMessageRaw("ShowAllElementsOnIndex"),
					true,
					listSettings

			));

			ParamsDefinition.Add(
				"ListProperties",
				new BXParamMultiSelection(
					GetMessageRaw("Properties"),
					"-",
					listSettings
				)
			);

			BXCategory detailSettings = BXCategory.DetailSettings;
			ParamsDefinition.Add(
				"DetailProperties",
				new BXParamMultiSelection(
					GetMessageRaw("Properties"),
					"-",
					detailSettings
				)
			);

			ParamsDefinition.Add(
				"PropertyKeywords",
				new BXParamSingleSelection(
					GetMessageRaw("SetPageKeywordsFromProperty"),
					"-",
					detailSettings
				)
			);

			ParamsDefinition.Add(
				"PropertyDescription",
				new BXParamSingleSelection(
					GetMessageRaw("SetPageDescriptionFromProperty"),
					"-",
					detailSettings
				)
			);

			BXCategory treeSettings = new BXCategory(GetMessageRaw("SectionTreeCategory"), "treeSettings", 850);
			ParamsDefinition.Add(
				"DepthLevel",
				new BXParamText(
					GetMessageRaw("SubsectionsDisplayDepth"),
					"2",
					treeSettings
				)
			);

			ParamsDefinition.Add(
				"ShowCounters",
				new BXParamYesNo(
					GetMessageRaw("DisplayQuantityOfElementsInSection"),
					false,
					treeSettings
				)
			);

			ParamsDefinition.Add(
				"IncludeParentSections",
				new BXParamYesNo(
					GetMessageRaw("IncludeParentSections"),
					true,
					treeSettings
				)
			);

			BXCategory additionalSettings = BXCategory.AdditionalSettings;
			ParamsDefinition.Add(
				"AddAdminPanelButtons",
				new BXParamYesNo(
					GetMessageRaw("AddButtonsForThisComponentToAdminPanel"),
					false,
					additionalSettings
				)
			);

			ParamsDefinition.Add(
				"SetPageTitle",
				new BXParamYesNo(
					GetMessageRaw("SetPageTitle"),
					true,
					additionalSettings
				)
			);

			ParamsDefinition.Add(
				"RootSectionTitle",
				new BXParamText(
					GetMessageRaw("RootSectionTitle"),
					"",
					additionalSettings
				)
			);

			string clientSideActionGroupViewId = ClientID;

			BXCategory topSettings = new BXCategory(GetMessageRaw("TopSectionSortBy.Category"), "topSettings", 900);
			ParamsDefinition.Add(
				 "ShowTopElements",
				 new BXParamYesNo(
					 GetMessageRaw("DisplayTopOfElements"),
					 false,
					 topSettings,
					 new ParamClientSideActionGroupViewSwitch(clientSideActionGroupViewId, "ShowTopElements", "Top", "NonTop")
				)
			);

			ParamsDefinition.Add(
				"TopElementCount",
				new BXParamText(
					GetMessageRaw("ElementsPerPage"),
					"6",
					topSettings,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "TopElementCount", new string[] { "Top" })
				)
			);


			ParamsDefinition.Add(
				"TopSortBy",
				new BXParamSingleSelection(
					GetMessageRaw("SortBy"),
					"Id",
					topSettings,
					null,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "TopSortBy", new string[] { "Top" })
				)
			);

			ParamsDefinition.Add(
				"TopSortOrder",
				new BXParamSort(
					GetMessageRaw("SortOrder"),
					true,
					topSettings,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "TopSortOrder", new string[] { "Top" })
				)
			);

			ParamsDefinition.Add(
				"TopProperties",
				new BXParamMultiSelection(
					GetMessageRaw("Properties"),
					"-",
					topSettings,
					null,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "TopProperties", new string[] { "Top" })
				)
			);

			BXParamsBag<BXParam> SefParams = BXParametersDefinition.Sef;
			SefParams["EnableSEF"].ClientSideAction = new ParamClientSideActionGroupViewSwitch(clientSideActionGroupViewId, "EnableSEF", "Sef", "NonSef");
			SefParams["SEFFolder"].ClientSideAction = new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "SEFFolder", new string[] { "Sef" });

			ParamsDefinition.Add(SefParams);

			ParamsDefinition.Add(
				"SectionIdVariable",
				new BXParamText(
					GetMessageRaw("SectionID"),
					"section_id",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "SectionIdVariable", new string[] { "NonSef" })
				)
			);

			ParamsDefinition.Add(
				"ElementIdVariable",
				new BXParamText(
					GetMessageRaw("ElementID"),
					"element_id",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "ElementIdVariable", new string[] { "NonSef" })
				)
			);

			ParamsDefinition.Add(
				"PageIdVariable",
				new BXParamText(
					GetMessageRaw("PageIdVariable"),
					"page",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "PageIdVariable", new string[] { "NonSef" })
				)
			);

			ParamsDefinition.Add(
				"ShowAllVariable",
				new BXParamText(
					GetMessageRaw("ShowAllVariable"),
					"showall",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "ShowAllVariable", new string[] { "NonSef" })
				)
			);

			ParamsDefinition.Add(
				"ElementDetailTemplate",
				new BXParamText(
					GetMessageRaw("ElementDetailTemplate"),
					"/#SectionId#/item-#ElementId#/",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "ElementDetailTemplate", new string[] { "Sef" })
				)
			);

			ParamsDefinition.Add(
				"ElementListTemplate",
				new BXParamText(
					GetMessageRaw("ElementListTemplate"),
					"/#SectionId#/",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "ElementListTemplate", new string[] { "Sef" })
				)
			);

			ParamsDefinition.Add(
				"CommonListPageTemplate",
				new BXParamText(
					GetMessageRaw("CommonListPageTemplate"),
					"/page-#pageId#",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "CommonListPageTemplate", new string[] { "Sef" })
				)
			);

			ParamsDefinition.Add(
				"CommonListShowAllTemplate",
				new BXParamText(
					GetMessageRaw("CommonListShowAllTemplate"),
					"/all",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "CommonListShowAllTemplate", new string[] { "Sef" })
				)
			);

			ParamsDefinition.Add(
				"SectionListPageTemplate",
				new BXParamText(
					GetMessageRaw("SectionListPageTemplate"),
					"/#SectionId#/page-#pageId#",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "SectionListPageTemplate", new string[] { "Sef" })
				)
			);

			ParamsDefinition.Add(
				"SectionListShowAllTemplate",
				new BXParamText(
					GetMessageRaw("SectionListShowAllTemplate"),
					"/#SectionId#/all",
					BXCategory.Sef,
					new ParamClientSideActionGroupViewMember(clientSideActionGroupViewId, "SectionListShowAllTemplate", new string[] { "Sef" })
				)
			);

			ParamsDefinition.Add(BXParametersDefinition.Paging);
			ParamsDefinition.Add(BXParametersDefinition.Cache);
			ParamsDefinition.Add(BXParametersDefinition.Search);
			ParamsDefinition.Add(BXParametersDefinition.Ajax);

			if (!String.IsNullOrEmpty(DesignerSite))
				ParamsDefinition.Add(BXParametersDefinition.Menu(DesignerSite));
		}

		protected override void LoadComponentDefinition()
		{
			//Iblock type
			List<BXParamValue> typeParamValue = new List<BXParamValue>();
			typeParamValue.Add(new BXParamValue(GetMessageRaw("SelectIBlockType"), ""));

			BXIBlockTypeCollection iblockTypes = BXIBlockType.GetList(null, new BXOrderBy(new BXOrderByPair(BXIBlockType.Fields.Name, BXOrderByDirection.Asc)), null, null, BXTextEncoder.EmptyTextEncoder);
			foreach (BXIBlockType iblockType in iblockTypes)
				typeParamValue.Add(new BXParamValue(iblockType.Translations[BXLoc.CurrentLocale].Name, iblockType.Id.ToString()));

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

			//Iblock
			int selectedIBlockType = 0;
			if (Parameters.ContainsKey("IBlockTypeId"))
				int.TryParse(Parameters["IBlockTypeId"], out selectedIBlockType);

			BXFilter filter = new BXFilter();
			if (selectedIBlockType > 0)
				filter.Add(new BXFilterItem(BXIBlock.Fields.Type.ID, BXSqlFilterOperators.Equal, selectedIBlockType));
			if (!String.IsNullOrEmpty(DesignerSite))
				filter.Add(new BXFilterItem(BXIBlock.Fields.Sites.SiteId, BXSqlFilterOperators.Equal, DesignerSite));

			List<BXParamValue> iblockParamValue = new List<BXParamValue>();
			iblockParamValue.Add(new BXParamValue(GetMessageRaw("SelectIBlockID"), "-"));
			BXIBlockCollection iblocks = BXIBlock.GetList(filter, new BXOrderBy(new BXOrderByPair(BXIBlock.Fields.Name, BXOrderByDirection.Asc)), null, null, BXTextEncoder.EmptyTextEncoder);
			foreach (BXIBlock iblock in iblocks)
				iblockParamValue.Add(new BXParamValue(iblock.Name, iblock.Id.ToString()));

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

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

			List<BXParamValue> sortProperties = new List<BXParamValue>();
			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)
				{
					string title = BXTextEncoder.HtmlTextEncoder.Decode(customField.EditFormLabel);
					string code = customField.Name.ToUpper();
					properties.Add(new BXParamValue(title, code));
					sortProperties.Add(new BXParamValue(title, "-" + code));
				}
			}

			ParamsDefinition["ListProperties"].Values = properties;
			ParamsDefinition["DetailProperties"].Values = properties;
			ParamsDefinition["PropertyKeywords"].Values = properties;
			ParamsDefinition["PropertyDescription"].Values = properties;
			ParamsDefinition["TopProperties"].Values = properties;

			//Sorting
			List<BXParamValue> sortingFields = new List<BXParamValue>();
			sortingFields.Add(new BXParamValue(GetMessageRaw("ElementID"), "ID"));
			sortingFields.Add(new BXParamValue(GetMessageRaw("ElementName"), "Name"));
			sortingFields.Add(new BXParamValue(GetMessageRaw("ActiveFromDate"), "ActiveFromDate"));
			sortingFields.Add(new BXParamValue(GetMessageRaw("ActiveUntilDate"), "ActiveToDate"));
			sortingFields.Add(new BXParamValue(GetMessageRaw("SortIndex"), "Sort"));
			sortingFields.Add(new BXParamValue(GetMessageRaw("DateOfModification"), "UpdateDate"));
			sortingFields.AddRange(sortProperties);

			ParamsDefinition["ListSortBy"].Values = sortingFields;
			ParamsDefinition["TopSortBy"].Values = sortingFields;	
		}
	}
}
