//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using CommunityServer.Components;
using CommunityServer.ControlPanel.UI;
using CommunityServer.Controls;
using CommunityServer.Discussions.Components;
using CA = ComponentArt.Web.UI;
using ResourceManager = CommunityServer.ControlPanel.Components.ResourceManager;
using ResourceControl = CommunityServer.ControlPanel.Controls.ResourceControl;

namespace CommunityServer.ControlPanel.Forums
{
	/// <summary>
	///	Summary description for ForumTreeViewControl.
	/// </summary>
	public class ForumTreeViewControl : BaseForumControl
	{

		#region Child Controls

		protected ContextMenu GroupContextMenu;
		protected ContextMenu SectionContextMenu;
		protected CA.TreeView Tree;
		private bool isAdmin = false;
		protected static readonly string AjaxQueryStringValue = "{0}:{1}";
		protected static readonly string AjaxQueryStringValuePattern = "(\\d+):([\\w\\.-]*)";

		#endregion

		#region Properties

		private string addGroupButtonClientID;
		public string AddGroupButtonClientID
		{
			get{return addGroupButtonClientID;}
			set{addGroupButtonClientID = value;}
		}

		private string addSectionButtonClientID;
		public string AddSectionButtonClientID
		{
			get{return addSectionButtonClientID;}
			set{addSectionButtonClientID = value;}
		}

		private string deleteButtonClientID;
		public string DeleteButtonClientID
		{
			get{return deleteButtonClientID;}
			set{deleteButtonClientID = value;}
		}

		protected string AjaxQueryStringKey
		{
			get
			{
				return "___" + this.ClientID;
			}
		}

		#endregion

		override protected void OnInit(EventArgs e)
		{
			this.Load += new EventHandler(this.Page_Load);
			base.OnInit(e);
		}


		private void Page_Load(object sender, EventArgs e)
		{
		    AjaxManager.Register(this,"ForumTreeViewControl");

			isAdmin = CSContext.Current.User.IsForumAdministrator;

			if(!Page.IsPostBack)
			{
				EnsureChildControls();
				BuildGroupTree();
			}
		}


		private CA.TreeViewNode BuildNode(string name)
		{
			CA.TreeViewNode node = new CA.TreeViewNode();

			if (name.Length > 30)
				node.Text = name.Substring(0, 27) + "...";
			else
				node.Text = name;

			return node;
		}
	

		private CA.TreeViewNode BuildRootnode()
		{
			CA.TreeViewNode node = new CA.TreeViewNode();
			node.Text = Components.ResourceManager.GetString("CP_Forums_TreeView_RootNodeLabel");
			node.DraggingEnabled = false;
			node.DroppingEnabled = true;
			node.EditingEnabled = false;
			node.ImageUrl = "folders.gif";
			node.Value = "-1:-1";
			node.Expanded = true;
			node.ID = "RootNode";
			return node;
		}


		private void BuildGroupTree()
		{
			if (Tree == null)
				return;

			// Get all forum groups
			ArrayList forumGroups = ForumGroups.GetForumGroups(false, isAdmin, true);

			// Create root node
			CA.TreeViewNode rootNode = BuildRootnode();
			Tree.Nodes.Add(rootNode);
			
			CA.TreeViewNode node;
			foreach (Group group in forumGroups)
			{
				node = BuildNode(group.Name);
				node.ImageUrl = "folders.gif";
				node.DraggingEnabled = true;
				node.DroppingEnabled = true;
				node.EditingEnabled = true;
				node.ID = String.Format("{0}:-1", group.GroupID);
				node.Value = String.Format("{0}:-1", group.GroupID);

				if (group.HasSections)
					node.Text += "(" + group.Sections.Count.ToString() + ")";

				rootNode.Nodes.Add(node);

				CSContext cntx = CSContext.Current;
				if (group.GroupID == cntx.GroupID)
				{
					node.Expanded = true;
					if (cntx.SectionID < 0)
					{
						node.CssClass = Tree.SelectedNodeCssClass;
						node.HoverCssClass = Tree.SelectedNodeCssClass;
					}
				}

				BuildForumTree(group.GroupID, -1, node.Nodes);

			}
		}


