using System;
using System.Collections.Generic;
using System.IO;
using System.Web;

using Bitrix;
using Bitrix.Components;
using Bitrix.Services;
using Bitrix.UI;
using Bitrix.IO;
using Bitrix.Configuration;
using Bitrix.Services.Js;
using Bitrix.UI.Popup;
using Bitrix.Security;

namespace Bitrix.Main.Components
{
	public class SystemPublicMenuComponent : BXComponent
	{
		public BXPublicMenuItemCollection Menu
		{
			get { return ComponentCache.Get<BXPublicMenuItemCollection>("menu"); }
            private  set { ComponentCache["menu"] = value; }
		}

		public bool HasMenu
		{
			get { return Menu != null; }
		}

		private string ParameterMenuName
		{
            get { return Parameters.Get("MenuName"); }
		}

		protected void Page_Load(object sender, EventArgs e)
		{
            if (InternalSiteMenuTypes.Count > 0)
            {
                int depth = Parameters.GetInt("depth", 1);
                string menuName = Parameters.GetString("MenuName", string.Empty),
                    subMenuName = Parameters.GetString("SubMenuName", string.Empty);

                if (string.IsNullOrEmpty(menuName) || InternalSiteMenuTypes.FindIndex(
                    delegate(string obj) { return string.Equals(menuName, obj, StringComparison.InvariantCultureIgnoreCase); }
                    ) < 0)
                    menuName = InternalSiteMenuTypes[0];
                if (string.IsNullOrEmpty(subMenuName) || InternalSiteMenuTypes.FindIndex(
                    delegate(string obj) { return string.Equals(subMenuName, obj, StringComparison.InvariantCultureIgnoreCase); }
                    ) < 0)
                    subMenuName = InternalSiteMenuTypes[InternalSiteMenuTypes.Count > 1 ? 1 : 0];

                try
                {
                    Menu = BXPublicMenu.Menu.GetMenuTreeByUri(new string[] { menuName, subMenuName }, HttpContext.Current.Request.RawUrl, depth);
                }
                catch (Exception /*exc*/) { }
            }
			IncludeComponentTemplate();
		}

		protected override void Render(System.Web.UI.HtmlTextWriter writer)
		{
			System.Diagnostics.Debug.WriteLine("Render", "#MenuComponent" + ID);
			base.Render(writer);
		}

        private List<string> _siteMenuTypes = null;
        protected List<string> InternalSiteMenuTypes
        {
            get 
            {
                if (_siteMenuTypes != null)
                    return _siteMenuTypes;
                _siteMenuTypes = new List<string>(2);
                foreach (KeyValuePair<string, string> kv in BXPublicMenu.GetMenuTypes(DesignerSite))
                    _siteMenuTypes.Add(kv.Key);
                return _siteMenuTypes;
            }
        }

		private string MenuPath
		{
			get
			{
				string menuPath = null;
				if (Menu == null)
				{
					//Почему нет страницы при POSTBACK
					//if (Page == null)
					//    throw new InvalidCastException("Page is not assigned!");
					//menuPath = BXPath.Combine(BXPath.GetDirectory(Page.AppRelativeVirtualPath), Parameters.Get("MenuName") + ".menu");

					HttpRequest request = HttpContext.Current != null ? HttpContext.Current.Request : null;
					if (request == null)
						throw new InvalidOperationException("Cold not find request!");
					menuPath = BXPath.Combine(BXPath.GetDirectory(VirtualPathUtility.ToAppRelative(request.FilePath)), Parameters.Get("MenuName") + ".menu");
				}
				else
					menuPath = Menu.MenuFilePath;
				return menuPath;
			}
		}

		private string Redirect2EditPageJavascript(string menuPath)
		{
			if (string.IsNullOrEmpty(menuPath))
				menuPath = MenuPath;
			return string.Format(
				"jsUtils.Redirect(arguments, '{0}')",
				BXJSUtility.Encode(string.Format(
					"{0}?path={1}&{2}={3}",
					BXPath.ToVirtualAbsolutePath("~/bitrix/admin/MenuEdit.aspx"),
					HttpUtility.UrlEncode(menuPath),
					BXConfigurationUtility.Constants.BackUrl,
					HttpUtility.UrlEncode(Request.RawUrl)
				))
			);

		}

