using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

namespace GridValidation
{
	/// <summary>
	/// Validates that at least one property is not empty.
	/// 
	/// </summary>
	[AttributeUsage(AttributeTargets.Class)]
	public class AtLeastOnePropertyNotEmptyAttribute : ValidationAttribute
	{
		/// <summary>
		/// Properties to check.
		/// 
		/// </summary>
		public string[] Properties { get; set; }

		/// <summary>
		/// Checks if at least one property is not null or white space.
		/// 
		/// </summary>
		/// <param name="value">Object representation of class to validate.</param>
		/// <returns>
		/// true, if one of the properties not null or white space, false otherwise.
		/// </returns>
		public override bool IsValid(object value)
		{
			Type type = value.GetType();
			PropertyInfo[] propertyInfoArray = type.GetProperties()
			                                       .SelectMany(propertyInfo => (IEnumerable<string>) Properties,
			                                                   (propertyInfo, propertyName) =>
			                                                   new
				                                                   {
					                                                   propertyInfo = propertyInfo,
					                                                   propertyName = propertyName
				                                                   })
			                                       .Where(param0 => param0.propertyName == param0.propertyInfo.Name)
			                                       .Select(param0 => param0.propertyInfo)
			                                       .ToArray();

			if (propertyInfoArray.Length != this.Properties.Length)
				throw new ApplicationException(string.Format("It was expected that the class {0} has {1} properties, but {2} was found", type.FullName, Properties.Length, propertyInfoArray.Length));
			
			bool flag = false;
			foreach (PropertyInfo propertyInfo in propertyInfoArray)
			{
				object obj = propertyInfo.GetValue(value, null);
				flag = !(obj is string) ? flag | obj != null : flag | !string.IsNullOrWhiteSpace((string)obj);
				if (flag)
					break;
			}
			return flag;
		}
	}
}