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

using System;
using System.Web.UI;
using CommunityServer.Components;
using CommunityServer.Controls;
using CommunityServer.Discussions.Components;
using CA = ComponentArt.Web.UI;

namespace CommunityServer.Discussions.Controls 
{
	// *********************************************************************
	//  ModerationMenu
	//
	/// <summary>
	/// This control renders a moderation menu used by forum moderators
	/// to moderate new posts.
	/// </summary>
	// ********************************************************************/ 	
	public class ModerationContextMenu : TemplatedWebControl, IPostBackEventHandler
	{
		#region Child Controls
		
		CA.Menu menu;
		CA.CallBack callback;

		CSContext csContext;
		bool canModerate = false;
		bool canEdit = false;

		#endregion
		
		#region Skin

		protected override void AttachChildControls() 
		{
			menu = (CA.Menu) FindControl("Menu");
			callback = (CA.CallBack) FindControl("Callback");
			
			InitializeChildControls();
		}

		private void InitializeChildControls() 
		{
			callback.Callback += new CA.CallBack.CallbackEventHandler(this.OnOpenContextMenu);
		}

		#endregion

		#region Control Event Handlers

		protected override void OnInit(EventArgs e) 
		{
			csContext = CSContext.Current;

			if (SkinName == null)
				ExternalSkinFileName = "Moderation/Skin-ModerationContextMenu.ascx";
			else 
				ExternalSkinFileName = SkinName;
			
			base.OnInit(e);
		}
		
		protected override void OnLoad(EventArgs e) 
		{
			if (!UserHasAccess)
			{
				this.Visible = false;
				return;
			}

			callback.Style["position"] = "absolute";
			callback.ClientSideOnCallbackComplete = string.Format("new Function('eval(\\'window.{0}.ShowContextMenu();\\');');", this.ClientID);

			base.OnLoad(e);
		}

		protected void OnOpenContextMenu(object sender, CA.CallBackEventArgs e)
		{
			this.Post = Posts.GetPost(int.Parse(e.Parameter), csContext.User.UserID);
			this.Forum = this.Post.Forum;
			this.DataBindMenu();

			menu.RenderControl(e.Output);
		}

		public string GetOpenContextMenuScript(ForumPost post)
		{
			this.Forum = post.Forum;
			this.Post = post;

			if (!UserHasAccess)
				return "";
			else
				return string.Format("window.{0}.LoadContextMenu(event, {1});", this.ClientID, post.PostID.ToString());
		}

		protected override void OnPreRender(System.EventArgs e)
		{
			string script = @"
<script language=javascript>
function ModerationContextMenu (name, contextMenuName, callback)
{
	this.Name = name;
	this.ContextMenuName = contextMenuName;
	this.CallBackHandle = callback;
	this.ContextMenuX = 0;
	this.ContextMenuY = 0;
	this.LastPostID = -1;
	this.MenuLoaded = false;

	this.LoadContextMenu = function(event, postID)
	{
		this.ContextMenuX = event.pageX ? event.pageX : event.x;
		this.ContextMenuY = event.pageY ? event.pageY : event.y;

		if (this.LastPostID == postID && this.MenuLoaded)
		{
			this.ShowContextMenu();
		}
		else
		{
			if (this.MenuLoaded)
				eval('window.' + this.ContextMenuName + '.Hide();');

			this.MenuLoaded = false;
			this.LastPostID = postID;
			this.CallBackHandle.DomElement.style.left = (this.ContextMenuX + parseInt(document.documentElement.scrollLeft, 10)) + 'px';
			this.CallBackHandle.DomElement.style.top = ((this.ContextMenuY - this.CallBackHandle.DomElement.offsetHeight) + parseInt(document.documentElement.scrollTop, 10)) + 'px';
			this.CallBackHandle.Callback(postID);
		}

		event.cancelBubble = true;
		event.returnValue = false;
		return false;
	}

	this.ShowContextMenu = function()
	{
		this.MenuLoaded = true;
		eval('window.' + this.ContextMenuName + '.ShowContextMenu(' + this.ContextMenuX + ', ' + this.ContextMenuY + ', null);');
	}
}
</script>";

			if (!Page.IsClientScriptBlockRegistered(this.GetType().FullName))
				Page.RegisterClientScriptBlock(this.GetType().FullName, script);

			if (!Page.IsClientScriptBlockRegistered(this.ClientID))
				Page.RegisterStartupScript(this.ClientID, String.Format("<script language=\"javascript\">window.{0} = new ModerationContextMenu('{0}', '{1}', window.{2});</script>", this.ClientID, this.menu.ClientID, this.callback.ClientID));

			base.OnPreRender(e);
		}