		private string OpenEditDialogJavascript(string menuPath)
		{
			if (string.IsNullOrEmpty(menuPath))
				menuPath = MenuPath;

			return string.Format(
				"jsPopup.ShowDialog('{0}',  {{'min_width':'400', 'min_height':'250', 'width':'720', 'height':'425'}})",
				BXJSUtility.Encode(string.Format(
					"{0}?path={1}&{2}={3}",
					BXPath.ToVirtualAbsolutePath("~/bitrix/dialogs/MenuEdit.aspx"),
					HttpUtility.UrlEncode(menuPath),
					BXConfigurationUtility.Constants.BackUrl,
					HttpUtility.UrlEncode(Request.RawUrl)
				))
			);
		}


		//zg, 7.05.2008
		//dip, 30.05.2008
		/// <summary>
		/// Создание эл-тов контекстного меню
		/// </summary>
		/// <returns></returns>
		public BXPopupMenuBaseItem[] CreateToolbarPopupMenuItems(BXShowMode showMode)
		{
			if (showMode != BXShowMode.View && BXPrincipal.Current.IsCanOperate(BXRoleOperation.Operations.MenuItemsEdit))
			{
				List<BXPopupMenuBaseItem> result = new List<BXPopupMenuBaseItem>();
				string dir = null;
				string file = null;
				string sectionMenu = null;
				if (BXPath.BreakPath(Page.AppRelativeVirtualPath, ref dir, ref file))
					sectionMenu = BXPath.Combine(dir, Parameters["MenuName"] + ".menu");

				#region edit menu
				string menuPath = this.MenuPath;
				if (menuPath == null || !Directory.Exists(BXPath.MapPath(dir)))
					return null;

				if (!string.IsNullOrEmpty(menuPath) && BXSecureIO.FileExists(menuPath))
				{
					BXPopupMenuItem item = new BXPopupMenuItem();
					item.IconCssClass = "icon menu-edit";
					item.Text = GetMessage("PopupMenuItem.Text.EditMenuItems");
					item.ClientClickScript = OpenEditDialogJavascript(null);
					result.Add(item);
				}
				#endregion

				//Отображается во всех режимах
				if (!string.IsNullOrEmpty(sectionMenu) && !BXSecureIO.FileExists(sectionMenu))
				{
					BXPopupMenuItem item = new BXPopupMenuItem();
					item.IconCssClass = "icon menu-edit";
					item.Text = GetMessage("PopupMenuItem.Text.CreateMenuInThisSection");
					item.ClientClickScript = OpenEditDialogJavascript(sectionMenu);
					result.Add(item);
				}
				return result.ToArray();
			}

			return null;
		}

		//zg, 07.05.2008
		public override BXComponentPopupMenuInfo PopupMenuInfo
		{
			get
			{
				BXComponentPopupMenuInfo info = base.PopupMenuInfo;
				info.CreateCustomPopupMenuItems = CreateToolbarPopupMenuItems;
				return info;
			}
		}

		//zg, 30.05.2008
		public override void CreatePublicPanelMenu(BXPublicPanelMenuSectionList sectionList)
		{
			if (MenuPath == null || string.IsNullOrEmpty(ParameterMenuName))
				return;
			if (!BXPrincipal.Current.IsCanOperate(BXRoleOperation.Operations.MenuItemsEdit))
				return;
			if (sectionList == null)
				throw new ArgumentNullException("sectionList");
			BXPublicPanelPopulator.EnsureMenu(BXPublicPanelMenuEntry.MenuGeneralMenu, BXShowMode.All, sectionList);
		}

