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

using System;
using System.Collections;
using CommunityServer.Components;
using CommunityServer.ControlPanel.Components;
using CA = ComponentArt.Web.UI;

namespace CommunityServer.ControlPanel.UI
{
	/// <summary>
	/// Summary description for BasePermissionsGridControl.
	/// </summary>
	public abstract class BasePermissionsGridControl : BaseGridControl
	{
		protected Hashtable permissionChanges;

		protected abstract ApplicationType applicationType{get;}
		protected abstract Type PermissionType{get;}

		#region Public Properties

		private int sectionID = -1;
		public int SectionID
		{
			get { return sectionID; }
			set { sectionID = value;}
		}

		#endregion

		public BasePermissionsGridControl()
		{

		}

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

			this.Grid.ItemCheckChanged += new CA.Grid.ItemCheckChangedEventHandler(this.Grid_ItemCheckChanged);
		}

		private void BasePage_Load(object sender, EventArgs e)
		{
			if(!Page.IsPostBack && !this.PanelPage.IsCallBack)
			{
				buildGrid();
				Grid.DataBind();
			}
		}

		private Permission GetPermission(string permission)
		{
			switch(permission)
			{
				case "Administer":
					return Permission.Administer;
				case "Delete":
					return Permission.Delete;
				case "Edit":
					return Permission.Edit;
				case "Moderate":
					return Permission.Moderate;
				case "Post":
					return Permission.Post;
				case "Reply":
					return Permission.Reply;
				case "SystemAdminister":
					return Permission.SystemAdmin;
				case "View":
					return Permission.View;
				case "Vote":
					return Permission.Vote;
				case "RemoteAttachment":
					return Permission.RemoteAttachment;
				case "LocalAttachment":
					return Permission.LocalAttachment;
				case "Announcement":
					return Permission.Announcement;
				case "CreatePoll":
					return Permission.CreatePoll;
				case "EditOthers":
					return Permission.EditOthers;
				case "Read":
					return Permission.Read;
				case "Sticky":
					return Permission.Sticky;
				case "Video":
					return Permission.Video;
				case "Ink":
					return Permission.Ink;
				case "Download":
					return Permission.Read;
				case "MarkAsAnswer":
					return Permission.MarkAsAnswer;
			}

			return Permission.Undefined;
		}

		protected abstract PermissionBase LoadPermission(int SectionID, Guid roleID);
		protected abstract ArrayList GetSectionPermissions(int SectionID);
		protected abstract PermissionBase NewPermission();

		protected virtual bool IsNew(PermissionBase permission)
		{
			return permission == null || permission.SectionID == -1;
		}

		protected virtual bool CreateFromDefault(PermissionBase permission)
		{
			return permission != null && permission.SectionID == -1;
		}

		protected virtual void UpdatePermissions(Guid roleID, ArrayList roleChanges)
		{
			PermissionBase permission = null;
			bool isNew = false;
			permission = LoadPermission(SectionID, roleID);
			
			if(IsNew(permission))
			{
				PermissionBase originalp = permission;

				isNew = true;
				permission = NewPermission();
				permission.SectionID = SectionID;
				permission.RoleID = roleID;

				//if we are transitioning from a default permission to a seciton permission 
				//copy the existing permissions for this role
				if(CreateFromDefault(originalp))
				{
					permission.AllowMask = originalp.AllowMask;
					permission.DenyMask = originalp.DenyMask;
				}
			}
			permission.ApplicationType = applicationType;
			
			foreach(GridCheckChange e in roleChanges)
			{
				AccessControlEntry access = (e.Checked)? AccessControlEntry.Allow: AccessControlEntry.Deny;
				permission.SetBit(GetPermission(e.Column.DataField.ToString()), access);
			}

			SavePermission(permission, isNew);
		}



		protected void SavePermission(PermissionBase p, bool isNew)
		{
			if(isNew)
			{
				p.SettingsID = CSContext.Current.SettingsID;
				Permissions.AddPermission(p);
			}
			else
			{
				Permissions.UpdatePermission(p) ;
			}

			//refresh the grid
			buildGrid();
			Grid.DataBind();
		}


		protected override void buildGrid()
		{
			ArrayList unsortedRoles = GetSectionPermissions(SectionID);
			if(SectionID != -1)
				unsortedRoles.AddRange(GetSectionPermissions(-1));
			
			//The list will have any section specific permissions followed by the default permissions
			//Remove the role default permissions if a section permission is specified
			SortedList roles = new SortedList();

			foreach(PermissionBase p in unsortedRoles)
			{
				if(!roles.ContainsKey(p.Name))
					roles.Add(p.Name, p);
			}

			//The grid will only show checkboxes in edit mode if the data source is a DataTable
			Grid.DataSource = CADataConverter.ToDataTable((IList)roles.Values, PermissionType);

			this.RecordCount = roles.Count;

			ApplyUserSettings();
			
			//Override the default page size because we don't have a pager
			Grid.PageSize = 99999;
			Grid.ShowFooter = false;
			Grid.ShowHeader = false;

		}

		public void Save()
		{
			//if(this.SectionID > 0 && permissionChanges != null)
			if(permissionChanges != null)
			{
				//foreach(GridCheckChange e in permissionChanges)
				//	this.UpdatePermission(e.Item , e.Column, e.Checked) ;

				foreach(object key in permissionChanges.Keys)
					this.UpdatePermissions((Guid)key, (ArrayList)permissionChanges[key]) ;
			}
		}

		public void Grid_ItemCheckChanged(object sender, CA.GridItemCheckChangedEventArgs e)
		{
			//This event is raised on every callback. We only need to handle it on a postback/click
			//This event is raised for each checkmark in the order they were clicked on the screen
			//			if(!this.ForumPage.IsCallBack) 
			//			{
			//				if(permissionChanges == null)
			//					permissionChanges = new ArrayList();
			//
			//				//put the checked vaules into the item
			//				permissionChanges.Add(new GridCheckChange(e.Item , e.Column, e.Checked));
			//			}

			if(!this.PanelPage.IsCallBack) 
			{
				if(permissionChanges == null)
					permissionChanges = new Hashtable();

				Guid role = new Guid(e.Item["RoleIDString"].ToString());
				ArrayList roleChanges;
				if(permissionChanges.ContainsKey(role))
					roleChanges = (ArrayList)permissionChanges[role];
				else
					roleChanges = new ArrayList();


				//put the checked vaules into the item
				roleChanges.Add(new GridCheckChange(e.Item , e.Column, e.Checked));


				if(permissionChanges.ContainsKey(role))
					permissionChanges[role] = roleChanges;
				else
					permissionChanges.Add(role, roleChanges) ;

			}
		}
	}
}
