/** 
 * @Title: Tools.java 
 * @Package com.zhiweidata.bjfzxWebapp.util 
 * @Description: TODO(用一句话描述该文件做什么) 
 * @author xuyimeng 
 * @date 2018年2月6日 上午10:44:33 
 * @version V1.0 
 */
/**
* 
*/
package com.zhiweidata.bjfzxWebapp.util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

/**
 * @ClassName: Tools
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author xuyimeng
 * @date 2018年2月6日 上午10:44:33
 */
public class Tools {

	private static Logger log = LoggerFactory.getLogger(Tools.class);
	private static final String key = "3e5135ac50dabd5476b5d1107fa839f9";
	private static final long timeout = 10000;

	/**
	 * @Title: getFileType
	 * @Description: TODO(判断文件类型)
	 * @param @param
	 *            type
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static String getFileType(String path) {
		String result = "";
		if (path != null) {
			int index = 0;
			try {
				if ((index = path.lastIndexOf('.')) != -1) {
					result = path.substring(index + 1);
				}
			} catch (Exception e) {
				result = "";
			}
		}
		result = result.toLowerCase();
		return result;
	}

	/**
	 * @Title: getMIME
	 * @Description: TODO(获取MIME类型)
	 * @param @param
	 *            type
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static String getMIME(String type) {
		String result = null;
		type = type.toLowerCase();
		if (type.equals("html") || type.equals("htm"))
			result = "text/html";
		if (type.equals("xml"))
			result = "text/xml";
		if (type.equals("xhtml"))
			result = "application/xhtml+xml";
		if (type.equals("txt"))
			result = "text/plain";
		if (type.equals("rtf"))
			result = "application/rtf";
		if (type.equals("pdf"))
			result = "application/pdf";
		if (type.equals("doc") || type.equals("docx"))
			result = "application/msword";
		if (type.equals("png"))
			result = "image/png";
		if (type.equals("jpg") || type.equals("jpeg"))
			result = "image/jpeg";
		if (type.equals("gif"))
			result = "image/gif";
		return result;
	}

	/**
	 * @Title: saveObjectToFile
	 * @Description: TODO(将对象保存到文件)
	 * @param @param
	 *            path
	 * @param @param
	 *            obj
	 * @param @return
	 *            设定文件
	 * @return void 返回类型
	 */
	public static void saveObjectToFile(String path, Object obj) {
		try {
			if (!(obj instanceof Serializable))
				throw new IOException(obj + " does not implement interface Serializable");
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
			oos.writeObject(obj);
			oos.flush();
			oos.close();
		} catch (Exception e) {
			log.error("should implement Serializable", e);
		}
	}

	/**
	 * @Title: readObjectInFile
	 * @Description: TODO(读取文件中存储的对象)
	 * @param @param
	 *            path
	 * @param @return
	 *            设定文件
	 * @return Object 返回类型
	 */
	public static Object readObjectInFile(String path) {
		Object obj = null;
		try {
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
			obj = ois.readObject();
			ois.close();
		} catch (Exception e) {
			File file = new File(path);
			file.delete();
			log.error("error in readObjectInFile", e);
		}
		return obj;
	}

