namespace Orciid.UserControls
{
	using System;
	using System.Data;
	using System.Drawing;
	using System.Web;
	using System.Web.UI.WebControls;
	using System.Web.UI.HtmlControls;
	using System.Collections;
	using Orciid.Core;

	public class ACLControl : System.Web.UI.UserControl
	{
		protected System.Web.UI.WebControls.Button ModifyButton;
		protected System.Web.UI.WebControls.LinkButton AddButton;
		protected System.Web.UI.HtmlControls.HtmlTable PrivilegeDisplayTable;
		protected Orciid.UserControls.PrivilegeDisplay PrivilegeDisplayControl;
		protected Orciid.UserControls.UserSelection UserSelectionControl;
		protected Orciid.UserControls.PrivilegeSelection PrivilegeSelectionControl;
		protected Orciid.UserControls.UserGroupSelection UserGroupSelectionControl;
		protected System.Web.UI.HtmlControls.HtmlGenericControl UserSelectionDiv;
		protected System.Web.UI.HtmlControls.HtmlGenericControl PrivilegeSelectionDiv;
		protected System.Web.UI.WebControls.Button PrivilegeSelectionCancelButton;
		protected System.Web.UI.WebControls.Button PrivilegeSelectionContinueButton;
		protected System.Web.UI.WebControls.CheckBoxList UserCheckBoxList;
		protected System.Web.UI.WebControls.Button UserSelectionCancelButton;
		protected System.Web.UI.WebControls.Button UserSelectionContinueButton;
		protected System.Web.UI.WebControls.Button UserGroupSelectionCancelButton;
		protected System.Web.UI.WebControls.Button UserGroupSelectionContinueButton;
		protected System.Web.UI.HtmlControls.HtmlGenericControl UserGroupSelectionDiv;
		protected System.Web.UI.WebControls.LinkButton AddGroupButton;
		protected System.Web.UI.HtmlControls.HtmlGenericControl AnonymousUserSpan;
		
		private IAccessControlled accesscontrolled;
		private bool databound = false;
		protected System.Web.UI.WebControls.LinkButton AddAnonymousUserLinkButton;
		protected System.Web.UI.WebControls.Button DeleteButton;
		protected System.Web.UI.HtmlControls.HtmlGenericControl SelectedEntriesSpan;
		protected System.Web.UI.HtmlControls.HtmlGenericControl SelectUsersSpan;
		protected System.Web.UI.HtmlControls.HtmlGenericControl SelectUserGroupsSpan;
		protected System.Web.UI.HtmlControls.HtmlGenericControl SelectPermissionsSpan;
		protected System.Web.UI.HtmlControls.HtmlGenericControl UncheckUnwantedSpan;
		private string mode;

		public IAccessControlled DataSource
		{
			get
			{
				return accesscontrolled;
			}
			set
			{
				accesscontrolled = value;
			}
		}

		protected override void LoadViewState(object savedState) 
		{
			if (savedState != null)
			{
				base.LoadViewState(savedState);
				mode = (string)ViewState["mode"];
				try
				{
					char objecttypeid = (char)ViewState["actype"];
					int objectid = (int)ViewState["acid"];
					accesscontrolled = AccessControl.GetAccessControlledObject(objecttypeid, objectid);
				}
				catch
				{
					accesscontrolled = null;
				}
			}
		}

		protected override object SaveViewState()
		{
			if (accesscontrolled != null)
			{
				ViewState["actype"] = accesscontrolled.GetObjectTypeIdentifier();
				ViewState["acid"] = accesscontrolled.GetID();
				ViewState["mode"] = mode;
			}
			return base.SaveViewState();
		}

		private void Page_Load(object sender, System.EventArgs e)
		{
			if (!IsPostBack && !databound)
			{
				PrivilegeDisplayTable.Visible = false;
				UserSelectionDiv.Visible = false;
				UserGroupSelectionDiv.Visible = false;
				PrivilegeSelectionDiv.Visible = false;
			}
		}

		public override void DataBind()
		{
			databound = true;
			ActivatePrivilegeDisplay();
		}

		private void ActivatePrivilegeDisplay()
		{
			UserSelectionDiv.Visible = false;
			UserGroupSelectionDiv.Visible = false;
			PrivilegeSelectionDiv.Visible = false;
			if (accesscontrolled != null)
			{
				PrivilegeDisplayTable.Visible = true;
				IAccessControl acl = accesscontrolled.GetAccessControl();
				PrivilegeDisplayControl.DataSource = acl;
				PrivilegeDisplayControl.DataBind();
			}
			else
				PrivilegeDisplayTable.Visible = false;
		}

