package cn.util.core;

import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.lang3.StringUtils;
import cn.constant.HttpConst;
import cn.constant.RegExp;
import cn.util.string.StringKit;

public class IsKit 
{
	/**
	 * 是否空白符<br>
	 * 空白符包括空格、制表符、全角空格和不间断空格<br>
	 *
	 * @param c 字符
	 * @return 是否空白符
	 */
	public static boolean isBlankChar(int c) {
		return Character.isWhitespace(c)
				|| Character.isSpaceChar(c)
				|| c == '\ufeff'
				|| c == '\u202a'
				|| c == '\u0000';
	}
	/**
	 * 是否空白符<br>
	 * 空白符包括空格、制表符、全角空格和不间断空格<br>
	 *
	 * @param c 字符
	 * @return 是否空白符
	 */
	public static boolean isBlankChar(char c) {
		return isBlankChar((int) c);
	}
	//判断字符串非空白
	public static boolean isNotBlank(CharSequence str) {
		//isBlank 方法返回 false 即可
		return false == isBlank(str);
	}
	//判断字符串是否为空白，空白的定义为：null、空白字符
	public static boolean isBlank(CharSequence str) {
		//字符串长度
		int length;

		//如果字符串为null 或者字符串长度等于0，直接返回 true
		if ((str == null) || ((length = str.length()) == 0)) {
			return true;
		}
		for (int i = 0; i < length; i++) {
			// 迭代检查字符串每个字符，只要有一个非空字符即为非空字符串
			if (false == isBlankChar(str.charAt(i))) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 检测字符串是否为空(null,"","null")
	 * 判断对象是否为空或者传入集合对象的是否为空，以及判断数组的长度 
	 * Object、String、List、ArrayList、Map、HashMap、Vector、Hashtable、LinkedList、TreeSet
	 * Set、 Iterator、LinkedHashMap、LinkedHashSet、WeakHashMap、SortedMap等
	 * 为空则返回true，不否则返回false
	 */
	public static boolean isNullOrEmpty(Object obj)
	{  
		if (obj == null || "NULL".equals(obj) 
				|| "null".equals(obj) || "".equals(obj)
				|| "[]".equals(obj) || "{}".equals(obj)
				|| "undefined".equals(obj))//页面js变量没有赋值 
		{
			return true;
		}
		if (obj instanceof String) {
			return StringUtils.isEmpty(StringUtils.trim((String)obj));
		}
		if ((obj instanceof Map)){
			return ((Map<?, ?>) obj).isEmpty();
		}
		if ((obj instanceof List)){
			return ((List<?>) obj).isEmpty();
		}
		Method method = null;  
		String newInput = "";  
		try {  
			method = obj.getClass().getMethod("size");  
			newInput = String.valueOf(method.invoke(obj));    
			if (Integer.parseInt(newInput) == 0) {    
				return true;  
			} else {  
				return false;  
			}  
		}
		catch (Exception e)
		{  
			try {   
				method = obj.getClass().getMethod("getItemCount");  
				newInput = String.valueOf(method.invoke(obj));    
				if (Integer.parseInt(newInput) == 0)     
				{
					return true;
				}
				else {   
					return false;
				}
			} catch (Exception ex) {  
				try{    
					if (Array.getLength(obj) == 0){  
						return true;  
					}
					else   
					{
						return false;
					}
				} catch (Exception exx) {  
					try{  
						method = Iterator.class.getMethod("hasNext");    
						newInput = String.valueOf(method.invoke(obj));    
						if (!Boolean.valueOf(newInput)) {   
							return true;  
						}
						else {   
							return false;
						}
					} catch (Exception exxx) {  
						return false;  
					}  
				}  
			}  
		}  
	}
	public static boolean isNotNullOrEmpty(Object object) {
		return !isNullOrEmpty(object);
	}
	/** 空返回True*/  
	public static boolean isEmpty(Object object)
	{
		if (object == null) {
			return true;
		} 
		if ("".equals(object)) {
			return (true);
		}
		if ("null".equals(object)) {
			return (true);
		}
		if (object instanceof Integer) {
			return Integer.valueOf(object.toString()) == 0;
		}
		if (object instanceof Long) {
			return Long.valueOf(object.toString()) == 0L;
		}
		if (object instanceof String) {
			return ((String)object).trim().length() == 0;
		}
		if (object instanceof StringBuffer) {
			return ((StringBuffer)object).toString().trim().length() == 0;
		}
		if (object instanceof Boolean) {
			return Boolean.valueOf(object.toString());
		}
		if (object instanceof List) {
			return ((List<?>)object).size() == 0;
		} 
		if (object instanceof Set) {
			return ((Set<?>)object).size() == 0;
		} 
		if (object instanceof Map) {
			return ((Map<?, ?>)object).size() == 0;
		}
		if (object instanceof Iterator) {
			return !((Iterator<?>)object).hasNext();
		}
		if (object.getClass().isArray()) {
			return Arrays.asList(object).size() == 0;
		}
		return false;
	}
	/**
	 * * 判断一个Collection是否为空， 包含List，Set，Queue
	 *
	 *要判断的Collection
	 *true：为空 false：非空
	 */
	public static boolean isEmpty(Collection<?> collection){
		return collection == null || collection.isEmpty();
	}
	public static boolean isEmpty(byte[] data) {
		return data == null || data.length == 0;
	}

	/**
	 * * 判断一个对象数组是否为空
	 *
	 * @param objects 要判断的对象数组
	 * @return true：为空 false：非空
	 */
	public static boolean isEmpty(Object[] objects) {
		return isNull(objects) || (objects.length == 0);
	}

	/** 不空返回True*/
	public static boolean isNotEmpty(Object object) 
	{
		if (object == null) {
			return false;
		} else if (object instanceof Integer) {
			return Integer.valueOf(object.toString()) > 0;
		} else if (object instanceof Long) {
			return Long.valueOf(object.toString()) > 0L;
		} else if (object instanceof String) {
			return ((String)object).trim().length() > 0;
		} else if (object instanceof StringBuffer) {
			return ((StringBuffer)object).toString().trim().length() > 0;
		} else if (object instanceof Boolean) {
			return Boolean.valueOf(object.toString());
		} else if (object instanceof List) {
			return ((List<?>)object).size() > 0;
		} else if (object instanceof Set) {
			return ((Set<?>)object).size() > 0;
		} else if (object instanceof Map) {
			return ((Map<?, ?>)object).size() > 0;
		} else if (object instanceof Iterator) {
			return ((Iterator<?>)object).hasNext();
		} else if (object.getClass().isArray()) {
			return Arrays.asList(object).size() > 0;
		} else {
			return true;
		}
	}
	/**
	 * * 判断一个对象数组是否非空
	 *
	 * @param objects 要判断的对象数组
	 * @return true：非空 false：空
	 */
	public static boolean isNotEmpty(Object[] objects) {
		return !isEmpty(objects);
	}
	/**
	 * * 判断一个Collection是否非空，包含List，Set，Queue
	 *
	 * @param coll 要判断的Collection
	 * @return true：非空 false：空
	 */
	public static boolean isNotEmpty(Collection<?> coll) {
		return !isEmpty(coll);
	}

	/**
	 * 判断一个对象是否为空
	 * 为空返回true;  非空返回false
	 */
	public static boolean isNull(Object obj) 
	{   //ofNullable：不空返回true
		return (!Optional.ofNullable(obj).isPresent()); 
	}

	/**
	 * * 判断一个对象是否非空
	 *
	 * @param object Object
	 * @return true：非空 false：空
	 */
	public static Boolean isNotNull(Object object) {
		return !isNull(object);
	}

	/**
	 * * 判断一个对象是否是数组类型（Java基本型别的数组）
	 *
	 * @param object 对象
	 * @return true：是数组 false：不是数组
	 */
	public static boolean isArray(Object object) {
		return isNotNull(object) && object.getClass().isArray();
	}

	//判断整数（int）
	public static boolean isInteger(String str) {
		if(IsKit.isNullOrEmpty(str)) {
			return false;
		}
		Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
		return pattern.matcher(str).matches();
	}

	//断浮点数（double和float）
	public static boolean isDouble(String str) {
		if(IsKit.isNullOrEmpty(str)) {
			return false;
		}
		Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$");
		return pattern.matcher(str).matches();
	}

	public static boolean isNumber(String str) {
		Boolean success = false;
		String re = "^-{0,1}\\d*\\.{0,1}\\d+$";
		if (StringUtils.isNotBlank(str)) {
			success = Pattern.matches(re, str);
		}
		return success;
	}	
	/**
	 * 是否纯数字
	 * @param str
	 * @return
	 */
	public static boolean isNumeric(String str)
	{
		if(IsKit.isNullOrEmpty(str)) {
			return false;
		}
		//return TimeConst.NUMERIC_REGEX.matcher(str).matches(); OR
		Pattern pattern = Pattern.compile("[0-9]*");
		return pattern.matcher(str).matches();   
	}

	/**判断yyyy-mm-dd格式类型的日期*/
	public static boolean isValidDate(String sDate) 
	{
		if ((sDate != null)) {
			Pattern pattern = Pattern.compile(RegExp.PATTERN_DATE_S);
			Matcher match = pattern.matcher(sDate);
			if (match.matches()) {
				pattern = Pattern.compile(RegExp.PATTERN_DATE);
				match = pattern.matcher(sDate);
				return match.matches();
			}
			else {
				return false;
			}
		}
		return false;
	}
	/**2018-01-22T18:23:00.000Z is the ISO 8601 format for an instant.
	 * So you may just use Instant.parse("2018-01-22T18:23:00.000Z"). 
	 * Catch a DateTimeParseException from the case where the string isn’t valid,
	 * either because it’s in the wrong format or the date and time is not valid 
	 * It will accept 2018-01-22T18:23Z and 2018-01-22T18:23:00.000000000Z too.
	 */
	public static boolean isValidUTC(String str) 
	{
		boolean convertSuccess = true;
		try {
			Instant.parse(str);
		} catch (DateTimeParseException e) {
			convertSuccess = false;
		}
		return convertSuccess;
	}

	/**
	 * 判断是JsonObject
	 * @param obj
	 * @return
	 */
	public static boolean isJsonObject(Object obj)
	{
		String content = obj.toString();
		try {
			JSONObject.parseObject(content);
			if (content.startsWith("{")) {
				return  true;
			}else {
				return  false;
			}
		} catch (Exception e) {
			return false;
		}
	}
	/**
	 * 判断是JsonArray
	 * @param obj
	 * @return
	 */
	public static boolean isJsonArray(Object obj){
		String content = obj.toString();
		try {
			JSONArray.parseArray(content);
			if (content.startsWith("[")) {
				return  true;
			}else {
				return  false;
			}
		} catch (Exception e) {
			return false;
		}
	}
	/**
	 * 是否包含字符串
	 *
	 * @param str  验证字符串
	 * @param strs 字符串组
	 * @return 包含返回true
	 */
	public static boolean isStrInArray(String str, String... strs) {
		if (str != null && strs != null) {
			for (String s : strs) {
				if (str.equalsIgnoreCase(StringKit.trim(s))) {
					return true;
				}
			}
		}
		return false;
	}	
	

	//判断某一文件(含路径)是否存在,存在返回true,不存在返回false
	public static boolean isFileExist(String filename){
		File f = new File(filename);
		if(f.exists()){
			return true;
		}
		return false;
	}

	/**
	 * 判断字段名是否在字段名的数组中
	 * @param fields 字段数组
	 * @param fieldName 给定字段名
	 * @return 给定的字段名是否在数组中
	 */
	public static boolean isInFields(Object[] fields, Object fieldName) 
	{
		boolean b = false;
		if(IsKit.isNullOrEmpty(fields)) {
			return b;
		}
		for (Object field : fields) {
			if (field.equals(fieldName)) {
				b = true;
				return b;
			}
		}
		return b;
	}
	public static boolean isInFields(List<String> fields, String fieldName) 
	{
		boolean b = false;
		if(IsKit.isNullOrEmpty(fields)) {
			return b;
		}
		for (Object field : fields) {
			if (field.equals(fieldName)) {
				b = true;
				return b;
			}
		}
		return b;
	}
	
	/**
	 * 是否为http(s)://开头
	 *
	 * @param link 链接
	 * @return 结果
	 */
	public static boolean ishttp(String link)
	{
		return StringUtils.startsWithAny(link,HttpConst.HTTP_SLASH,HttpConst.HTTPS_SLASH);
	}
}