		//zg, 30.05.2008
		public override void PopulatePublicPanelMenu(BXPublicPanelMenuSectionList sectionList)
		{
			if (MenuPath == null || string.IsNullOrEmpty(ParameterMenuName))
				return;
			if (!BXPrincipal.Current.IsCanOperate(BXRoleOperation.Operations.MenuItemsEdit))
				return;
			if (sectionList == null)
				throw new ArgumentNullException("sectionList");
			BXPublicPanelMenu menu = BXPublicPanelPopulator.FindMenu(BXPublicPanelMenuEntry.MenuGeneralMenu, sectionList);
			if (menu == null)
				throw new InvalidOperationException("Could not find MenuGeneralMenu");

			string typeName = ParameterMenuName;
			string menuItemId = string.Format("MenuEdit_{0}", typeName);

			BXPopupMenuV2 menuPopup = menu.PopupMenu;
			if (menuPopup == null)
				menuPopup = menu.PopupMenu = new BXPopupMenuV2();
			BXPopupMenuBaseItem[] menuItems = menuPopup.Items;
			if (Array.FindIndex(menuItems, delegate(BXPopupMenuBaseItem obj)
			{
				return string.CompareOrdinal(obj.ID, menuItemId) == 0;
			}) < 0)
			{
				//bool canAccessAdmin = BXConfigurationUtility.ShowMode == BXShowMode.Configurator && BXPrincipal.Current.IsCanOperate("AccessAdminSystem");
				bool canAccessAdmin = false; //новая логика, для меню секция "В панели управления" не отображается

				BXPopupMenuItemContainer admin = null;
				int adminSeparatorIndex = -1;
				BXPopupMenuSeparator adminSeparator = null;
				if (canAccessAdmin)
				{
					adminSeparatorIndex = Array.FindIndex<BXPopupMenuBaseItem>(menuItems, delegate(BXPopupMenuBaseItem obj)
					{
						return string.CompareOrdinal(obj.ID, "MenuEditSeparator") == 0;
					});

					if (adminSeparatorIndex < 0)
					{
						adminSeparator = new BXPopupMenuSeparator();
						adminSeparator.ID = "MenuEditSeparator";
						menuPopup.AddItem(adminSeparator);
						adminSeparatorIndex = menuPopup.ItemCount - 1;
					}
					else
						adminSeparator = (BXPopupMenuSeparator)menuItems[adminSeparatorIndex];

					int adminIndex = Array.FindIndex<BXPopupMenuBaseItem>(menuItems, delegate(BXPopupMenuBaseItem obj)
					{
						return string.CompareOrdinal(obj.ID, "MenuEditAdmin") == 0;
					});

					if (adminIndex < 0)
					{
						admin = new BXPopupMenuItemContainer();
						admin.ID = "MenuEditAdmin";
						admin.Text = GetMessage("PopupMenuItem.Text.InControlPanel");
						admin.Title = admin.Text;
						menuPopup.AddItem(admin);
					}
					else
						admin = (BXPopupMenuItemContainer)menuItems[adminIndex];
				}

				string sectionMenu = null;
				string dir = null;
				string file = null;
				if (BXPath.BreakPath(Page.AppRelativeVirtualPath, ref dir, ref file))
					sectionMenu = BXPath.Combine(dir, Parameters["MenuName"] + ".menu");

				//секция с эл-тами вида "Создать XXX меню"
				//bool aboutCreateSection = BXConfigurationUtility.ShowMode == BXShowMode.Configurator && !string.IsNullOrEmpty(sectionMenu) && !BXSecureIO.FileExists(sectionMenu);
				//включается во всех режимах просмотра 
				bool aboutCreateSection = !string.IsNullOrEmpty(sectionMenu) && !BXSecureIO.FileExists(sectionMenu);

				BXPopupMenuSeparator createSeparator = null;
				int createSeparatorIndex = Array.FindIndex<BXPopupMenuBaseItem>(menuItems, delegate(BXPopupMenuBaseItem obj)
					{
						return string.CompareOrdinal(obj.ID, "MenuEditCreateSeparator") == 0;
					});
				if (aboutCreateSection)
				{
					if (createSeparatorIndex < 0)
					{
						createSeparator = new BXPopupMenuSeparator();
						createSeparator.ID = "MenuEditCreateSeparator";
						createSeparatorIndex = adminSeparatorIndex >= 0 ? adminSeparatorIndex : menuPopup.ItemCount;
						menuPopup.AddItem(createSeparator, createSeparatorIndex);
						if (adminSeparatorIndex >= 0)
							adminSeparatorIndex++;
					}
					else
						createSeparator = (BXPopupMenuSeparator)menuItems[createSeparatorIndex];
				}

				string modifyTypeNameLoc;
				switch (typeName.ToLowerInvariant())
				{
					case "top":
						modifyTypeNameLoc = GetMessage("PopupMenuItem.Text.Part.TopMenu");
						break;
					case "left":
						modifyTypeNameLoc = GetMessage("PopupMenuItem.Text.Part.LeftMenu");
						break;
					case "bottom":
						modifyTypeNameLoc = GetMessage("PopupMenuItem.Text.Part.BottomMenu");
						break;
					default:
                        modifyTypeNameLoc = string.Format(GetMessage("PopupMenuItem.Text.FormatPart.MenuOfType"), "\"" + BXPublicMenu.GetMenuTitle(BXSite.Current.Id, typeName)+"\"");
						break;
				}

				BXPopupMenuItem menuPopupEditPublic = new BXPopupMenuItem();
				menuPopupEditPublic.ID = menuItemId;
				menuPopupEditPublic.Text = string.Format(GetMessage("PopupMenuItem.Text.FormatPart.EditMenuItems"), modifyTypeNameLoc);
				menuPopupEditPublic.Title = menuPopupEditPublic.Text;
				menuPopupEditPublic.IconCssClass = "icon menu-edit";
				menuPopupEditPublic.ClientClickScript = OpenEditDialogJavascript(null);

				int menuPopupEditPublicIndex = createSeparatorIndex >= 0 ? createSeparatorIndex : adminSeparatorIndex >= 0 ? adminSeparatorIndex : menuPopup.ItemCount;
				menuPopup.AddItem(menuPopupEditPublic, menuPopupEditPublicIndex);
				if (createSeparatorIndex >= 0)
					createSeparatorIndex++;

				if (adminSeparatorIndex >= 0)
					adminSeparatorIndex++;

				if (aboutCreateSection)
				{
					string createTypeNameLoc;
					switch (typeName.ToLowerInvariant())
					{
						case "top":
							createTypeNameLoc = GetMessage("PopupMenuItem.Text.Part.CreateTopMenu");
							break;
						case "left":
							createTypeNameLoc = GetMessage("PopupMenuItem.Text.Part.CreateLeftMenu");
							break;
						case "bottom":
							createTypeNameLoc = GetMessage("PopupMenuItem.Text.Part.CreateBottomMenu");
							break;
						default:
							createTypeNameLoc = string.Format(GetMessage("PopupMenuItem.Text.FormatPart.MenuOfType"), BXPublicMenu.GetMenuTitle(BXSite.Current.Id, typeName));
							break;
					}

					BXPopupMenuItem menuPopupCreatePublic = new BXPopupMenuItem();
					menuPopupCreatePublic.IconCssClass = "icon menu-edit";
					menuPopupCreatePublic.Text = string.Format(GetMessage("PopupMenuItem.Text.FormatPart.CreateMenuInThisSection"), createTypeNameLoc);
					;
					menuPopupCreatePublic.ClientClickScript = OpenEditDialogJavascript(sectionMenu);
					int menuPopupCreatePublicIndex = adminSeparatorIndex >= 0 ? adminSeparatorIndex : menuPopup.ItemCount;
					menuPopup.AddItem(menuPopupCreatePublic, menuPopupCreatePublicIndex);
				}

				if (canAccessAdmin)
				{
					BXPopupMenuItem menuPopupEditAdmin = new BXPopupMenuItem();
					menuPopupEditAdmin.ID = menuItemId + "_admin";
                    menuPopupEditAdmin.Text = string.Format(GetMessage("PopupMenuItem.Text.FormatPart.EditMenuItems"), modifyTypeNameLoc); //TODO: Localize "Редакт..."
					menuPopupEditAdmin.Title = menuPopupEditAdmin.Text;
					menuPopupEditAdmin.IconCssClass = "icon menu-edit";
					menuPopupEditAdmin.ClientClickScript = Redirect2EditPageJavascript(null);
					admin.Items.Add(menuPopupEditAdmin);
				}

				menu.PopupMenuItemIndexForDefaultAction = 0;
			}
			base.PopulatePublicPanelMenu(sectionList);
		}

