package com.iamberry.wechat.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Date;
import java.util.UUID;

import javax.servlet.ServletContext;

import org.springframework.web.multipart.MultipartFile;

import sun.misc.BASE64Decoder;

import com.iamberry.wechat.tools.DateTimeUtil;
/**
 * @company	深圳爱贝源科技有限公司
 * @website www.iamberry.com
 * @author 	献
 * @tel		18271840547
 * @date	2016年10月13日
 * @explain	上传文件工具类
 */
public class FileUtils {
	
	/**
	 * 保存文件到项目根目录下指定路径
	 * @param servletContext 使用request.getServletContext() 获取<br>
	 * @param file           文件路径<br>
	 * @param savePathStr    项目根目录下路，必须以'/'结尾,如:'/aa/bb/cc/'<br>
	 * @return               返回UploadResultBean<br>
	 * @throws Exception     异常
	 */
	public static UploadResultBean saveFile(ServletContext servletContext, MultipartFile file, String savePathStr) {
		
		// 检查&获取原文件名称
		if (file.getOriginalFilename() == null || file.isEmpty()) {
			return null;
		}
		String imageName = file.getOriginalFilename();
		if (imageName == null || imageName.isEmpty()) {
			return null;
		}

		// 返回对象
		UploadResultBean bean = new UploadResultBean();
		bean.setUploadFileName(imageName);

		// 获取文件后缀
		FileType fileType = null;
		boolean isTxt = false;
		if (!isTxt) {
			try {
				fileType = getType(file.getInputStream());
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			if (fileType == null) {
				return null;
			}
		} else {
			fileType = FileType.TXT;
		}
		
		// 文件名称
		StringBuilder fileName = new StringBuilder();
		fileName.append(DateTimeUtil.format(new Date(), "yyMMddHHmmss")).append(byte2hex(createRandomByte())).append(".").append(fileType.getSuffix());
		bean.setSaveFileName(fileName.toString());
		bean.setSaveFilePath(savePathStr + fileName.toString());
		// URL路径
		String savePath = servletContext.getRealPath(savePathStr);
		// 文件系统路径
		savePath = savePath + File.separator + fileName.toString();
		try {
			org.apache.commons.io.FileUtils.writeByteArrayToFile(new File(savePath), file.getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 关闭相关流对象
		return bean;
	}
	
	/**
	 * 读取文件头,这里需要注意的是，每个文件的魔数的长度都不相同，由此使用startWith
	 * @param filePath
	 * @return
	 * @throws Exception
	 */
	public static String getFileHeader(InputStream inputStream) throws Exception {
		byte [] b = new byte[28];
		inputStream.read(b, 0, 28);
		// 此处可以不关，但是掉用方，必须关闭流对象
		inputStream.close();
		return byte2hex(b);
	}
	
	/** 
     * java字节码转字符串 
     * @param b 
     * @return 
     */
    public static String byte2hex(byte[] b) { //一个字节的数，
        // 转成16进制字符串
        String hs = "";
        String tmp = "";
        for (int n = 0; n < b.length; n++) {
            //整数转成十六进制表示
            tmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (tmp.length() == 1) {
                hs = hs + "0" + tmp;
            } else {
                hs = hs + tmp;
            }
        }
        tmp = null;
        return hs;
    }
	
	/**
	 * 判断文件类型
	 * @throws Exception 
	 */
	public static FileType getType(InputStream inputStream) {
		String fileHead = null;
		try {
			fileHead = getFileHeader(inputStream);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (fileHead == null || fileHead.length() == 0) {
			return null;
		}
		// 大写,因为在我们的FileType中，全部使用了大写
		fileHead = fileHead.toUpperCase();
		FileType [] fileTypes = FileType.values();
		for (FileType fileType : fileTypes) {
			if (fileHead.startsWith(fileType.getValue())) {
				return fileType;
			}
		}
		return null;
	}
	

	public static String getType(String fileHead) {
		FileType [] fileTypes = FileType.values();
		for (FileType fileType : fileTypes) {
			if (fileHead.startsWith(fileType.getValue())) {
				return fileType.getSuffix();
			}
		}
		return null;
	}
	
	public static boolean generateImage(String imgStr, String imgFilePath) throws IOException {  
		// Base64解码  
		byte[] bytes = new BASE64Decoder().decodeBuffer(imgStr);
		for (int i = 0; i < bytes.length; ++i) {  
			if (bytes[i] < 0) {
				// 调整异常数据  
				bytes[i] += 256;  
			}  
		}  
		// 生成图片 
		File file = new File(imgFilePath);
		org.apache.commons.io.FileUtils.writeByteArrayToFile(file, bytes);
		return true;  
	}
	
	private static SecureRandom random = null;
	static {
		try {
			random = SecureRandom.getInstance("SHA1PRNG");
		} catch (NoSuchAlgorithmException e) {
		}
	}
	/**
	 * 创建一个安全的随机数组byte[]
	 * 
	 * @return
	 */
	private static byte[] createRandomByte() {
		try {
			byte[] bytes = new byte[1024 / 8];
			random.nextBytes(bytes);
			int count = 10;
			byte[] seed = random.generateSeed(count);
			random = SecureRandom.getInstance("SHA1PRNG");
			random.setSeed(seed);
			SecureRandom random2 = SecureRandom.getInstance("SHA1PRNG");
			random2.setSeed(seed);
			return seed;
		} catch (Exception e) {
			return UUID.randomUUID().toString().getBytes();
		}
	}

	/**
	 * 获取一个安全的token
	 * 
	 * @return
	 */
	public static String getToken() {
		return byte2hex(createRandomByte());
	}
}
