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

using System;
using CommunityServer.Components;

namespace CommunityServer.Galleries.Components
{

	/// <summary>
	/// Summary description for GalleryPermission.
	/// </summary>
	public class GalleryPermission : PermissionBase 
	{

		#region Public Properites - Permissions

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

		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 Vote 
		{
			get{ return GetBit( Permission.Vote ); }
		}

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

		public virtual bool Administer 
		{
			get{ return GetBit( Permission.Administer ); }
		}
		
		public virtual bool SystemAdminister 
		{
			get{ return GetBit( Permission.SystemAdmin ); }
		}

		public virtual bool RemoteAttachment 
		{
			get{ return GetBit( Permission.RemoteAttachment ); }
		}
		#endregion

		public static bool Validate(Section section, Permission permission, User user, Post p)
		{
			if(section == null || section.PermissionSet == null || user == null )
				return false;

			bool bReturn = true;
			GalleryPermission fpFinal = section.ResolvePermission(user) as GalleryPermission;

			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.Moderate)) && bReturn )
				bReturn &= fpFinal.Moderate;

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

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

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

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

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

			return bReturn;
		}

		#region AccessCheck
		public static void AccessCheck(Section section, Permission permission, User user, Post post)
		{
			CSContext cSContext = CSContext.Current;

			if (cSContext.User.IsForumAdministrator || cSContext.User.IsModerator )
				return;

			/*
			 * Not sure when this was commented out, but it seems
			 * this was done to lower the overhead of making a trip
			 * to the DP.  Needs to check against the forum permission instead.
			 * 
			// Moderators can delete posts
			//
			if ( (cSContext.User.IsModerator) && (Moderate.CheckIfUserIsModerator(cSContext.User.UserID, post.ForumID)) )
				return;

			*/

			GalleryPermission fp = section.ResolvePermission( user ) as GalleryPermission;

			// TDD HACK 10/20/2004
			// there is a bug with the C# compiler in that if you have an Int64 enum and try to use it in a switch statement, 
			// the case values are only treated as Int32 and not the enum type. To solve this I'm having to use the constant 
			// values from the enumeration to make this work.
			long lValue = (long)permission;
			switch (lValue) 
			{
				case 0x0100000000000000: //(long)Permission.Administer:
					if (!cSContext.Context.Request.IsAuthenticated)
						throw new CSException(CSExceptionType.AccessDenied);

					if( !fp.Administer )
						RedirectOrExcpetion(CSExceptionType.AdministrationAccessDenied);
					break;
				case (long)Permission.Delete:
					if (!cSContext.Context.Request.IsAuthenticated)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);

					if (cSContext.User.IsAnonymous)
						if (!cSContext.Context.Request.IsAuthenticated)
							RedirectOrExcpetion(CSExceptionType.PostDeleteAccessDenied);

					// If the user is denied delete return
					if (!fp.Delete)
						RedirectOrExcpetion(CSExceptionType.PostDeleteAccessDenied);

					// Ensure we have a post
					//
					if (post == null)
						throw new Exception("Post parameter is required for Delete check");

					// Ensure the user that created this post is the user attempting to delete it
					//
					if (cSContext.User.UserID != post.User.UserID)
						RedirectOrExcpetion(CSExceptionType.PostDeleteAccessDenied);

					// Does the post have children, if so the user can't delete
					//
					if (post.Replies > 0)
						RedirectOrExcpetion(CSExceptionType.PostDeleteAccessDenied);

					// Has the time limit been exceeded for this user to delete the post?
					//
					if (GalleryConfiguration.Instance().PostDeleteAgeInMinutes > 0)
						if( DateTime.Now < post.PostDate.AddMinutes(GalleryConfiguration.Instance().PostDeleteAgeInMinutes))
							RedirectOrExcpetion(CSExceptionType.PostDeletePermissionExpired);
					break;
				case (long)Permission.Edit:
					if (!cSContext.Context.Request.IsAuthenticated)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);

					if (!cSContext.Context.Request.IsAuthenticated)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);

					if (cSContext.User.IsAnonymous)
						if (!cSContext.Context.Request.IsAuthenticated)
							RedirectOrExcpetion(CSExceptionType.PostEditAccessDenied);

					if (!fp.Edit)
						RedirectOrExcpetion(CSExceptionType.PostEditAccessDenied);

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

					// Has the time limit been exceeded for this user to delete the post?
					//
					if (GalleryConfiguration.Instance().PostEditBodyAgeInMinutes > 0)
						if (post.PostDate < DateTime.Now.AddMinutes(GalleryConfiguration.Instance().PostEditBodyAgeInMinutes))
							RedirectOrExcpetion(CSExceptionType.PostEditPermissionExpired);

					break;
				case 0x0000100000000000://Permission.Moderate:
					if (!cSContext.Context.Request.IsAuthenticated)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);

					if(!fp.Moderate)
						throw new CSException(CSExceptionType.ModerateAccessDenied);
					break;
				case (long)Permission.Post:
					if ((!cSContext.SiteSettings.EnableAnonymousUserPosting) && (!section.EnableAnonymousPosting) && (cSContext.User.IsAnonymous))
						if (!cSContext.Context.Request.IsAuthenticated)
							RedirectOrExcpetion(CSExceptionType.PostAccessDenied);

					if (!fp.Post)
						throw new CSException(CSExceptionType.PostAccessDenied);
					break;
				case (long)Permission.Reply:
					if (!cSContext.Context.Request.IsAuthenticated)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);
					
					if ((cSContext.User.IsAnonymous) && (!section.EnableAnonymousPosting) && (!cSContext.SiteSettings.EnableAnonymousUserPosting))
						if (!cSContext.Context.Request.IsAuthenticated)
							RedirectOrExcpetion(CSExceptionType.PostReplyAccessDenied);

					if (!fp.Reply) 
						RedirectOrExcpetion(CSExceptionType.PostReplyAccessDenied);
					
					// Ensure we have a post
					//
					if (post == null)
						throw new Exception("Post parameter is required for Reply check");

					// Can't reply if locked
					//
					if (post.IsLocked)
						RedirectOrExcpetion(CSExceptionType.PostLocked);

					break;
				case (long)Permission.View:
					if(!fp.View)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);
					break;
				case (long)Permission.RemoteAttachment:
					if(!fp.RemoteAttachment)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);
					break;
				case (long)Permission.Vote:
					if (!cSContext.Context.Request.IsAuthenticated)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);

					if (!fp.Vote)
						RedirectOrExcpetion(CSExceptionType.AccessDenied);
					break;
				default	:
					RedirectOrExcpetion(CSExceptionType.AccessDenied);
                    break;
			}
		}
		#endregion

	}

}