		private void ActivatePrivilegeSelection(IPrivilegeAssignee[] usersandgroups, 
			Privilege granted, Privilege denied)
		{
			SortedList users = new SortedList();
			SortedList groups = new SortedList();
			foreach (IPrivilegeAssignee a in usersandgroups)
			{
				if (a is Orciid.Core.User)
					users.Add(a.GetName(), String.Format("U{0}", a.GetID()));
				else if (a is Orciid.Core.UserGroup)
					groups.Add(a.GetName(), String.Format("G{0}", a.GetID()));
				else
					throw new Exception("Unknown IPrivilegeAssignee type");
			}
			ArrayList combined = new ArrayList();
			foreach (string key in groups.Keys)
				combined.Add(new ListItem(key, (string)groups[key]));
			foreach (string key in users.Keys)
				combined.Add(new ListItem(key, (string)users[key]));
			UserCheckBoxList.DataSource = combined;
			UserCheckBoxList.DataTextField = "Text";
			UserCheckBoxList.DataValueField = "Value";
			UserCheckBoxList.DataBind();
			foreach (ListItem item in UserCheckBoxList.Items)
				item.Selected = true;
			PrivilegeSelectionDiv.Visible = true;
			PrivilegeSelectionControl.RelevantPrivileges = accesscontrolled.GetRelevantPrivileges();
			PrivilegeSelectionControl.GrantedPrivileges = granted;
			PrivilegeSelectionControl.DeniedPrivileges = denied;
			PrivilegeSelectionControl.DataBind();
		}


		#region Web Form Designer generated code
		override protected void OnInit(EventArgs e)
		{
			//
			// CODEGEN: This call is required by the ASP.NET Web Form Designer.
			//
			InitializeComponent();
			base.OnInit(e);
		}
		
