using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
namespace Csla.Security
{
  /// 
  /// Maintains a list of allowed and denied user roles
  /// for each property.
  /// 
  /// 
  [Serializable()]
  public class AuthorizationRules
  {
    private Type _businessObjectType;
    private AuthorizationRulesManager _typeRules;
    private AuthorizationRulesManager _instanceRules;
    /// 
    /// Creates an instance of the object, initializing
    /// it with the business object type.
    /// 
    /// 
    /// Type of the business object to which the rules
    /// apply.
    /// 
    public AuthorizationRules(Type businessObjectType)
    {
      _businessObjectType = businessObjectType;
    }
    private AuthorizationRulesManager InstanceRules
    {
      get
      {
        if (_instanceRules == null)
          _instanceRules = new AuthorizationRulesManager();
        return _instanceRules;
      }
    }
    private AuthorizationRulesManager TypeRules
    {
      get
      {
        if (_typeRules == null)
          _typeRules = SharedAuthorizationRules.GetManager(_businessObjectType, true);
        return _typeRules;
      }
    }
    #region Add Per-Instance Roles
    /// 
    /// Specify the roles allowed to read a given
    /// property.
    /// 
    /// Name of the property.
    /// List of roles granted read access.
    /// 
    /// This method may be called multiple times, with the roles in
    /// each call being added to the end of the list of allowed roles.
    /// In other words, each call is cumulative, adding more roles
    /// to the list.
    /// 
    public void InstanceAllowRead(string propertyName, params string[] roles)
    {
      RolesForProperty currentRoles = InstanceRules.GetRolesForProperty(propertyName);
      foreach (string item in roles)
        currentRoles.ReadAllowed.Add(item);
    }
    /// 
    /// Specify the roles denied read access to 
    /// a given property.
    /// 
    /// Name of the property.
    /// List of roles denied read access.
    /// 
    /// This method may be called multiple times, with the roles in
    /// each call being added to the end of the list of denied roles.
    /// In other words, each call is cumulative, adding more roles
    /// to the list.
    /// 
    public void InstanceDenyRead(string propertyName, params string[] roles)
    {
      RolesForProperty currentRoles = InstanceRules.GetRolesForProperty(propertyName);
      foreach (string item in roles)
        currentRoles.ReadDenied.Add(item);
    }
    /// 
    /// Specify the roles allowed to write a given
    /// property.
    /// 
    /// Name of the property.
    /// List of roles granted write access.
    /// 
    /// This method may be called multiple times, with the roles in
    /// each call being added to the end of the list of allowed roles.
    /// In other words, each call is cumulative, adding more roles
    /// to the list.
    /// 
    public void InstanceAllowWrite(string propertyName, params string[] roles)
    {
      RolesForProperty currentRoles = InstanceRules.GetRolesForProperty(propertyName);
      foreach (string item in roles)
        currentRoles.WriteAllowed.Add(item);
    }
    /// 
    /// Specify the roles denied write access to 
    /// a given property.
    /// 
    /// Name of the property.
    /// List of roles denied write access.
    /// 
    /// This method may be called multiple times, with the roles in
    /// each call being added to the end of the list of denied roles.
    /// In other words, each call is cumulative, adding more roles
    /// to the list.
    /// 
    public void InstanceDenyWrite(string propertyName, params string[] roles)
    {
      RolesForProperty currentRoles = InstanceRules.GetRolesForProperty(propertyName);
      foreach (string item in roles)
        currentRoles.WriteDenied.Add(item);
    }
    #endregion
    #region Add Per-Type Roles
    /// 
    /// Specify the roles allowed to read a given
    /// property.
    /// 
    /// Name of the property.
    /// List of roles granted read access.
    /// 
    /// This method may be called multiple times, with the roles in
    /// each call being added to the end of the list of allowed roles.
    /// In other words, each call is cumulative, adding more roles
    /// to the list.
    /// 
    public void AllowRead(string propertyName, params string[] roles)
    {
      RolesForProperty currentRoles = TypeRules.GetRolesForProperty(propertyName);
      foreach (string item in roles)
        currentRoles.ReadAllowed.Add(item);
    }
    /// 
    /// Specify the roles denied read access to 
    /// a given property.
    /// 
    /// Name of the property.
    /// List of roles denied read access.
    /// 
    /// This method may be called multiple times, with the roles in
    /// each call being added to the end of the list of denied roles.
    /// In other words, each call is cumulative, adding more roles
    /// to the list.
    /// 
    public void DenyRead(string propertyName, params string[] roles)
    {
      RolesForProperty currentRoles = TypeRules.GetRolesForProperty(propertyName);
      foreach (string item in roles)
        currentRoles.ReadDenied.Add(item);
    }
    /// 
    /// Specify the roles allowed to write a given
    /// property.
    /// 
    /// Name of the property.
    /// List of roles granted write access.
    /// 
    /// This method may be called multiple times, with the roles in
    /// each call being added to the end of the list of allowed roles.
    /// In other words, each call is cumulative, adding more roles
    /// to the list.
    /// 
    public void AllowWrite(string propertyName, params string[] roles)
    {
      RolesForProperty currentRoles = TypeRules.GetRolesForProperty(propertyName);
      foreach (string item in roles)
        currentRoles.WriteAllowed.Add(item);
    }
    /// 
    /// Specify the roles denied write access to 
    /// a given property.
    /// 
    /// Name of the property.
    /// List of roles denied write access.
    /// 
    /// This method may be called multiple times, with the roles in
    /// each call being added to the end of the list of denied roles.
    /// In other words, each call is cumulative, adding more roles
    /// to the list.
    /// 
    public void DenyWrite(string propertyName, params string[] roles)
    {
      RolesForProperty currentRoles = TypeRules.GetRolesForProperty(propertyName);
      foreach (string item in roles)
        currentRoles.WriteDenied.Add(item);
    }
    #endregion
    #region Check Roles
    /// 
    /// Indicates whether the property has a list
    /// of roles granted read access.
    /// 
    /// Name of the property.
    public bool HasReadAllowedRoles(string propertyName)
    {
      if (InstanceRules.GetRolesForProperty(propertyName).ReadAllowed.Count > 0)
        return true;
      return TypeRules.GetRolesForProperty(propertyName).ReadAllowed.Count > 0;
    }
    /// 
    /// Indicates whether the current user as defined by
    /// 
    /// is explicitly allowed to read the property.
    /// 
    /// Name of the property.
    public bool IsReadAllowed(string propertyName)
    {
      System.Security.Principal.IPrincipal user = ApplicationContext.User;
      if (InstanceRules.GetRolesForProperty(propertyName).IsReadAllowed(user))
        return true;
      return TypeRules.GetRolesForProperty(propertyName).IsReadAllowed(user);
    }
    /// 
    /// Indicates whether the property has a list
    /// of roles denied read access.
    /// 
    /// Name of the property.
    public bool HasReadDeniedRoles(string propertyName)
    {
      if (InstanceRules.GetRolesForProperty(propertyName).ReadDenied.Count > 0)
        return true;
      return TypeRules.GetRolesForProperty(propertyName).ReadDenied.Count > 0;
    }
    /// 
    /// Indicates whether the current user as defined by
    /// 
    /// is explicitly denied read access to the property.
    /// 
    /// Name of the property.
    public bool IsReadDenied(string propertyName)
    {
      System.Security.Principal.IPrincipal user = ApplicationContext.User;
      if (InstanceRules.GetRolesForProperty(propertyName).IsReadDenied(user))
        return true;
      return TypeRules.GetRolesForProperty(propertyName).IsReadDenied(user);
    }
    /// 
    /// Indicates whether the property has a list
    /// of roles granted write access.
    /// 
    /// Name of the property.
    public bool HasWriteAllowedRoles(string propertyName)
    {
      if (InstanceRules.GetRolesForProperty(propertyName).WriteAllowed.Count > 0)
        return true;
      return TypeRules.GetRolesForProperty(propertyName).WriteAllowed.Count > 0;
    }
    /// 
    /// Indicates whether the current user as defined by
    /// 
    /// is explicitly allowed to set the property.
    /// 
    /// Name of the property.
    public bool IsWriteAllowed(string propertyName)
    {
      System.Security.Principal.IPrincipal user = ApplicationContext.User;
      if (InstanceRules.GetRolesForProperty(propertyName).IsWriteAllowed(user))
        return true;
      return TypeRules.GetRolesForProperty(propertyName).IsWriteAllowed(user);
    }
    /// 
    /// Indicates whether the property has a list
    /// of roles denied write access.
    /// 
    /// Name of the property.
    public bool HasWriteDeniedRoles(string propertyName)
    {
      if (InstanceRules.GetRolesForProperty(propertyName).WriteDenied.Count > 0)
        return true;
      return TypeRules.GetRolesForProperty(propertyName).WriteDenied.Count > 0;
    }
    /// 
    /// Indicates whether the current user as defined by
    /// 
    /// is explicitly denied write access to the property.
    /// 
    /// Name of the property.
    public bool IsWriteDenied(string propertyName)
    {
      System.Security.Principal.IPrincipal user = ApplicationContext.User;
      if (InstanceRules.GetRolesForProperty(propertyName).IsWriteDenied(user))
        return true;
      return TypeRules.GetRolesForProperty(propertyName).IsWriteDenied(user);
    }
    #endregion
  }
}