		private void BuildForumTree(int groupID, int sectionID, CA.TreeViewNodeCollection nodes)
		{
			ArrayList forums;

			if (sectionID > 0)
			{
				forums = Discussions.Components.Forums.GetForum(sectionID, false, isAdmin).Sections;

				// Sort subforums by name
				forums.Sort(new SectionSorter(SectionSortBy.Name));
			}
			else
				forums = Discussions.Components.Forums.GetForumsByForumGroupID(groupID, false, isAdmin, true, true);

			if (forums != null)
			{
				CA.TreeViewNode node;
				foreach (Forum forum in forums)
				{
					node = BuildNode(forum.Name);
					node.Checked = forum.IsActive;
					node.EditingEnabled = false;

					if ((forum.ForumType == ForumType.Deleted) || (forum.ForumType == ForumType.Reporting))
					{
						node.DraggingEnabled = false;
						node.DroppingEnabled = false;
					}
					else
					{
						node.DraggingEnabled = true;
						node.DroppingEnabled = true;
					}

					if(forum.IsActive)
						node.ImageUrl = "notes.gif"; 
					else
						node.ImageUrl = "notesdisabled.gif"; 
				
					node.ID = String.Format("{0}:{1}", forum.GroupID, forum.SectionID);
					node.Value = String.Format("{0}:{1}", forum.GroupID, forum.SectionID);

					if (forum.Sections.Count > 0)
					{
						node.Text += "(" + forum.Sections.Count.ToString() + ")";
						BuildForumTree(forum.GroupID, forum.SectionID, node.Nodes);
					}

					nodes.Add(node);

					if (forum.SectionID == CSContext.Current.SectionID)
					{
						node.CssClass = Tree.SelectedNodeCssClass;
						node.HoverCssClass = Tree.SelectedNodeCssClass;
					}
				}
			}
		}


		#region Call Back Methods

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public string ChangeSectionEnabled(int groupID, int sectionID)
		{
			if( !CSContext.Current.User.IsForumAdministrator ) 
				return "-1";

			if(sectionID > 0)
			{
				Forum f = Discussions.Components.Forums.GetForum(sectionID, false, true);
				f.IsActive = !f.IsActive;
			    Discussions.Components.Forums.Update(f);
			}

			return string.Format("{0}^{1}",groupID, sectionID ) ;
		}


		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public string GetNextName(int groupID)
		{
			string name = Components.ResourceManager.GetString("CP_Forums_TreeView_NewForum");
			ArrayList forums = Discussions.Components.Forums.GetForums(true, false, false, true);
			name = Sections.NextSectionName(forums, name);
			return string.Format("{0}^{1}", groupID, name );
		}


		#region Reorder / Move

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public string MoveForum(int groupID, int sectionID, int targetGroupID, int targetSectionID)
		{
			Forum section = Discussions.Components.Forums.GetForum(sectionID, false, true );

			// Do not allow move of special forum types
			if ((section.ForumType == ForumType.Deleted) || (section.ForumType == ForumType.Reporting)) 
				return "0";

			// Move the forum
			section.GroupID = targetGroupID;

			if (targetSectionID < 0)
				section.ParentID = 0;
			else
				section.ParentID = targetSectionID;

			// Move any children sections as well
			if (section.Sections.Count > 0)
			{
				foreach (Forum f in section.Sections)
				{
					MoveSubForum(f, targetGroupID);
				}
			}

		    Discussions.Components.Forums.Update(section);

			

			return string.Format("{0}^{1}^{2}^{3}",groupID, targetGroupID, sectionID, targetSectionID) ;
		}

