package com.nbclass.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CommonUtils {

	protected static Logger logger = LoggerFactory.getLogger(CommonUtils.class);


	/**
	 * 转换Date类型为字符串类型
	 * 
	 * @param value
	 * @return
	 */
	public static String getSimpleDate(Date value) {
		return getSimpleDate(value, "yyyy-MM-dd HH:mm:ss");
	}
	
	/**
	 * 转换Date类型为中文字符串类型
	 * 
	 * @param value
	 * @return
	 */
	public static String getChinieseDate(Date value) {
		return getSimpleDate(value, "yyyy年MM月dd日HH时mm分");
	}

	/**
	 * 转换Date类型为字符串类型
	 * 
	 * @param value
	 * @return
	 */
	public static String getSimpleDate(Date value, String pattern) {
		SimpleDateFormat formatter = new SimpleDateFormat(pattern);
		return formatter.format(value);
	}

	/**
	 * 判断字符串是否空或空字符串
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isEmpty(String str) {
		if (str == null || str.trim().length() == 0) {
			return true;
		}
		return false;
	}

	/**
	 * 判断字符串是否为非空
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNotEmpty(String str) {
		if (str == null || str.trim().length() == 0) {
			return false;
		}
		return true;
	}

	/**
	 * 返回trim后的字符串，如空字符串，则直接返回空。
	 * 
	 * @param str
	 * @return
	 */
	public static String trimToEmpty(String str) {
		if (str == null || str.trim().length() == 0) {
			return null;
		}
		return str.trim();
	}

	/**
	 * 返回trim后的字符串，如果为null,则返回""
	 * 
	 * @param str
	 * @return
	 */
	public static String trimToEmptyForce(String str) {
		if (str == null || str.trim().length() == 0) {
			return "";
		}
		return str.trim();
	}

	/**
	 * 判断字符是否为数值型
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNumeric(String str) {
		try {
			Integer.parseInt(str);
			return true;
		} catch (NumberFormatException e) {
			return false;
		}

	}

	/**
	 * 获取几月后的时间
	 * 
	 * @param d
	 * @param d
	 * @return
	 */
	public static Date nextMonth(Date d, int m) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		now.set(Calendar.MONTH, now.get(Calendar.MONTH) + m);
		return now.getTime();
	}

	/**
	 * 获取几天后的时间
	 * 
	 * @param d
	 * @param day
	 * @return
	 */
	public static Date nextDate(Date d, int day) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
		return now.getTime();
	}

	/**
	 * 获取几小时后的时间
	 * 
	 * @param d
	 * @param d
	 * @return
	 */
	public static Date nextHour(Date d, int hour) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		now.set(Calendar.HOUR_OF_DAY, now.get(Calendar.HOUR_OF_DAY) + hour);
		return now.getTime();
	}

	/**
	 * 获取几分钟后的时间
	 * 
	 * @param d
	 * @param minute
	 * @return
	 */
	public static Date nextMinute(Date d, int minute) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		now.set(Calendar.MINUTE, now.get(Calendar.MINUTE) + minute);
		return now.getTime();
	}

	/**
	 * 获取两个日期的间隔天数
	 * 
	 * @param startDay
	 * @param endDay
	 * @return
	 */
	public static int dayInterval(Date startDay, Date endDay) {
		return (int) ((endDay.getTime() - startDay.getTime()) / (24 * 60 * 60 * 1000));
	}

	/**
	 * 转换String类型为Date类型
	 * 
	 * @param value
	 * @return
	 * @throws java.text.ParseException
	 */
	public static Date getSimpleDate(String value){
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			return formatter.parse(value);
		} catch (ParseException e) {
		}
		return null;
	}

	/**
	 * 转换String类型为Date类型
	 * 
	 * @param value
	 * @return
	 * @throws java.text.ParseException
	 */
	public static Date getSimpleDateBy(String value, String pattern){
		SimpleDateFormat formatter = new SimpleDateFormat(pattern);
		try {
			return formatter.parse(value);
		} catch (ParseException e) {
		}
		return null;
	}

	/**
	 * 转换String类型为Date类型
	 * 
	 * @param value
	 * @return
	 * @throws java.text.ParseException
	 */
	public static Date getSimpleDate2(String value) throws ParseException {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		return formatter.parse(value);
	}

	/**
	 * 把时分秒置为0
	 * 
	 * @param date
	 * @return
	 */
	public static Date getDateOnly(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	/**
	 * 首字母大写
	 * 
	 * @param name
	 * @return
	 */
	public static String getUpperName(String name) {
		byte[] items = name.getBytes();
		items[0] = (byte) ((char) items[0] - 'a' + 'A');
		return new String(items);
	}

	/**
	 * 判断字符串是否合法(不含有非法字符或中文) 若数组中其中一字符串含有非法字符，返回false，反之，返回true
	 * 
	 * @param sarray
	 * @return
	 */
	public static boolean judgeIllegalChar(String[] sarray) {
		boolean result = true;
		if (sarray != null) {
			Pattern pattern = Pattern.compile("^\\w+$");
			for (int i = 0; i < sarray.length; i++) {
				if (!pattern.matcher(sarray[i]).matches()) {
					result = false;
					break;
				}
			}
		} else {
			result = false;
		}
		return result;
	}

	/**
	 * 判断字符串是否为合法邮箱
	 * 
	 * @param email
	 * @return
	 */
	public static boolean judgeEmail(String email) {
		boolean result = false;
		if (email != null) {
			Pattern pattern = Pattern
					.compile("^([a-z0-9A-Z._-])+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$");
			if (pattern.matcher(email).matches()) {
				result = true;
			}
		}
		return result;
	}

	/**
	 * 判断字符串是否合法(不含有非法字符，可含中文) 若数组中其中一字符串含有非法字符，返回false，反之，返回true
	 * 
	 * @param sarray
	 * @return
	 */
	public static boolean judgeIllegalCharAndChinese(String[] sarray) {
		boolean result = true;
		if (sarray != null) {
			Pattern pattern = Pattern.compile("^[\u4e00-\u9fa5a-zA-Z0-9_-]+$");
			for (int i = 0; i < sarray.length; i++) {
				if (sarray[i] == null || !pattern.matcher(sarray[i]).matches()) {
					result = false;
					break;
				}
			}
		} else {
			result = false;
		}
		return result;
	}

	/**
	 * 判断字符串是否合法(不含 ' 字符，可含中文) 若数组中其中一字符串含有非法字符，返回false，反之，返回true
	 * 
	 * @param sarray
	 * @return
	 */
	public static boolean judgePartIllegalCharAndChinese(String[] sarray) {
		boolean result = true;
		if (sarray != null) {
			Pattern pattern = Pattern.compile("[^\']+");
			for (int i = 0; i < sarray.length; i++) {
				if (sarray[i] == null || !pattern.matcher(sarray[i]).matches()) {
					result = false;
					break;
				}
			}
		} else {
			result = false;
		}
		return result;
	}

	public static String apiEncode(Integer uid, Integer wuid) {
		String randString = UUID.randomUUID().toString();
		String startString = randString.substring(0, 4);
		String endString = randString.substring(0, 10);
		String midString = "C";
		wuid = wuid << 2;
		uid = uid << 3;
		return startString + uid + midString + wuid + endString;
	}

	public static Integer[] apiDecode(String key) {
		key = key.substring(0, key.length() - 10).substring(4);
		String[] array = key.split("C");
		Integer uid = Integer.parseInt(array[0]);
		uid = uid >> 3;
		Integer wuid = Integer.parseInt(array[1]);
		wuid = wuid >> 2;
		return new Integer[] { uid, wuid };
	}

	/**
	 * 分享链接编码
	 * 
	 * @param uid
	 * @return
	 */
	public static String shareEncode(Integer uid) {
		String randString = UUID.randomUUID().toString();
		String startString = randString.substring(0, 4);
		String endString = randString.substring(0, 10);
		String midString = "C";
		uid = uid << 3;
		return startString + uid + midString + endString;
	}

	/**
	 * 分享链接解码
	 * 
	 * @param key
	 * @return
	 */
	public static Integer shareDecode(String key) {
		key = key.substring(0, key.length() - 10).substring(4);
		String[] array = key.split("C");
		Integer uid = Integer.parseInt(array[0]);
		uid = uid >> 3;
		return uid;
	}

	/**
	 * 截取左边max个字符,ascll码大于255算两个字符，字符过长以...结尾
	 * 
	 * @param s
	 * @param max
	 * @return
	 */
	public static String left(String s, int max) {
		char[] cs = s.toCharArray();
		int count = 0;
		int last = cs.length;
		for (int i = 0, len = last; i < len; i++) {
			if (cs[i] > 255) {
				count += 2;
			} else {
				count++;
			}
			if (count > max) {
				last = i + 1;
				break;
			}
		}
		if (count <= max) {
			return s;
		}
		max -= 3;
		for (int i = last - 1; i >= 0; i--) {
			if (cs[i] > 255) {
				count -= 2;
			} else {
				count--;
			}
			if (count <= max) {
				return s.substring(0, i) + "...";
			}
		}
		return "...";
	}

	/**
	 * 从指定的时间截取年月日。将时分秒毫秒都设置为0
	 * 
	 * @param source
	 *            原始时间
	 * @return 将时分秒毫秒都设置为0的日期
	 */
	public static Date trimDate(Date source) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(source);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	/**
	 * 获取字符串的长度，中文占一个字符,英文数字占半个字符
	 * 
	 * @param value
	 *            指定的字符串
	 * @return 字符串的长度
	 */
	public static double length(String value) {
		double valueLength = 0;
		String chinese = "[\u4e00-\u9fa5]";
		for (int i = 0; i < value.length(); i++) {
			String temp = value.substring(i, i + 1);
			if (temp.matches(chinese)) {
				valueLength += 1;
			} else {
				valueLength += 0.5;
			}
		}
		return Math.ceil(valueLength);
	}

	/**
	 * 生成一个随机码
	 * 
	 * @return
	 */
	/*
	public static String getRandomCode() {
		SimpleDateFormat millSecondFormat = new SimpleDateFormat(
				"yyyyMMddHHmmssSSS");
		String prefix = millSecondFormat.format(new Date());
		Random random = new Random();
		int number = random.nextInt(100);
		return prefix + number;
	}
	*/

	/**
	 * 计算两个时间之间的秒数，注意不能超过50年
	 * @param start 开始时间
	 * @param end 结束时间
	 * @return
	 */
	public static int calSecondsBetween(Date start, Date end) {
		long times = (end.getTime() - start.getTime()) / 1000;
		return (int)times;
	}
	
	public static java.sql.Date UtilDateToSQLDate(Date utilDate) {
		if (utilDate == null) return null;
		return new java.sql.Date(utilDate.getTime());
	}
	
	public static Timestamp UtilDateToSQLTimestamp(Date utilDate){
		if (utilDate == null) return null;
		return new Timestamp(utilDate.getTime());
	}

	public static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])|(16[6])|(17[0-3,5-8])|(18[0-9])|(19[89]))\\d{8}$";

	/**
	 * 验证手机号（精确）
	 * @param phone 待验证文本
	 * @return {@code true}: 匹配<br>{@code false}: 不匹配
	 */
	public static boolean isMobile(String phone) {
	     boolean result = StringUtils.isNotBlank(phone) && Pattern.matches(REGEX_MOBILE_EXACT, phone);
	     return result;
	}
	
	/**
	 * 获取随机代码
	 * @param length 需要的长度
	 * @return
	 */
	public static String getRandomCode(int length) {
		char[] chs = { 'a', 'b', 'c', '1', '2', '3', 'd', 'e', 'f',
				'A', 'B', 'C', 'D', 'E', 'F',
				'4', '5',
				'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
				'6', '8',
				'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
				's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '6', '7', '8', '9',
				'2', '5', '9',
				'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
		SecureRandom random = new SecureRandom();
		char[] value = new char[length];
		for (int i = 0; i < length; i++) {
			value[i] = chs[random.nextInt(chs.length)];
		}
		String code = new String(value);
		return code;
	}

	public static int getValidInt(String str){
    	return getValidInt(str, -1);
    }
	
	public static int getValidInt(String str, int defaultVal){
    	int result = defaultVal;
    	try {
			if(StringUtils.isNotBlank(str)){
				result = Integer.parseInt(str);
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
    	return result;
    }

	/**
	 * 封装JDK自带的UUID, 通过Random数字生成, 中间无-分割.
	 */
	public static String getUUID() {
		String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
		//uuid = uuid + "|yupenxiqi";
		if(uuid.length() > 28)uuid = uuid.substring(0, 28);
		return uuid;
	}
	
	public static String getOpenId(String prefix) {
		int length = 28;
		if(StringUtils.isNotBlank(prefix)){
			length -= prefix.length();
		}
		
		char[] chs = { 'a', 'b', 'c', '1', '2', '3', 'd', 'e', 'f',
				'A', 'B', 'C', 'D', 'E', 'F',
				'4', '5',
				'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
				'6', '8',
				'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
				's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '6', '7', '8', '9',
				'2', '5', '9',
				'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
		SecureRandom random = new SecureRandom();
		char[] value = new char[length];
		for (int i = 0; i < length; i++) {
			value[i] = chs[random.nextInt(chs.length)];
		}
		String code = new String(value);
		if(StringUtils.isNotBlank(prefix)){
			code = prefix+code;
		}
		return code;
	}
	
	
    /**
     * 向URL中添加参数(有则修改，无则添加)
     * @param url
     * @param ParamName
     * @param ParamValue
     * @return
     */
	public static String addParamValue(String url, String ParamName, String ParamValue) {
        if(StringUtils.isNotBlank(url) && StringUtils.isNotBlank(ParamName) && StringUtils.isNotBlank(ParamValue)) {
            if(url.contains(ParamName+"=")){
            	url = replaceParamValue(url, ParamName, ParamValue);
            }else{
            	if(url.contains("?") || url.contains("\\?")){
                	url += "&"+ParamName+"=" + ParamValue;
                }else{
                	url += "?"+ParamName+"=" + ParamValue;
                }
            }
        }
        return url;
    }
    
    /**
     * 替换URL参数的值
     * @param url
     * @param ParamName
     * @param ParamValue
     * @return
     */
	public static String replaceParamValue(String url, String ParamName, String ParamValue) {
		if(StringUtils.isNotBlank(url) && StringUtils.isNotBlank(ParamName) && StringUtils.isNotBlank(ParamValue)) {
            url = url.replaceAll("(\\?" + ParamName +"=[^&]*)", "?"+ParamName + "=" + ParamValue);
            url = url.replaceAll("(\\&" + ParamName +"=[^&]*)", "&"+ParamName + "=" + ParamValue);
        }
        return url;
    }
	
	/**
	 * 删除URL中的参数
	 * @param url
	 * @param ParamName
	 * @return
	 */
	public static String removeParamValue(String url, String ParamName) {
        if(StringUtils.isNotBlank(url) && StringUtils.isNotBlank(ParamName)) {
        	while(url.contains("?"+ParamName+"=") || url.contains("%3f"+ParamName+"%3d") || url.contains("%3F"+ParamName+"%3D")
        		|| url.contains("&"+ParamName+"=") || url.contains("%26"+ParamName+"%3d") || url.contains("%26"+ParamName+"%3D")){
        		url = url.replaceAll("(\\?" + ParamName +"=[^&]*)", "");
            	url = url.replaceAll("(%3f" + ParamName +"%3d[^&]*)", "");
                url = url.replaceAll("(%3F" + ParamName +"%3D[^&]*)", "");
                
            	url = url.replaceAll("(\\&" + ParamName +"=[^&]*)", "");
            	url = url.replaceAll("(%26" + ParamName +"%3d[^&]*)", "");
                url = url.replaceAll("(%26" + ParamName +"%3D[^&]*)", "");
            }
        }
        return url;
    }
    
	/**
	 * 优惠码的生成
	 * @return
	 */
	public static String getCode(int length) {
		char[] chs = { 'a', 'b', 'c', '1', '2', '3', '4', '5', 'd', 'e', 'f',
				'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
				's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '6', '7', '8', '9' };
		SecureRandom random = new SecureRandom();
		final char[] value = new char[length];
		for (int i = 0; i < length; i++) {
			value[i] = chs[random.nextInt(chs.length)];
		}
		final String code = new String(value);
		return code;
	}
	
	/**
	 * 生成随机邀请码
	 * @return
	 */
	public static String getInvitecode() {
		int length = 4;
		char[] chs = { 'A', 'B', 'C', '1', '2', '3', '4', '5', 'D', 'E', 'F',
				'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R',
				'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '6', '7', '8', '9' };
		SecureRandom random = new SecureRandom();
		final char[] value = new char[length];
		for (int i = 0; i < length; i++) {
			value[i] = chs[random.nextInt(chs.length)];
		}
		final String code = new String(value);
		return code;
	}

	public static int[] toIntArray(String[] array) {
		int[] result = new int[array.length];
		int count = 0;
		for (int i = 0; i < array.length; i++) {
			if (array[i] != null && !array[i].trim().equals("") && !array[i].trim().equals("undefined"))
				result[count++] = Integer.parseInt(array[i]);
		}
		return result;
	}

	public static int[] toIntArray(ArrayList<String> array){
		int[] result = new int[array.size()];
		int count = 0;
		for (int i = 0; i < array.size(); i++) {
			String item = array.get(i);
			if (item != null && !item.trim().equals(""))
				result[count++] = Integer.parseInt(item);
		}
		return result;
	}
	
	public static int[] toIntArray(String str){
		if(str == null || str.equals("")) return null;
		int[] result;
		if(str.indexOf(",")!=-1){
			String[] strArr = str.split(",");
			result =toIntArray(strArr);
		}else{
			result = new int[]{Integer.parseInt(str)};
		}
		return result;
	}
	
	public static List<Integer> toIntList(String str){
		List<Integer> idList = null;
		if(str == null || str.equals("")) return null;
		int[] result = toIntArray(str);
		if(result!=null && result.length>0){
			idList = new ArrayList<Integer>();
			for (int id : result) {
				idList.add(id);
			}
		}
		return idList;
	}

	
	public static long[] toLongArray(String[] array) {
		long[] result = new long[array.length];
		int count = 0;
		for (int i = 0; i < array.length; i++) {
			if (array[i] != null && !array[i].trim().equals("") && !array[i].trim().equals("undefined"))
				result[count++] = Long.parseLong(array[i]);
		}
		return result;
	}
	
	public static long[] toLongArray(String str){
		if(str == null || str.equals("")) return null;
		long[] result;
		if(str.indexOf(",")!=-1){
			String[] strArr = str.split(",");
			result = toLongArray(strArr);
		}else{
			result = new long[]{Long.parseLong(str)};
		}
		return result;
	}
	
	public static List<Long> toLongList(String str){
		List<Long> idList = null;
		if(str == null || str.equals("")) return null;
		long[] result = toLongArray(str);
		if(result!=null && result.length>0){
			idList = new ArrayList<Long>();
			for (long id : result) {
				idList.add(id);
			}
		}
		return idList;
	}
	
	/**
	 * 获取请求URL，到ContextPath止
	 * @param request
	 * @return
	 */
	public static String getBaseUrl(HttpServletRequest request){
		String result = null;
		int port = request.getServerPort();
		result = request.getScheme()+"://"+request.getServerName()+(port==80||port==443 ? "" : ":"+port)+request.getContextPath()+"/";
		return result;
	}
	
	/**
	 * 获取服务器IP地址
	 * @return
	 */
	public static String getHostIP(){
		String hostip = null;
		try {
			InetAddress address = InetAddress.getLocalHost();
			hostip = address.getHostAddress();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		return hostip;
	}
	
	/**
	 * 获取当前服务器cdn域名
	 * 国内: 39.108.10.19 - 172.18.219.193
	 * 国外: 47.88.236.90 - 172.21.7.78
	 * @return
	 */
	/**
	 * 是否是内网
	 * @return
	 */
	public static boolean isNw(){
		boolean isnw = false;
		String hostip = getHostIP();
		if(hostip.startsWith("172.") || hostip.startsWith("10.")){
			isnw = true;
		}
		return isnw;
	}

	/**
	 * str数组转list
	 * @param str
	 * @return
	 */
	public static ArrayList<String> str2List(String str){
		ArrayList<String> list = new ArrayList<>();
		if(str!=null && str.trim().length()>0){
			if(str.indexOf(",")!=-1){
				String[] arr = str.split(",");
				for (String string : arr) {
					list.add(string);
				}
			}else{
				list.add(str);
			}
		}
		return list;
	}

	public static void main(String[] args) {
		for (int i=0; i < 10; i++) {
			System.out.println(getInvitecode());
		}
	}
}
