//==============================================================
//  版权所有：深圳杰文科技
//  文件名：DataVerifier.cs
//  版本：V1.0  
//  创建者：Jay  ( QQ： 85363208 )
//  创建时间：2017-11-28 16:18
//  创建描述：
//  修改者：
//  修改时间：
//  修改说明： 
//==============================================================

using System;
using System.Linq;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;

namespace Infrastructure.Utilities
{
	/// <summary>
	/// 数据校验。
	/// </summary>
	//[DebuggerStepThrough]
	public class DataVerifier
	{
		private StringBuilder content = new StringBuilder();

		public event Action<bool> Verified;

		public DataVerifier()
		{
			Pass = true;
			PromptThrowException = true;
		}

		public DataVerifier(string title, params object[] args)
			: this(true, null, title, args)
		{
		}

		public DataVerifier(Type customExceptionType)
			: this(true, customExceptionType, "")
		{
		}

		public DataVerifier(bool promptThrowException, Type customExceptionType)
			: this(promptThrowException, customExceptionType, "")
		{
		}

		public DataVerifier(bool promptThrowException, Type customExceptionType, string title, params object[] args)
			: this()
		{
			this.PromptThrowException = promptThrowException;
			this.customExceptionType = customExceptionType;
			this.Title = string.Format(title, args);
		}

		private Type customExceptionType = null;
		/// <summary>
		/// 要抛出的异常的类型。
		/// </summary>
		public Type CustomExceptionType
		{
			get
			{
				return customExceptionType;
			}
			set
			{
				if (!value.IsAssignableFrom(typeof(Exception)))
				{
					throw new Exception("CustomExceptionType必须继承自Exception");
				}
				customExceptionType = value;
			}
		}

		/// <summary>
		/// 是否即时抛出异常。当检测到第一个校验未通过时，直接抛出错误。
		/// 如果需要抛出自定义类型的异常，请给CustomExceptionType指定自定义异常的类型；否则将默认抛出Exception异常。
		/// </summary>
		public bool PromptThrowException
		{
			get;
			set;
		}

		public string Title
		{
			get;
			set;
		}

		private void RaiseVerified(bool expression)
		{
			if (Verified != null)
			{
				Verified(expression);
			}
		}

		public void AddContent(string msg, params object[] args)
		{
			Check(1 == 1, msg, args);
		}

		//此方法通常用于比较耗时、耗资源的检查。
		//其思路为：因为本次检查太耗时，如果前面有未通过的检查，那么本次检查就可以跳过了。
		public DataVerifier CheckIfBeforePass(bool expression, string msg, params object[] args)
		{
			if (Pass)
			{
				return Check(expression, msg, args);
			}
			return this;
		}

		public DataVerifier Check(bool expression, string msg, params object[] args)
		{
			if (Pass) //只要有一项校验未通过，即算整个校验未通过。
			{
				Pass = !expression;
			}
			if (!(msg.EndsWith("！") || msg.EndsWith("!") || msg.EndsWith("。") || msg.EndsWith(".")))
			{
				msg += "！";
			}
			content.Append(expression ? string.Format(msg, args) + "\r\n" : "");

			RaiseVerified(expression);

			if (PromptThrowException) //如果是即时抛出错误，
			{
				ThrowExceptionIfFailed();
			}
			return this;
		}

		public void Check(bool expression, Action beforeAction, string msg, params object[] args)
		{
			beforeAction();
			Check(expression, msg);
		}

		public bool Pass
		{
			get;
			private set;
		}

		public string Content
		{
			get
			{
				return content.ToString();
			}
			set
			{
				content.AppendLine(value);
			}
		}

		/// <summary>
		/// 如果校验失败，那么显示错误信息，否则不显示任何提示。
		/// </summary>
		public DataVerifier ShowMsgIfFailed()
		{
			if (!Pass)
			{
				MessageBox.Show(GetContent(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
			return this;
		}

		/// <summary>
		/// 如果检验失败，那么用自定义的方式显示信息，否则不显示任何提示。
		/// </summary>
		/// <param name="showMsgMethod"></param>
		public DataVerifier CustomShowMsgIfFailed(Action<string> showMsgMethod)
		{
			if (!Pass && showMsgMethod != null)
			{
				showMsgMethod(GetContent());
			}
			return this;
		}

		/// <summary>
		/// 如果检验失败，那么抛出异常。
		/// </summary>
		public void ThrowExceptionIfFailed()
		{
			if (!Pass)
			{
				Exception e = null;
				if (CustomExceptionType == null)
				{
					e = new Exception(GetContent());
				}
				else
				{
					e = Activator.CreateInstance(CustomExceptionType, GetContent()) as Exception;
				}
				throw e;
			}
		}

		private string GetContent()
		{
			return Title + "\r\n" + Content;
		}

	}
}
