/**
 * $Id: ValidationUtil.java 2138 2015-12-14 08:40:06Z wangwei $
 * Copyright(C) 2014-2020 easegame, All Rights Reserved.
 */
package com.liquidnet.commons.lang.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author <a href="mailto:wangwei@kowlone.com">kowlone</a>
 * @version 1.0 2015年11月26日 18:23:00
 */
public class ValidationUtil {

	private ValidationUtil() {}

	/**
	 * 校验对象为空
	 * @param obj 待检测对象
	 * @param logMsg 检验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：对象为空</li>
	 * <li>false：对象不为空</li>
	 */
	public static boolean checkNull(Object obj, String logMsg, Object... params) {
		return (obj == null) ? true : writeLog(logMsg, params);
	}

	/**
	 * 校验对象不为空
	 * @param obj 待检测对象
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：对象不为空</li>
	 * <li>false：对象为空</li>
	 */
	public static boolean checkNotNull(Object obj, String logMsg, Object... params) {
		return (obj != null) ? true : writeLog(logMsg, params);
	}

	/**
	 * 校验字符串为空
	 * @param str 字符串
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：字符串为空</li>
	 * <li>false：字符串不为空</li>
	 */
	public static boolean checkEmpty(String str, String logMsg, Object... params) {
		return StringUtil.isEmpty(str) ? true : writeLog(logMsg, params);
	}

	/**
	 * 校验字符串不为空
	 * @param str 字符串
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：字符串不为空</li>
	 * <li>false：字符串为空</li>
	 */
	public static boolean checkNotEmpty(String str, String logMsg, Object... params) {
		return StringUtil.isNotEmpty(str) ? true : writeLog(logMsg, params);
	}

	/**
	 * 校验两个字符串相等
	 * @param str1 字符串1
	 * @param str2 字符串2
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：字符串不为空，且内容相等</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkEquals(String str1, String str2, String logMsg, Object... params) {
		return (str1 != null && str1.equals(str2)) ? true : writeLog(logMsg, createNewArray(params, str1, str2));
	}

	/**
	 * 校验两个整数相等
	 * @param v1 整数1
	 * @param v2 整数2
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：两整数相等</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkEquals(int v1, int v2, String logMsg, Object... params) {
		return (v1 == v2) ? true : writeLog(logMsg, createNewArray(params, v1, v2));
	}

	/**
	 * 校验两个长整数相等
	 * @param v1 长整数1
	 * @param v2 长整数2
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：两整数相等</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkEquals(long v1, long v2, String logMsg, Object... params) {
		return (v1 == v2) ? true : writeLog(logMsg, createNewArray(params, v1, v2));
	}

	/**
	 * 校验两个字符串不相等
	 * @param str1 字符串1
	 * @param str2 字符串2
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：字符串不为空，且与compare内容不相等</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkNotEquals(String str1, String str2, String logMsg, Object... params) {
		return ((str1 == null && str2 == null) || (str1 != null && str1.equals(str2))) ? writeLog(logMsg, createNewArray(params, str1, str2)) : null;
	}

	/**
	 * 校验两个整数不相等
	 * @param v1 整数1
	 * @param v2 整数2
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：字符串不为空，且与compare内容不相等</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkNotEquals(int v1, int v2, String logMsg, Object... params) {
		return (v1 != v2) ? true : writeLog(logMsg, createNewArray(params, v1, v2));
	}

	/**
	 * 校验两个长整数不相等
	 * @param v1 长整数1
	 * @param v2 长整数2
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：两整数不相等</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkNotEquals(long v1, long v2, String logMsg, Object... params) {
		return (v1 != v2) ? true : writeLog(logMsg, createNewArray(params, v1, v2));
	}

	/**
	 * 校验最小值
	 * @param val 校验值
	 * @param min 最小值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：校验值大于等于最小值</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkMin(int val, int min, String logMsg, Object... params) {
		return (val >= min) ? true : writeLog(logMsg, createNewArray(params, val, min));
	}

	/**
	 * 校验最小值
	 * @param val 校验值
	 * @param min 最小值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：校验值大于等于最小值</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkMin(long val, long min, String logMsg, Object... params) {
		return (val >= min) ? true : writeLog(logMsg, createNewArray(params, val, min));
	}

	/**
	 * 校验最小值
	 * @param val 校验值
	 * @param min 最小值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：校验值大于等于最小值</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkMin(double val, double min, String logMsg, Object... params) {
		return (val >= min) ? true : writeLog(logMsg, createNewArray(params, val, min));
	}

	/**
	 * 校验最大值
	 * @param val 校验值
	 * @param max 最大值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：校验值小于等于最大值</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkMax(int val, int max, String logMsg, Object... params) {
		return (val <= max) ? true : writeLog(logMsg, createNewArray(params, val, max));
	}

	/**
	 * 校验最大值
	 * @param val 校验值
	 * @param max 最大值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：校验值小于等于最大值</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkMax(long val, long max, String logMsg, Object... params) {
		return (val <= max) ? true : writeLog(logMsg, createNewArray(params, val, max));
	}

	/**
	 * 校验最大值
	 * @param val 校验值
	 * @param max 最大值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：校验值小于等于最大值</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkMax(double val, double max, String logMsg, Object... params) {
		return (val <= max) ? true : writeLog(logMsg, createNewArray(params, val, max));
	}

	/**
	 * 校验参数是否在两个值中间
	 * @param v 待校验值
	 * @param min 校验最值
	 * @param max 校验最大值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：v1 <= v <= v2</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkBetween(int v, int min, int max, String logMsg, Object... params) {
		return ((v >= min) && (v <= max)) ? true : writeLog(logMsg, createNewArray(params, v, min, max));
	}

	/**
	 * 校验参数是否在两个值中间
	 * @param v 待校验值
	 * @param min 校验最值
	 * @param max 校验最大值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：v1 <= v <= v2</li>
	 * <li>false：其他</li>
	 */
	public static boolean checkBetween(long v, long min, long max, String logMsg, Object... params) {
		return ((v >= min) && (v <= max)) ? true : writeLog(logMsg, createNewArray(params, v, min, max));
	}