		protected override void PreLoadComponentDefinition()
		{
			Title = GetMessage("Title");
			Description = GetMessage("Description");
			Icon = "component.gif";

			Group = new BXComponentGroup("system_menu", GetMessage("Group"), 100, BXComponentGroup.Utility);

			ParamsDefinition["Depth"] = new BXParamText(GetMessageRaw("ComponentParam.Title.MenuDepth"), "1", BXCategory.Main);
			ParamsDefinition["MenuName"] = new BXParamSingleSelection(GetMessageRaw("ComponentParam.Title.MenuType"), "top", BXCategory.Main);
			ParamsDefinition["SubMenuName"] = new BXParamSingleSelection(GetMessageRaw("ComponentParam.Title.SubmenuType"), "left", BXCategory.Main);
			//ParamsDefinition.Add(BXParametersDefinition.Cache);
		}

		protected override void LoadComponentDefinition()
		{
			ParamsDefinition["MenuName"].Values.Clear();
			ParamsDefinition["SubMenuName"].Values.Clear();

			if (!IsComponentDesignMode)
			{
				BXSite site = BXSite.Current;
				if (site != null)
				{
					foreach (KeyValuePair<string, string> p in BXPublicMenu.GetMenuTypes(site.Id))
					{
						ParamsDefinition["MenuName"].Values.Add(new BXParamValue(string.Format("{0} ({1})", p.Value, p.Key.ToLowerInvariant()), p.Key.ToLowerInvariant()));
						ParamsDefinition["SubMenuName"].Values.Add(new BXParamValue(string.Format("{0} ({1})", p.Value, p.Key.ToLowerInvariant()), p.Key.ToLowerInvariant()));
					}
				}
			}
			else
			{
				if (!string.IsNullOrEmpty(DesignerSite))
				{
					foreach (KeyValuePair<string, string> p in BXPublicMenu.GetMenuTypes(DesignerSite))
					{
						ParamsDefinition["MenuName"].Values.Add(new BXParamValue(string.Format("{0} ({1})", p.Value, p.Key.ToLowerInvariant()), p.Key.ToLowerInvariant()));
						ParamsDefinition["SubMenuName"].Values.Add(new BXParamValue(string.Format("{0} ({1})", p.Value, p.Key.ToLowerInvariant()), p.Key.ToLowerInvariant()));
					}
				}
			}
		}
	}

