package com.yutu.base.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.Charsets;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

public class CommonUtil {
	/**使用统一的UTF-8方式获得字符串md5值*/
    public final static String getMD5(String s) {
        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        try {
            byte[] btInput = s.getBytes("utf-8");
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

	/**
	 * 生成UUID值
	 * @return
	 */
	public static String createId(){
		UUID uid=UUID.randomUUID();//每次产生一个随机字符串,具有唯一性
		return uid.toString();
	}

	/**
	 * 如果字符串参数不为空则去掉前后空格后返回,如果字符串为空字符串则返回null
	 * @param str
	 * @return
	 */
	public static String initStr(String str){
		if(str!=null){
			str=str.trim();
			if("".equals(str)){
				str=null;
			}
		}
		return str;
	}
	/**
	 * 初始化 HttpServletResponse对象 返回输出流
	 * @param resp
	 * @return
	 * @throws IOException
	 */
	public static PrintWriter InitResponse(HttpServletResponse resp) throws IOException{
		resp.setCharacterEncoding("utf-8");//
		resp.setContentType("text/plain;charset=utf-8");
		PrintWriter pw = resp.getWriter();
		return pw;
	}
	/**
	 *
	 * @param req http请求对象
	 * @return 返回http请求字符串(utf-8编码)
	 * @throws IOException
	 */
	public static String getRequestBody(HttpServletRequest req) throws IOException{
		InputStream is=req.getInputStream();
		StringBuffer sb = new StringBuffer();
		byte[] bs = new byte[4096];
		int length = 0;
		try {
			while ((length = is.read(bs)) > 0) {
				sb.append(new String(bs, 0 , length,"utf-8"));
			}
			is.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sb.toString();
	}
	/**
	 * 判断字符串数组中的元素是否全不为空或者为空字符串
	 * @param params
	 * @return 字符串数组中有一个元素为空或空字符串则返回false,否则返回true
	 */
	public static boolean checkParameter(String[] params){
		boolean b=true;
		if(params!=null && params.length>0){
			for(int i=0;i<params.length;i++){
				if(params[i]==null || "".equals(params[i])){
					b=false;
					break;
				}
			}
		}else{
			b=false;
		}
		return b;
	}
	/**
	 * 将时间字符串转换为Timestamp类型
	 * @param timeStr 时间字符串(yyyy-MM-dd HH:mm:ss)
	 * @return
	 */
	public static Timestamp stringToTime(String timeStr){
		Timestamp ttime=null;
		if(timeStr!=null && !"".equals(timeStr)){
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			try {
				Date date=sdf.parse(timeStr);
				ttime=new Timestamp(date.getTime());
			} catch (Exception e) {
				System.out.println("时间字符串转换为Timestamp时异常");
			}
		}
		return ttime;
	}
	/**
	 * 将时间字符串转换为Timestamp类型
	 * @param timeStr 时间字符串(yyyyMMdd)
	 * @return
	 */
	public static Timestamp stringToTimeRule(String timeStr){
		Timestamp ttime=null;
		if(timeStr!=null && !"".equals(timeStr)){
			SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
			try {
				Date date=sdf.parse(timeStr);
				ttime=new Timestamp(date.getTime());
			} catch (Exception e) {
				System.out.println("时间字符串转换为Timestamp时异常");
			}
		}
		return ttime;
	}

	/**
	 * 根据指定格式获得当前时间字符串
	 * @param timeFormat
	 * @return
	 */
	public static String sysTimeString(String timeFormat){
		String timeStr=null;
		if(timeFormat==null || "".equals(timeFormat)){
			timeFormat="yyyy-MM-dd HH:mm:ss";
		}
		try {
			SimpleDateFormat sdf=new SimpleDateFormat(timeFormat);
			timeStr=sdf.format(new Date());
		} catch (Exception e) {
			System.out.println("时间格式错误:"+timeFormat);
		}
		return timeStr;
	}
	/**
	 * 将时间字符串从旧的格式转换为新的格式
	 * @param timeString 时间字符串
	 * @param formatOld 原格式
	 * @param formatNew 目标格式
	 * @return 目标格式的时间字符串
	 */
	public static String timeStringConvert(String timeString,
			String formatOld,String formatNew){
		String timeStr=null;
		try {
			SimpleDateFormat sdfOld=new SimpleDateFormat(formatOld);
			SimpleDateFormat sdfNew=new SimpleDateFormat(formatNew);
			Date date=sdfOld.parse(timeString);
			timeStr=sdfNew.format(date);
		} catch (Exception e) {
			System.out.println("将旧时间字符串转换为新的时间字符串时异常");
		}
		return timeStr;
	}
	/**
	 * 判断字符串是否为空字符串,如果为空则返回null,否则返回字符串本身
	 * @param str
	 */
	public static String initString(String str){
		if("".equals(str)){
			str=null;
		}
		return str;
	}
	/**
	 * 将double类型数据转为整数,如果有小数点则进位
	 * @param d double类型数据
	 * @return 整数
	 */
	public static Integer toInteger(Double d){
		Integer retInt=null;
		if(d!=null){
			Integer dempInt=d.intValue();
			if(d>dempInt){
				dempInt+=1;
			}
			retInt=dempInt;
		}
		return retInt;
	}

	/**
	 * 加密
	 * @param content 需要加密的内容
	 * @param password 加密密码
	 * @return
	 */
	public static String encrypt(String content, String password){
		String result=null;
	    try {
	        byte[] raw = password.getBytes(Charsets.UTF_8);
	        if (raw.length != 16) {
	            throw new IllegalArgumentException("Invalid key size. " + password + ", 密钥token长度不是16位");
	        }
	        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
	        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16])); // zero IV
	        byte[] finaly = cipher.doFinal(content.getBytes(Charsets.UTF_8));
	        result=new String(org.apache.commons.codec.binary.Base64.encodeBase64(finaly));
	    } catch (Exception e) {
	        //logger.error(e.getMessage(), e);
	        //throw e;
	    	System.out.println("加密方法中出现异常");
	    	e.printStackTrace();
	    }
	    return result;
	}
	/**
	 * 解密
	 * @param content 需要解密的内容
	 * @param password 加密密码
	 * @return
	 */
	public static String decrypt(String content, String password){
		String result=null;
	    try {
	        byte[] raw = password.getBytes(Charsets.UTF_8);
	        if (raw.length != 16) {
	            throw new IllegalArgumentException("Invalid key size. " + password + ", 密钥token长度不是16位");
	        }
	        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
	        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
	        byte[] toDecrypt = org.apache.commons.codec.binary.Base64.decodeBase64(content.getBytes());
	        byte[] original = cipher.doFinal(toDecrypt);
	        result=new String(original, Charsets.UTF_8);
	    }catch (Exception e){
	        //logger.error(e.getMessage(), e);
	    	//throw e;
	    	System.out.println("解密方法中出现异常");
	    	e.printStackTrace();
	    }
	    return result;
	}
	/**
	 * 生成系统的Sign
	 * @param timeStr
	 * @return
	 */
	//FF813302B268A3D074ABBEFCCB469A51
	public static String systemSign(String method){
			SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
			String time=sdf.format(new Date());
			String str=method+time+"33C30CBEM3E7894555D1F17F66C9EB5D";
			String sign=getMD5(str);
		return sign;
	}
/**
 * 判断是否为所传参数是否为json格式
 * @param josn
 * @return
 */
	public static boolean VerificationJson(String json){
		boolean boo=false;
		try{
		if("".equals(json)||json==null){
			return boo;
		}
		JSONObject.parseObject(json);
		boo=true;
		}catch (Exception e) {
			boo=false;
		}
		//System.out.println("参数:"+json+"是否为json格式:"+boo);
		return boo;
	}

	/**
	 * 将字符串数组中的所有字符串一次累加生成新字符串后返回
	 * @param args 字符串数组
	 * @return
	 */
	public static String createKey(String[] args){
		StringBuilder sb=new StringBuilder("");
		if(args!=null){
			for(int i=0;i<args.length;i++){
				String arg=args[i];
				if(i==args.length-1){
					sb.append(arg==null? "":arg);
				}
				else{
					sb.append((arg==null? "":arg)+":");
				}

			}
		}
		return sb.toString();
	}

	/**
	 * Md5加密(32位)
	 * @param str
	 * @return
	 */
	public static String getMD5Str(String str){
        MessageDigest messageDigest = null;
        try
        {
            messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e)
        {
            System.out.println("NoSuchAlgorithmException caught!");
            System.exit(-1);
        } catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

        byte[] byteArray = messageDigest.digest();

        StringBuffer md5StrBuff = new StringBuffer();

        for (int i = 0; i < byteArray.length; i++)
        {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
            else
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
        }
        return md5StrBuff.toString();
    }
}