		#endregion

		#region DataBind

		protected virtual void DataBindMenu() 
		{
			// If the current user does not have moderate permissions on the post, return.
			//

			if (this.Post == null)
				return;

           
			if (!UserHasAccess)
			{
				menu.Visible = false;
				return;
			}

			CA.MenuItem item;

			if (!post.IsApproved)
			{
				// Add the Approve click event handler.
				//
				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("ModerationMenu_Approve");
				item.ClientSideCommand = Page.GetPostBackClientEvent(this, "Approve:" + this.Post.PostID.ToString());
				menu.Items.Add(item);
			

				// Add the ApproveReply click event handler.
				//
				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("ModerationMenu_ApproveReply");
				item.ClientSideCommand = Page.GetPostBackClientEvent(this, "ApproveReply:" + this.Post.PostID.ToString());
				menu.Items.Add(item);

				// Add the ApproveEdit click event handler.
				//
				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("ModerationMenu_ApproveEdit");
				item.ClientSideCommand = Page.GetPostBackClientEvent(this, "ApproveEdit:" + this.Post.PostID.ToString());
				menu.Items.Add(item);
			}

			// Set the EditPost url to the ModeratePostEdit url.
			//
			item = new CA.MenuItem();
			item.Text = ResourceManager.GetString("ModeratePost_EditPost");
			item.NavigateUrl = Globals.GetSiteUrls().ModeratePostEdit(this.Post.PostID, Globals.UrlEncode(Globals.GetSiteUrls().Post(this.Post.PostID)));
			menu.Items.Add(item);

			// Set the DeleteApprovedPost url based on the post level of the post.
			//
			if (this.Post.PostLevel == 1) 
			{
				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("ModerationMenu_DeleteThread");
				item.NavigateUrl = Globals.GetSiteUrls().ModeratePostDelete(this.Post.PostID, Globals.UrlEncode(ForumUrls.Instance().Forum(this.Post.SectionID)));
				menu.Items.Add(item);
			} 
			else 
			{
				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("ModerationMenu_DeletePost");
				item.NavigateUrl = Globals.GetSiteUrls().ModeratePostDelete(this.Post.PostID, Globals.UrlEncode(Globals.GetSiteUrls().Post(this.Post.ParentID)));
				menu.Items.Add(item);
			}

			// Set the Move url to the ModeratePostMove url if the post level is 1, otherwise disable the move control.
			//
			if (this.Post.PostLevel == 1) 
			{
				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("ModeratePost_Move");
				item.NavigateUrl = Globals.GetSiteUrls().ModeratePostMove(this.Post.PostID, Globals.UrlEncode(ForumUrls.Instance().Forum(this.Post.SectionID)));
				menu.Items.Add(item);
			}

			// Set the Split url to the ModerateThreadSplit url
			//
			if (this.Post.PostLevel > 1) 
			{
				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("ModerateThread_Split");
				item.NavigateUrl = Globals.GetSiteUrls().ModerateThreadSplit(this.Post.PostID, Globals.UrlEncode(ForumUrls.Instance().Forum(this.Post.SectionID)));
				menu.Items.Add(item);
			} 
			else 
			{
				item = new CA.MenuItem();
				item.NavigateUrl = Globals.GetSiteUrls().ModerateThreadJoin(this.Post.PostID, ForumUrls.Instance().Forum(this.Post.SectionID));
				item.Text = ResourceManager.GetString("ModerateThread_Join");
				menu.Items.Add(item);
			}

			// Toggle Lock / Unlock Post
			//
			if (this.Post.PostLevel == 1) 
			{
				item = new CA.MenuItem();

				if (this.Post.IsLocked) 
					item.Text = ResourceManager.GetString("ModerateThread_UnLock_Thread");
				else 
					item.Text = ResourceManager.GetString("ModerateThread_Lock_Thread");

				item.ClientSideCommand = Page.GetPostBackClientEvent(this, "LockUnlock:" + this.Post.PostID.ToString());
				menu.Items.Add(item);
			}

			if (canModerate) 
			{
				// Set the text for the hyperlink
				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("ModeratePost_EditUser");
				item.NavigateUrl = Globals.GetSiteUrls().ControlPanelUserEdit(this.Post.User.UserID);
				menu.Items.Add(item);

				// Toggle Moderate / Unmoderate User
				//
				item = new CA.MenuItem();
				switch (this.Post.User.ModerationLevel) 
				{
					case ModerationLevel.Unmoderated:
						item.Text = ResourceManager.GetString("ModerateThread_Moderate_User");
						break;

					case ModerationLevel.Moderated:
						item.Text = ResourceManager.GetString("ModerateThread_UnModerate_User");
						break;

					default:
						item = null;
						break;
				}
                
				if (item != null)
				{
					item.ClientSideCommand = Page.GetPostBackClientEvent(this, "ModerateUnModerateUser:" + this.Post.User.UserID.ToString());
					menu.Items.Add(item);
				}

				// Set the ModerationHistory url.
				//
				if (csContext.SiteSettings.EnableUserModerationCounters) 
				{
					item = new CA.MenuItem();
					item.Text = ResourceManager.GetString("ModeratePost_ModerationHistory");
					item.NavigateUrl = Globals.GetSiteUrls().ModerationHistory(Post.PostID, Globals.UrlEncode(ForumUrls.Instance().Forum(this.Post.SectionID)));
					menu.Items.Add(item);
				}
			}
		}
        