		/// <summary>
		///		Required method for Designer support - do not modify
		///		the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
			this.AddGroupButton.Click += new System.EventHandler(this.AddGroupButton_Click);
			this.AddAnonymousUserLinkButton.Click += new System.EventHandler(this.AddAnonymousUserLinkButton_Click);
			this.ModifyButton.Click += new System.EventHandler(this.ModifyButton_Click);
			this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click);
			this.UserSelectionCancelButton.Click += new System.EventHandler(this.UserSelectionCancelButton_Click);
			this.UserSelectionContinueButton.Click += new System.EventHandler(this.UserSelectionContinueButton_Click);
			this.UserGroupSelectionCancelButton.Click += new System.EventHandler(this.UserGroupSelectionCancelButton_Click);
			this.UserGroupSelectionContinueButton.Click += new System.EventHandler(this.UserGroupSelectionContinueButton_Click);
			this.PrivilegeSelectionCancelButton.Click += new System.EventHandler(this.PrivilegeSelectionCancelButton_Click);
			this.PrivilegeSelectionContinueButton.Click += new System.EventHandler(this.PrivilegeSelectionContinueButton_Click);
			this.Load += new System.EventHandler(this.Page_Load);
			this.PreRender += new System.EventHandler(this.ACLControl_PreRender);

		}
		#endregion

		private void AddButton_Click(object sender, System.EventArgs e)
		{
			PrivilegeDisplayTable.Visible = false;
			UserSelectionDiv.Visible = true;
			UserSelectionDiv.DataBind();
			mode = "add";
		}

		private void UserSelectionContinueButton_Click(object sender, System.EventArgs e)
		{
			UserSelectionDiv.Visible = false;
			int[] selected = UserSelectionControl.GetSelection();
			if (selected != null && selected.Length > 0)
			{
				ActivatePrivilegeSelection(Orciid.Core.User.GetByID(selected),
					Privilege.None, Privilege.None);
			}
			else
			{
				ActivatePrivilegeDisplay();
			}
		}

		private void UserSelectionCancelButton_Click(object sender, System.EventArgs e)
		{
			ActivatePrivilegeDisplay();
		}

		private void PrivilegeSelectionCancelButton_Click(object sender, System.EventArgs e)
		{
			ActivatePrivilegeDisplay();
		}

		private void PrivilegeSelectionContinueButton_Click(object sender, System.EventArgs e)
		{
			ArrayList selectedusers = new ArrayList();
			ArrayList selectedgroups = new ArrayList();
			Privilege granted = PrivilegeSelectionControl.GrantedPrivileges;
			Privilege denied = PrivilegeSelectionControl.DeniedPrivileges;
			foreach (ListItem item in UserCheckBoxList.Items)
				if (item.Selected)
				{
					string type = item.Value.Substring(0, 1);
					int id = Int32.Parse(item.Value.Substring(1));
					if (type == "U")
						selectedusers.Add(id);
					else if (type == "G")
						selectedgroups.Add(id);
					else
						throw new Exception("Invalid type character");
				}
			int[] userids = (int[])selectedusers.ToArray(typeof(int));
			int[] groupids = (int[])selectedgroups.ToArray(typeof(int));
			if (accesscontrolled != null)
			{
				IAccessControl acl = accesscontrolled.GetAccessControl();
				if (mode == "add")
				{
					acl.AddUserPrivilege(granted, denied, userids);
					acl.AddUserGroupPrivilege(granted, denied, groupids);
				}
				else if (mode == "set")
				{
					acl.SetUserPrivilege(granted, denied, userids);
					acl.SetUserGroupPrivilege(granted, denied, groupids);
				}
				else
					throw new Exception("mode has invalid value");
			}
			ActivatePrivilegeDisplay();
		}

		private void UserGroupSelectionCancelButton_Click(object sender, System.EventArgs e)
		{
			ActivatePrivilegeDisplay();
		}

		private void UserGroupSelectionContinueButton_Click(object sender, System.EventArgs e)
		{
			UserGroupSelectionDiv.Visible = false;
			int[] selected = UserGroupSelectionControl.GetSelection();
			if (selected != null && selected.Length > 0)
			{
				ActivatePrivilegeSelection(Orciid.Core.UserGroup.GetByID(selected),
					Privilege.None, Privilege.None);
			}
			else
			{
				ActivatePrivilegeDisplay();
			}		
		}

		private void AddGroupButton_Click(object sender, System.EventArgs e)
		{
			PrivilegeDisplayTable.Visible = false;
			UserGroupSelectionDiv.Visible = true;
			UserGroupSelectionDiv.DataBind();	
			mode = "add";
		}

		private void DeleteButton_Click(object sender, System.EventArgs e)
		{
			int[] userids = PrivilegeDisplayControl.GetSelectedUsers();
			int[] usergroupids = PrivilegeDisplayControl.GetSelectedUserGroups();
			if (accesscontrolled != null)
			{
				IAccessControl acl = accesscontrolled.GetAccessControl();
				acl.SetUserPrivilege(Privilege.None, Privilege.None, userids);
				acl.SetUserGroupPrivilege(Privilege.None, Privilege.None, usergroupids);
				ActivatePrivilegeDisplay();
			}
		}

		private void ModifyButton_Click(object sender, System.EventArgs e)
		{
			int[] userids = PrivilegeDisplayControl.GetSelectedUsers();
			int[] usergroupids = PrivilegeDisplayControl.GetSelectedUserGroups();
			if (userids.Length > 0 || usergroupids.Length > 0)
			{
				Privilege granted = Privilege.None;
				Privilege denied = Privilege.None;
				ArrayList selected = new ArrayList(userids.Length + usergroupids.Length);
				selected.AddRange(Orciid.Core.UserGroup.GetByID(usergroupids));
				selected.AddRange(Orciid.Core.User.GetByID(userids));
				if (accesscontrolled != null)
				{
					IAccessControl acl = accesscontrolled.GetAccessControl();
					foreach (IPrivilegeAssignee i in selected)
					{
						granted = granted | acl.GetGrantedPrivileges(i);
						denied = denied | acl.GetDeniedPrivileges(i);
					}
				}
				PrivilegeDisplayTable.Visible = false;
				mode = "set";
				ActivatePrivilegeSelection((IPrivilegeAssignee[])selected.ToArray(typeof(IPrivilegeAssignee)), 
					granted, denied);
			}
			else
			{
				ActivatePrivilegeDisplay();
			}		
		}

		private void AddAnonymousUserLinkButton_Click(object sender, System.EventArgs e)
		{
			PrivilegeDisplayTable.Visible = false;
			mode = "add";
			UserSelectionDiv.Visible = false;
			ActivatePrivilegeSelection(new IPrivilegeAssignee[] { AnonymousUser.User },
				Privilege.None, Privilege.None);
		}

		private void ACLControl_PreRender(object sender, System.EventArgs e)
		{
			if (accesscontrolled.GetObjectTypeIdentifier() == 'S')
			{
				Properties props = Properties.GetSystemProperties();
				AnonymousUserSpan.Visible = (props.GetAsInt("allowgrant2guest", 0) == 1);
			}
			else
				AnonymousUserSpan.Visible = true;
		}
	}
}