		protected void MoveSubForum(Forum forum, int groupID)
		{
			forum.GroupID = groupID;
		    Discussions.Components.Forums.Update(forum);

			// Move any children sections as well
			if (forum.Sections.Count > 0)
			{
				foreach (Forum f in forum.Sections)
				{
					MoveSubForum(f, groupID);
				}
			}
		}


		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public void ReorderForumOrGroup(int groupID, int sectionID, int index)
		{
			if (sectionID < 0)
			{
				// ReOrder Group
				Groups.ReOrder(groupID, index);
			}
			else
			{
				// ReOrder Section
				Sections.MoveOrReOrder(groupID, sectionID, index);
			}
		}

		#endregion

		#region Rename

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public int RenameGroup(int groupID, string newName)
		{
		    Group group = ForumGroups.GetForumGroup(groupID, false, true);
			group.Name = newName.Trim();

			// Check to make sure the same name doesn't already exist
			foreach(Group g in ForumGroups.GetForumGroups(false, true, true))
			{
				if((g.Name == group.Name) && (g.GroupID != group.GroupID))
					return -1;
			}

			Groups.UpdateGroup(group);

			return groupID;
		}

		#endregion

		#region Add

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public string AddGroup()
		{
			string name = ResourceManager.GetString("CP_Forums_TreeView_NewGroup");
			ArrayList groups = ForumGroups.GetForumGroups(false, true, true); 
			name = Groups.NextGroupName(groups, name); 

		    Group group = new Group();
			group.ApplicationType = ApplicationType.Forum;
			group.Name = name.Trim();
			
			int groupID = Groups.AddGroup(group);
	
			// Not Cluster safe, but lets try and update the cache
			groups = ForumGroups.GetForumGroups(true, true, true); 

			return string.Format("{0}^{1}", groupID, name);
		}

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public string AddSection(int groupID, int parentSectionID, string name)
		{
			if(name.Trim() == string.Empty)
				return "-1";

			ArrayList forums = Discussions.Components.Forums.GetForums(true, false, false, true); 
			if(Sections.HasSection(forums, name))
				return "0";

			// Add the GroupID onto the appKey
			string rawKey = String.Format("{0}-{1}", name, groupID);
			string formattedKey = null;
			Globals.ValidateApplicationKey(rawKey, out formattedKey);
			
			Forum f = new Forum();
			f.GroupID = groupID;
			f.Name = name;
			f.ApplicationKey = formattedKey;
			f.IsActive = false;
			f.SettingsID = CSContext.Current.SiteSettings.SettingsID;
			f.ApplicationType = ApplicationType.Forum;
			f.ForumType = ForumType.Normal;
			f.IsSearchable =  true;

			// Check if this is a subforum
			if (parentSectionID > 0)
				f.ParentID = parentSectionID;

			// Create The Forum
			f.SectionID = Discussions.Components.Forums.Add(f);

			// Not Cluster safe, but lets try and update the cache
			forums = Discussions.Components.Forums.GetForums(true, true, false, true); 
			
			return string.Format("{0}^{1}^{2}^{3}", groupID, f.ParentID, f.SectionID, name);
		}

		#endregion

		#region Delete

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public int DeleteGroup(int groupID)
		{
			CSContext cntx = CSContext.Current;
			if( !cntx.User.IsForumAdministrator ) 
				return 0;

		    Group group = ForumGroups.GetForumGroup(groupID, false, true, cntx.UserID);

			// Don't delete a group if it has sections
			if(ForumGroups.HasChildSections(group.GroupID))
				return 0;

			Groups.DeleteGroup(group);
			return groupID;
		}	

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public string DeleteSection(int groupID, int sectionID)
		{
			if( !CSContext.Current.User.IsForumAdministrator ) 
				return "0";

			Forum section = Discussions.Components.Forums.GetForum(sectionID, false, true);
			if ((section.ForumType == ForumType.Deleted) || (section.ForumType == ForumType.Reporting)) 
				return "0";

			CommunityServer.Discussions.Components.Forums.Delete(section);
			return string.Format("{0}^{1}",groupID, sectionID) ;
		}

		#endregion
		
		#endregion

	}
}