		#endregion

		#region Properties

		/// <summary>
		/// Property UsePathToRedirect (bool)
		/// </summary>
		public bool UsePathToRedirect
		{
			get 
			{  
				object obj = ViewState["UsePathToRedirect"];
				return obj == null ? false : (bool)obj;
			}
			set {  ViewState["UsePathToRedirect"] = value; }
		}

		private ForumPost post = null;
		public ForumPost Post 
		{
			get 
			{
				return post;
			}
			set 
			{
				post = value;
			}
		}

		private Forum forum = null;
		public Forum Forum 
		{
			get 
			{
				return forum;
			}
			set 
			{
				forum = value;
			}
		}

		protected bool UserHasAccess
		{
			get
			{
				if (Forum != null)
				{
					canModerate = Permissions.ValidatePermissions(Forum, Permission.Moderate, csContext.User);
					canModerate |= csContext.User.IsForumAdministrator;

					canEdit = Permissions.ValidatePermissions(Forum, Permission.EditOthers, csContext.User);

					return (canModerate || canEdit);
				}
				else
					return false;
			}
		}

		#endregion

		#region Events

		public event EventHandler PostModerateRefresh;
		private void OnPostModerateRefresh(EventArgs e)
		{
			if(PostModerateRefresh != null)
				PostModerateRefresh(null, e);
		}

		#endregion

		#region Event Handlers

		// *********************************************************************
		//  Approve_Click
		//
		/// <summary>
		/// Event handler for approving a post
		/// </summary>
		// ***********************************************************************/
		private void Approve_Click(string commandArgument) 
		{   
			int postID = int.Parse(commandArgument);
			ForumPost post = Posts.GetPost(postID, csContext.User.UserID);

			// Approve the post.
			Moderate.ApprovePost(post, csContext.User.UserID);

			//Context.Response.Redirect(Globals.GetSiteUrls().ModerateForum(csContext.SectionID));
			Context.Response.Redirect(Globals.GetSiteUrls().ModerateForum(post.Forum.SectionID));
			Context.Response.End();
		}
        
