using System;
namespace Csla.Validation
{
  /// 
  /// Tracks all information for a rule.
  /// 
  internal class RuleMethod : IRuleMethod, IComparable, IComparable
  {
    private RuleHandler _handler;
    private string _ruleName = String.Empty;
    private RuleArgs _args;
    private int _priority;
    /// 
    /// Returns the name of the method implementing the rule
    /// and the property, field or column name to which the
    /// rule applies.
    /// 
    public override string ToString()
    {
      return _ruleName;
    }
    /// 
    /// Gets the priority of the rule method.
    /// 
    /// The priority value
    /// 
    /// Priorities are processed in descending
    /// order, so priority 0 is processed
    /// before priority 1, etc.
    /// 
    public int Priority
    {
      get { return _priority; }
    }
    /// 
    /// Gets the name of the rule.
    /// 
    /// 
    /// The rule's name must be unique and is used
    /// to identify a broken rule in the BrokenRules
    /// collection.
    /// 
    public string RuleName
    {
      get { return _ruleName; }
    }
    /// 
    /// Returns the name of the field, property or column
    /// to which the rule applies.
    /// 
    public RuleArgs RuleArgs
    {
      get { return _args; }
    }
    /// 
    /// Creates and initializes the rule.
    /// 
    /// The address of the method implementing the rule.
    /// A RuleArgs object.
    public RuleMethod(RuleHandler handler, RuleArgs args)
    {
      _handler = handler;
      _args = args;
      _ruleName = string.Format(@"rule://{0}/{1}", _handler.Method.Name, _args.ToString());
    }
    /// 
    /// Creates and initializes the rule.
    /// 
    /// The address of the method implementing the rule.
    /// A RuleArgs object.
    /// 
    /// Priority for processing the rule (smaller numbers have higher priority, default=0).
    /// 
    public RuleMethod(RuleHandler handler, RuleArgs args, int priority)
      : this(handler, args)
    {
      _priority = priority;
    }
    /// 
    /// Invokes the rule to validate the data.
    /// 
    /// 
    ///  if the data is valid, 
    ///  if the data is invalid.
    /// 
    public bool Invoke(object target)
    {
      return _handler.Invoke(target, _args);
    }
    #region IComparable
    int IComparable.CompareTo(object obj)
    {
      return Priority.CompareTo(((IRuleMethod)obj).Priority);
    }
    int IComparable.CompareTo(IRuleMethod other)
    {
      return Priority.CompareTo(other.Priority);
    }
    #endregion
  }
  /// 
  /// Tracks all information for a rule.
  /// 
  /// Type of the target object.
  /// Type of the arguments parameter.
  internal class RuleMethod 
    : IRuleMethod, IComparable, IComparable 
    where R : RuleArgs
  {
    private RuleHandler _handler;
    private string _ruleName = string.Empty;
    private R _args;
    private int _priority;
    /// 
    /// Returns the name of the method implementing the rule
    /// and the property, field or column name to which the
    /// rule applies.
    /// 
    public override string ToString()
    {
      return _ruleName;
    }
    /// 
    /// Gets the priority of the rule method.
    /// 
    /// The priority value
    /// 
    /// Priorities are processed in descending
    /// order, so priority 0 is processed
    /// before priority 1, etc.
    /// 
    public int Priority
    {
      get { return _priority; }
    }
    /// 
    /// Gets the name of the rule.
    /// 
    /// 
    /// The rule's name must be unique and is used
    /// to identify a broken rule in the BrokenRules
    /// collection.
    /// 
    public string RuleName
    {
      get {return _ruleName;}
    }
    /// 
    /// Returns the name of the field, property or column
    /// to which the rule applies.
    /// 
    RuleArgs IRuleMethod.RuleArgs
    {
      get {return this.RuleArgs;}
    }
    /// 
    /// Returns the name of the field, property or column
    /// to which the rule applies.
    /// 
    public R RuleArgs
    {
      get { return _args; }
    }
    /// 
    /// Creates and initializes the rule.
    /// 
    /// The address of the method implementing the rule.
    /// A RuleArgs object.
    public RuleMethod(RuleHandler handler, R args)
    {
      _handler = handler;
      _args = args;
      _ruleName = string.Format(@"rule://{0}/{1}", _handler.Method.Name, _args.ToString());
    }
    /// 
    /// Creates and initializes the rule.
    /// 
    /// The address of the method implementing the rule.
    /// A RuleArgs object.
    /// 
    /// Priority for processing the rule (smaller numbers have higher priority, default=0).
    /// 
    public RuleMethod(RuleHandler handler, R args, int priority)
      : this(handler, args)
    {
      _priority = priority;
    }
    /// 
    /// Invokes the rule to validate the data.
    /// 
    /// True if the data is valid, False if the data is invalid.
    bool IRuleMethod.Invoke(object target)
    {
      return this.Invoke((T)target);
    }
    /// 
    /// Invokes the rule to validate the data.
    /// 
    /// 
    ///  if the data is valid, 
    ///  if the data is invalid.
    /// 
    public bool Invoke(T target)
    {
      return _handler.Invoke(target, _args);
    }
    #region IComparable
    int IComparable.CompareTo(object obj)
    {
      return Priority.CompareTo(((IRuleMethod)obj).Priority);
    }
    int IComparable.CompareTo(IRuleMethod other)
    {
      return Priority.CompareTo(other.Priority);
    }
    #endregion
  }
}