	public class SystemPublicMenuTemplate : BXComponentTemplate<SystemPublicMenuComponent>
	{
		protected override void PrepareDesignMode()
		{
			MinimalWidth = "85";
			MinimalHeight = "45";
			StartWidth = "100%";
			StartHeight = "100";

			if (Results["menu"] == null || (Results["menu"] as BXPublicMenuItemCollection).Count == 0)
			{
				BXPublicMenuItemCollection menu = new BXPublicMenuItemCollection();

				for (int i = 0; i < 5; i++)
				{
					BXPublicMenuItem item = new BXPublicMenuItem();
					if (i == 0)
						item.Link = "~/bitrix";
					else
						item.Link = string.Format("~/bitrix{0}", i);

					item.Title = string.Format("Bitrix {0}", i + 1);
					menu.Add(item);
				}

				Results["menu"] = menu;
			}
		}
	}
}

#region Compatibility Issue
public partial class PublicMenuComponent : Bitrix.Main.Components.SystemPublicMenuComponent
{
	//NESTED CLASSES
	public class Template : BXComponentTemplate<PublicMenuComponent>
	{
		protected override void PrepareDesignMode()
		{
			MinimalWidth = "85";
			MinimalHeight = "45";
			StartWidth = "100%";
			StartHeight = "100";

			if (Results["menu"] == null || (Results["menu"] as BXPublicMenuItemCollection).Count == 0)
			{
				BXPublicMenuItemCollection menu = new BXPublicMenuItemCollection();

				for (int i = 0; i < 5; i++)
				{
					BXPublicMenuItem item = new BXPublicMenuItem();
					if (i == 0)
						item.Link = "~/bitrix";
					else
						item.Link = string.Format("~/bitrix{0}", i);

					item.Title = string.Format("Bitrix {0}", i + 1);
					menu.Add(item);
				}

				Results["menu"] = menu;
			}
		}
	}
}
#endregion