using System;
using System.Collections; 
using Meta.Web;
using Meta.Web.Configuration; 
using Meta.Web.Security;  
using MetaSite.Components.Providers; 

namespace MetaSite.Components
{
	/// <summary>
	/// Permissions¡£
	/// </summary>
	public class ForumPermission
	{
		#region Private Members
		
		int	   roleId;
		string roleName;			
		int    forumId;		
	
		Permission		allowMask;
		Permission		denyMask;
		bool			implied;

		public ForumPermission()
		{			
			allowMask = 0;
			denyMask = (Permission)(long)-1;
			implied	= true;			
		}
		
		public ForumPermission(int role, string name, Permission allow, Permission deny, bool impliedPermissions )
		{			
			roleId = role;
			roleName = name;
			allowMask = allow;
			denyMask = deny;
			implied = impliedPermissions;
		}

		#endregion	
		
		#region Core Public Properties

		public int RoleId 
		{
			get{ return roleId; }
			set{ roleId = value; }
		}

		public string Name 
		{
			get{ return roleName; }
			set{ roleName = value; }
		}

		public int ForumId
		{
			get {return forumId;}
			set {forumId = value;}
		}
	
		public bool Implied 
		{
			get{ return implied; }
			set{ implied = value; }
		}

		public Permission AllowMask 
		{
			get{ return allowMask; }
			set{ allowMask = value; }
		}
       
		public Permission DenyMask 
		{
			get{ return denyMask; }
			set{ denyMask = value; }
		}
		
		#endregion

		#region Public Methods

		public bool GetBit( Permission mask ) 
		{
			bool bReturn = false;
				
			if(( denyMask & mask ) == mask )
				bReturn = false;

			if(( allowMask & mask ) == mask )
				bReturn = true;
				
			return bReturn;
		}

		public void SetBit( Permission mask, AccessControlEntry accessControl ) 
		{
			switch( accessControl )
			{
				case AccessControlEntry.Allow:
					allowMask	|= (Permission)((long)mask & (long)-1);
					denyMask	&= ~(Permission)((long)mask & (long)-1);
					break;
				case AccessControlEntry.NotSet:
					allowMask	&= ~(Permission)((long)mask & (long)-1);
					denyMask	&= ~(Permission)((long)mask & (long)-1);
					break;
				default:
					allowMask	&= ~(Permission)((long)mask & (long)-1);
					denyMask	|= (Permission)((long)mask & (long)-1);
					break;
			}
		}
	
		public void Merge( ForumPermission forumPermission ) 
		{
			this.allowMask	|= forumPermission.AllowMask;
			this.denyMask	|= forumPermission.DenyMask;		
		}

		#endregion

		#region Public Properites - Permissions
		public virtual bool View 
		{
			get{ return GetBit( Permission.View ); }
		}

		public virtual bool Read 
		{
			get{ return GetBit( Permission.Read ); }
		}

		public virtual bool Post 
		{
			get{ return GetBit( Permission.Post ); }
		}

		public virtual bool Reply 
		{
			get{ return GetBit( Permission.Reply ); }
		}
        
		public virtual bool Edit 
		{
			get{ return GetBit( Permission.Edit ); }
		}
        
		public virtual bool Delete 
		{
			get{ return GetBit( Permission.Delete ); }
		} 
		public virtual bool Administer 
		{
			get{ return GetBit( Permission.Administer ); }
		}	
	
		#endregion

		# region"static"
		
		public static bool Validate(Forum forum, Permission permission, User user) 
		{
			if(forum == null || forum.PermissionSet == null || user == null )
				return false;
		
			bool bReturn = true;
			ForumPermission fpFinal = forum.ResolvePermission(user);
		
			if((permission == (permission | Permission.Administer)) && bReturn )
				bReturn &= fpFinal.Administer;
	
			if((permission == (permission | Permission.Delete)) && bReturn ) 
				bReturn &= fpFinal.Delete;

			if((permission == (permission | Permission.Edit)) && bReturn )
				bReturn &= fpFinal.Edit;
	
			if((permission == (permission | Permission.Post)) && bReturn )
				bReturn &= fpFinal.Post;

			if((permission == (permission | Permission.Read)) && bReturn )
				bReturn &= fpFinal.Read;

			if((permission == (permission | Permission.Reply)) && bReturn )
				bReturn &= fpFinal.Reply;
			
			if((permission == (permission | Permission.View)) && bReturn )
				bReturn &= fpFinal.View;
		
			return bReturn;
		}

		public static void AccessCheck(Forum forum, Permission permission, User user, Post post) 
		{
			ContextData context = ContextData.Current;


			int forumId;
			if (post != null)
				forumId = post.ForumId;
			else
				forumId = forum.ForumId;
		
			ForumPermission fp = forum.ResolvePermission( user ) as ForumPermission;

			long lValue = (long)permission;

			switch (lValue) 
			{
				case (long)Permission.Administer:
					if (!context.Context.Request.IsAuthenticated)
						RedirectOrExcpetion();

					if( !fp.Administer )
						RedirectOrExcpetion();
					break;			
			
				case (long)Permission.Delete:	
					if (!context.Context.Request.IsAuthenticated)
						RedirectOrExcpetion();

					if (!fp.Delete)
						RedirectOrExcpetion();
				
					if (post == null)
						throw new Exception("Post parameter is required for Delete check");
				
					if (context.User.UserId != post.User.UserId)
						RedirectOrExcpetion();
					
						
					break;

				case (long)Permission.Edit:	
			
					if (!context.Context.Request.IsAuthenticated)
						RedirectOrExcpetion();
				
					if (!fp.Edit)
						RedirectOrExcpetion();		

					if (post == null)
						throw new Exception("Post parameter is required for Edit check");

				
					if (context.User.UserId != post.User.UserId )
					{
						RedirectOrExcpetion();	
					}

					break;				
			
				case (long)Permission.Post:		
			
					if (!context.Context.Request.IsAuthenticated)
						RedirectOrExcpetion();

					if (!fp.Post)
						RedirectOrExcpetion();	
					break;

				case (long)Permission.Read:
					if(!fp.Read)
						RedirectOrExcpetion();	

					break;
				case (long)Permission.Reply:	
				
					if (!context.Context.Request.IsAuthenticated)
						RedirectOrExcpetion();
					
					if (!fp.Reply) 
						RedirectOrExcpetion();						
				
					if (post == null)
						throw new Exception("Post parameter is required for Reply check");

					if (post.IsLocked)
						RedirectOrExcpetion();	
					break;

			
				case (long)Permission.View:
					if(!fp.View)
						RedirectOrExcpetion();	
					break;
				
				default	:
					RedirectOrExcpetion();	
					break;
			}
		}
	
		public static void RedirectOrExcpetion(string  message)
		{
			ContextData context = ContextData.Current;

			if(context.IsWebRequest && context.User.UserName == Users.AnonymousUser)
			{
				context.Context.Response.Redirect(Globals.UrlBase + Urls.Instance()["Login"]);
				context.Context.Response.End();
			}
			else
				throw new Exception(message);
		}
	
		public static void RedirectOrExcpetion()
		{
			ContextData context = ContextData.Current;

			if(context.IsWebRequest && context.User.UserName == Users.AnonymousUser)
			{
				context.Context.Response.Redirect(Globals.UrlBase + Urls.Instance()["Login"]);
				context.Context.Response.End();
			}		
		}	

		#endregion
	}
}