	/**
	 * 校验真
	 * @param v 待校验值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：校验值为true</li>
	 * <li>false：校验值为false</li>
	 */
	public static boolean checkTrue(boolean v, String logMsg, Object... params) {
		return v ? true : writeLog(logMsg, createNewArray(params, v));
	}

	/**
	 * 校验假
	 * @param v 待校验值
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：校验值为false</li>
	 * <li>false：校验值为true</li>
	 */
	public static boolean checkFalse(boolean v, String logMsg, Object... params) {
		return v ? writeLog(logMsg, createNewArray(params, v)) : null;
	}

	private static final String EMAIL_PATTERN = "^[\\w\\p{Punct}+@(\\w+\\p{Punct}+)+[a-zA-Z]{2,5}$";
	/**
	 * 校验email地址
	 * @param email 待校验email地址
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：合法的email地址</li>
	 * <li>false：不合法的email地址</li>
	 */
	public static boolean checkEmail(String email, String logMsg, Object... params) {
		return ((email != null) && email.matches(EMAIL_PATTERN)) ? true : writeLog(logMsg, createNewArray(params, email));
	}

	/**
	 * 校验字符串格式是否匹配指定的正则表达式
	 * @param str 待校验字符串
	 * @param regex 字符串格式
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：字符串与正则表达式匹配</li>
	 * <li>false：字符串不匹配正则表达式</li>
	 */
	public static boolean checkRegex(String str, String regex, String logMsg, Object... params) {
		return ((str != null) && str.matches(regex)) ? true : writeLog(logMsg, createNewArray(params, str, regex));
	}

	/**
	 * 校验字符串格式是否不匹配指定的正则表达式
	 * @param str 待校验字符串
	 * @param regex 字符串格式
	 * @param logMsg 校验失败时日志信息
	 * @param params 校验失败时日志参数
	 * @return
	 * <li>true：字符串与正则表达式不匹配</li>
	 * <li>false：字符串匹配正则表达式</li>
	 */
	public static boolean checkNotRegex(String str, String regex, String logMsg, Object... params) {
		return ((str != null) && str.matches(regex)) ? writeLog(logMsg, createNewArray(params, str, regex)) : null;
	}

	private static Object[] createNewArray(Object[] p1, Object... params) {
		if (p1 == null && params == null) {
            return null;
        }

		List<Object> ret = new ArrayList<>();

		for (Object param : params) {
			ret.add(param);
		}

		if (p1 != null) {
			ret.addAll(Arrays.asList(p1));
		}

		return ret.toArray();
	}

	private static boolean writeLog(String logMsg, Object... params) {
		String msg = StringUtil.isNotEmpty(logMsg) ? logMsg : "logMsg未传值";
		msg += " : " + StringUtil.joinArray(", ", params);
		return false;
	}
}