	/**
	 * @Title: getEncode
	 * @Description: TODO(判断字符串编码)
	 * @param @param
	 *            path
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static String getEncode(String path) {
		String result = null;
		BufferedInputStream bis = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(path));
			int p = (bis.read() << 8) + bis.read();
			switch (p) {
			case 0xefbb:
				result = "UTF-8";
				break;
			case 0xfffe:
				result = "UTF-16LE";// Unicode
				break;
			case 0xfeff:
				result = "UTF-16BE";
				break;
			case 0x5c75:
				result = "ANSI|ASCII";
			default:
				result = "GBK";
			}
		} catch (Exception e) {
			log.error("error in getEncode", e);
		} finally {
			try {
				if (bis != null) {
					bis.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * @Title: validKey
	 * @Description: TODO(验证下载校验码)
	 * @param @param
	 *            type
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static boolean validKey(String id, String token) {
		boolean result = false;
		if (id != null && token != null) {
			String src = decrypt(token);
			if (src != null) {
				if (src.indexOf(',') != -1) {
					String[] strs = src.split(",");
					if (strs.length == 2) {
						result = true;
						try {
							if (!strs[0].equals(id))
								result = false;
							Date date = new Date(Long.parseLong(strs[1]));
							if (new Date().getTime() - date.getTime() > timeout)
								result = false;
						} catch (Exception e) {
							result = false;
							e.printStackTrace();
						}
					}
				}
			}
		}
		return result;
	}

	/**
	 * @Title: generateKey
	 * @Description: TODO(生成下载校验码)
	 * @param @param
	 *            type
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static String generateKey(String id) {
		String result = null;
		if (id != null) {
			String str = id + "," + new Date().getTime();
			result = encrypt(str);
		}
		return result;
	}

	private static String encrypt(String str) {
		String result = null;
		if (str != null && key != null) {
			try {
				KeyGenerator kgen = KeyGenerator.getInstance("AES");
				SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
				sr.setSeed(key.getBytes());
				kgen.init(128, sr);
				SecretKey secretKey = kgen.generateKey();
				byte[] enCodeFormat = secretKey.getEncoded();
				SecretKeySpec sks = new SecretKeySpec(enCodeFormat, "AES");
				Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器
				byte[] byteContent = str.getBytes();
				cipher.init(Cipher.ENCRYPT_MODE, sks);// 初始化
				result = bytesToHexString(cipher.doFinal(byteContent));
			} catch (Exception e) {
			}
		}
		return result;
	}

	private static String decrypt(String str) {
		String result = null;
		if (str != null && key != null) {
			try {
				KeyGenerator kgen = KeyGenerator.getInstance("AES");
				SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
				sr.setSeed(key.getBytes());
				kgen.init(128, sr);
				SecretKey secretKey = kgen.generateKey();
				byte[] enCodeFormat = secretKey.getEncoded();
				SecretKeySpec sks = new SecretKeySpec(enCodeFormat, "AES");
				Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器
				cipher.init(Cipher.DECRYPT_MODE, sks);// 初始化
				result = new String(cipher.doFinal(hexStringToBytes(str)));
			} catch (Exception e) {
			}
		}
		return result;
	}

	/**
	 * 将二进制转换成16进制
	 * 
	 * @param buf
	 * @return
	 */
	private static String bytesToHexString(byte bytes[]) {
		String result = null;
		if (bytes != null) {
			if (bytes.length > 0) {
				StringBuffer sb = new StringBuffer();
				for (int i = 0; i < bytes.length; i++) {
					String hex = Integer.toHexString(bytes[i] & 0xFF);
					if (hex.length() == 1) {
						hex = '0' + hex;
					}
					sb.append(hex);
				}
				result = sb.toString().toLowerCase();
			}
		}
		return result;
	}

	/**
	 * 将16进制转换为二进制
	 * 
	 * @param hexStr
	 * @return
	 */
	private static byte[] hexStringToBytes(String hexs) {
		byte[] result = null;
		if (hexs != null) {
			if (!hexs.equals("")) {
				hexs = hexs.toUpperCase();
				result = new byte[hexs.length() / 2];
				for (int i = 0; i < hexs.length() / 2; i++) {
					int high = Integer.parseInt(hexs.substring(i * 2, i * 2 + 1), 16);
					int low = Integer.parseInt(hexs.substring(i * 2 + 1, i * 2 + 2), 16);
					result[i] = (byte) (high * 16 + low);
				}
			}
		}
		return result;
	}

	public static String escapeSql(String str) {
		String result = null;
		if (str != null) {
			if (str.equals(""))
				str = null;
		}
		if (str != null) {
			result = StringEscapeUtils.escapeSql(str);
		}
		return result;
	}