		// *********************************************************************
		//  UnModerateUser_Click
		//
		/// <summary>
		/// Event handler for unmoderating a user.
		/// </summary>
		// ***********************************************************************/
		private void ModerateUnModerateUser_Click (string commandArgument) 
		{
			User user = Users.GetUser(int.Parse(commandArgument), false, false);
			Moderate.ToggleUserSettings( ModerateUserSetting.ToggleModerate, user, csContext.User.UserID);

			//Basically, if in mod menu then redirect to mod menu - otherwise, you are in forum so redirect to where you are
			if (this.UsePathToRedirect)
			{
				Context.Response.Redirect(Globals.GetSiteUrls().ModerateForum(csContext.SectionID));
				Context.Response.End();
			}
			else
			{
				Context.Response.Redirect(Globals.GetSiteUrls().Post(this.Post.PostID));
				Context.Response.End();
			}
		}

		// *********************************************************************
		//  LockUnlock_Click
		//
		/// <summary>
		/// Event handler for approving a post and replying to the post.
		/// </summary>
		// ***********************************************************************/
		private void LockUnlock_Click (string commandArgument) 
		{
			int postID = int.Parse(commandArgument);
			ForumPost post = Posts.GetPost(postID, csContext.User.UserID);

			// Check for access before submitting
			Permissions.AccessCheck( post.Section, Permission.Moderate, csContext.User, post );

			// Doing this twice just in case the exception thrown from the access check doesn't fully abort execution
			if(Permissions.ValidatePermissions(post.Section, Permission.Moderate, csContext.User, post))
				Moderate.TogglePostSettings(ModeratePostSetting.ToggleLock, post, csContext.User.UserID);

			// Fire an event to refresh the thread
			OnPostModerateRefresh(new System.EventArgs());
		}

		// *********************************************************************
		//  ApproveReply_Click
		//
		/// <summary>
		/// Event handler for approving a post and replying to the post.
		/// </summary>
		// ***********************************************************************/
		private void ApproveReply_Click(string commandArgument) 
		{
			int postID = int.Parse(commandArgument);
			ForumPost post = Posts.GetPost(postID, csContext.User.UserID);

			// Approve the post.
			Moderate.ApprovePost(post, csContext.User.UserID);

			// Redirect the user to the PostReply url.
			Context.Response.Redirect(ForumUrls.Instance().PostReply(postID));
			Context.Response.End();
		}

		// *********************************************************************
		//  ApproveEdit_Click
		//
		/// <summary>
		/// Event handler for approving a post and editing the post.
		/// </summary>
		// ***********************************************************************/
		private void ApproveEdit_Click(string commandArgument) 
		{
			int postID = int.Parse(commandArgument);
			ForumPost post = Posts.GetPost(postID, csContext.User.UserID);

			// Approve the post.
			Moderate.ApprovePost(post, csContext.User.UserID);

			// Redirect the user to the edit post url.
			Context.Response.Redirect(Globals.GetSiteUrls().ModeratePostEdit(postID, SiteUrls.Instance().Post(Post.PostID)));
			Context.Response.End();
		}

		#endregion

		#region IPostBackEventHandler Members

		public void RaisePostBackEvent(string eventArgument)
		{
			string[] e = eventArgument.Split(':');
			switch (e[0])
			{
				case "Approve":
					this.Approve_Click(e[1]);
					break;

				case "ApproveReply":
					this.ApproveReply_Click(e[1]);
					break;

				case "ApproveEdit":
					this.ApproveEdit_Click(e[1]);
					break;

				case "LockUnlock":
					this.LockUnlock_Click(e[1]);
					break;

				case "ModerateUnModerateUser":
					this.ModerateUnModerateUser_Click(e[1]);
					break;
			}	
		}

		#endregion
	}
}

