using Hydra.Framework.Helpers;

namespace Hydra.Framework.Specification
{
    /// <summary>
    /// Or Predicate Specification
    /// </summary>
    /// <typeparam name="TCandidate"></typeparam>
    public class OrSpecification<TCandidate>
        : AbstractSpecification<TCandidate>
    {
        #region Member Variables
        /// <summary>
        /// Left Element in the Specification
        /// </summary>
        private readonly ISpecification<TCandidate> leftSpecification;

        /// <summary>
        /// Right Element in the Specification
        /// </summary>
        private ISpecification<TCandidate> rightSpecification;
        #endregion


        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="OrSpecification&lt;TCandidate&gt;"/> class.
        /// </summary>
        /// <param name="left">The left.</param>
        public OrSpecification(ISpecification<TCandidate> left)
        {
            leftSpecification = left;
        }
        #endregion

        #region Overrides
        /// <summary>
        /// Determines whether [is satisfied by] [the specified candidate].
        /// </summary>
        /// <param name="candidate">The candidate.</param>
        /// <returns>
        /// 	<c>true</c> if [is satisfied by] [the specified candidate]; otherwise, <c>false</c>.
        /// </returns>
        public override bool IsSatisfiedBy(TCandidate candidate)
        {
            Check.That(rightSpecification, Is.Not.Null);

            return leftSpecification.IsSatisfiedBy(candidate) || 
                   rightSpecification.IsSatisfiedBy(candidate);
        }

        /// <summary>
        /// Equals the specified property name.
        /// </summary>
        /// <typeparam name="TValue">The type of the value.</typeparam>
        /// <param name="propertyName">StateName of the property.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public override ISpecificationBuilder<TCandidate> Equal<TValue>(string propertyName, TValue value)
        {
            rightSpecification = new EquateSpecification<TCandidate, TValue>(propertyName, value);

            return this;
        }
        #endregion
    }
}