	/**
	 * @Title: md5
	 * @Description: 计算字符串Md5
	 * @param @param
	 *            str
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static String md5(String str) {
		String result = null;
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] bytes = str.getBytes("utf-8");
			md.update(bytes);
			bytes = md.digest();
			result = bytesToHexString(bytes);
		} catch (Exception e) {
		}
		return result;
	}

	/**
	 * @Title: sleep
	 * @Description: 线程等待，忽略异常
	 * @param @param
	 *            millis
	 * @return void
	 */
	public static void sleep(long millis) {
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
		}
	}

	/**
	 * 
	 * @deprecated:生成邮件验证的code
	 * @param @return
	 * @return String 返回类型
	 */
	public static String generateMailCode(int length) {
		return RandomStringUtils.randomAlphanumeric(length);
	}

	/**
	 * 
	 * @deprecated:生成手机验证的code
	 * @param @param
	 *            length
	 * @param @return
	 * @return String 返回类型
	 */
	public static String generatePhoneCode(int length) {
		return RandomStringUtils.randomNumeric(length);
	}

	/**
	 * @Title: replaceBlank
	 * @Description: TODO(去除特殊字符)
	 * @param @param
	 *            str
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static String replaceBlank(Object str) {
		String dest = "";
		if (str != null) {
			Pattern p = Pattern.compile("=|,|\"|“|\\s*|\t|\r|\n");
			Matcher m = p.matcher(str.toString());
			dest = m.replaceAll("");
		}
		return dest;
	}

	/**
	 * 
	 * @Title: decodeUnicode
	 * @Description: TODO(unicode 转换成 中文)
	 * @param @param
	 *            theString
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static String decodeUnicode(String theString) {
		char aChar;
		int len = theString.length();
		StringBuffer outBuffer = new StringBuffer(len);
		for (int x = 0; x < len;) {
			aChar = theString.charAt(x++);
			if (aChar == '\\') {
				aChar = theString.charAt(x++);
				if (aChar == 'u') {
					// Read the xxxx
					int value = 0;
					for (int i = 0; i < 4; i++) {
						aChar = theString.charAt(x++);
						switch (aChar) {
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
							value = (value << 4) + aChar - '0';
							break;
						case 'a':
						case 'b':
						case 'c':
						case 'd':
						case 'e':
						case 'f':
							value = (value << 4) + 10 + aChar - 'a';
							break;
						case 'A':
						case 'B':
						case 'C':
						case 'D':
						case 'E':
						case 'F':
							value = (value << 4) + 10 + aChar - 'A';
							break;
						default:
							throw new IllegalArgumentException("Malformed   \\uxxxx   encoding.");
						}
					}
					outBuffer.append((char) value);
				} else {
					if (aChar == 't')
						aChar = '\t';
					else if (aChar == 'r')
						aChar = '\r';
					else if (aChar == 'n')
						aChar = '\n';
					else if (aChar == 'f')
						aChar = '\f';
					outBuffer.append(aChar);
				}
			} else
				outBuffer.append(aChar);
		}
		return outBuffer.toString();
	}

	/**
	 * 
	 * @Title: percentMap
	 * @Description: TODO(计算百分比，保留两位小数)
	 * @param @param
	 *            map
	 * @param @return
	 *            设定文件
	 * @return Map<String,String> 返回类型
	 */
	public static Map<String, String> percentMap(Map<String, Integer> map) {
		Map<String, String> newMap = new HashMap<String, String>();
		Integer total = 0;
		for (Entry<String, Integer> e : map.entrySet()) {
			total += Integer.valueOf(e.getValue().toString());
		}
		for (String str : map.keySet()) {
			double f = map.get(str).doubleValue() / total * 100;

			// 保留两位小数
			BigDecimal b = new BigDecimal(f);
			double f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

			newMap.put(str, f1 + "%");
		}
		return newMap;
	}

	/**
	 * 
	 * @TODO(TODO 保留两位小数)
	 * @author 陈炜涛
	 * @param map
	 * @return
	 * @time 2016年11月24日上午10:07:33
	 * @return Map<String,String>
	 */
	public static Double percentDouble(double num) {
		double f1 = 0.00;
		if (0 != num) {
			// 保留两位小数
			BigDecimal b = new BigDecimal(num);
			f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
		}
		return f1;
	}

	/**
	 * @Title: getFile
	 * @Description: TODO(根据文件名和路径获取文件)
	 * @param @param
	 *            path
	 * @param @param
	 *            fileName
	 * @param @return
	 *            设定文件
	 * @return File 返回类型
	 */
	public static File getFile(String path, String fileName) {
		// 判断目录，不存在那么创建目录
		path.replace("\\", File.pathSeparator);
		File dir = new File(path);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		// 判断文件是否存在
		File file = new File(path, fileName);
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return file;
	}

	// 正则表达式
	/**
	 * #([^\\#|.]+)# 话题的表达式
	 * 
	 * @用户的表达式 @[\u4e00-\u9fa5a-zA-Z0-9_-]{4,30}
	 * 
	 */
	public static String getString(String text, String expression) {
		StringBuffer buffer = new StringBuffer();
		Pattern TAG_PATTERN = Pattern.compile(expression);
		Matcher m = TAG_PATTERN.matcher(text);
		while (m.find()) {
			buffer.append(m.group());
			buffer.append(" ");
		}
		if (!" ".equals(buffer.toString())) {
			System.out.println("原始内容：" + text + "\t获取的数据：" + buffer.toString());
			return buffer.toString();
		} else {
			System.out.println("原始内容：" + text.substring(0, 10) + "\t没找到@用户：");
		}
		return "";
	}

	/**
	 * @Title: changeVtype
	 * @Description: TODO(微博认证类型转换)
	 * @param @param
	 *            vtype
	 * @param @return
	 *            设定文件
	 * @return String 返回类型
	 */
	public static String changeVtype(int vtype) {
		String type = "";
		switch (vtype) {
		case -2:
			type = "未知";
			break;
		case -1:
			type = "普通用户";
			break;
		case 0:
			type = "名人";
			break;
		case 1:
			type = "政府";
			break;
		case 2:
			type = "企业";
			break;
		case 3:
			type = "媒体";
			break;
		case 4:
			type = "校园";
			break;
		case 5:
			type = "网站";
		case 6:
			type = "应用";
		case 7:
			type = "团体";
		case 10:
			type = "微博女郎";
			break;
		case 220:
			type = "达人";
			break;
		case 200:
			type = "达人";
			break;
		}
		return type;
	}

	/**
	 * 
	 * @Title: getWechatTsn
	 * @Description: TODO(更具相差多少天匹配微信采集参数)
	 * @param @param
	 *            day
	 * @param @return
	 *            设定文件
	 * @return int 返回类型
	 */
	public static int getWechatTsn(int day) {
		int tsn = 1;
		if (day > 1 && day <= 7) {
			tsn = 2;
		} else if (day > 7 && day <= 30) {
			tsn = 3;
		} else if (day > 31) {
			tsn = 4;
		}
		return tsn;
	}

	/**
	 * @Title: getWorksByFile
	 * @Description: TODO(通过文件名获取文件中的关键词)
	 * @param @param
	 *            file
	 * @param @return
	 *            设定文件
	 * @return List<String> 返回类型
	 */
	public static List<String> getWorksByFile(File file) {
		List<String> list = new ArrayList<String>();
		FileInputStream fi = null;
		try {
			fi = new FileInputStream(file);
			BufferedReader reader = new BufferedReader(new InputStreamReader(fi));
			String line = null;
			while ((line = reader.readLine()) != null) {
				list.add(line);
			}
			reader.close();
			fi.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (fi != null) {
					fi.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return list;
	}

	public static <T> DBObject bean2DBObject(T bean) throws IllegalArgumentException, IllegalAccessException {
		if (bean == null) {
			return null;
		}
		DBObject dbObject = new BasicDBObject();
		// 获取对象对应类中的所有属性域
		Field[] fields = bean.getClass().getDeclaredFields();
		for (Field field : fields) {
			// 获取属性名
			String varName = field.getName();
			// 修改访问控制权限
			boolean accessFlag = field.isAccessible();
			if (!accessFlag) {
				field.setAccessible(true);
			}
			Object param = field.get(bean);
			if (param == null) {
				continue;
			} else if (param instanceof Integer) {// 判断变量的类型
				int value = ((Integer) param).intValue();
				dbObject.put(varName, value);
			} else if (param instanceof String) {
				String value = (String) param;
				dbObject.put(varName, value);
			} else if (param instanceof Double) {
				double value = ((Double) param).doubleValue();
				dbObject.put(varName, value);
			} else if (param instanceof Float) {
				float value = ((Float) param).floatValue();
				dbObject.put(varName, value);
			} else if (param instanceof Long) {
				long value = ((Long) param).longValue();
				dbObject.put(varName, value);
			} else if (param instanceof Boolean) {
				boolean value = ((Boolean) param).booleanValue();
				dbObject.put(varName, value);
			} else if (param instanceof Date) {
				Date value = (Date) param;
				dbObject.put(varName, value);
			}
			// 恢复访问控制权限
			field.setAccessible(accessFlag);
		}
		return dbObject;
	}

	public static <T> T dbObject2Bean(DBObject dbObject, T bean)
			throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		if (bean == null) { // 测试已通过
			return null;
		}
		Field[] fields = bean.getClass().getDeclaredFields();
		for (Field field : fields) {
			String varName = field.getName();
			Object object = dbObject.get(varName);
			if (object != null) {
				BeanUtils.setProperty(bean, varName, object);
			}
		}
		return bean;
	}
}
