package cn.hmsoft.helper;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.HashMap;

import org.springframework.web.multipart.MultipartFile;

import cn.hmsoft.application.SpringHelper;
import cn.hmsoft.frame.exception.BusinessException;

/*********************
 * 文件相关类
 * 
 * @author zxq
 * @create 2019-06-28 22:16:50
 * @version 2.0.0
 * @email: revisit@126.com
 * @Company: www.hmsoft.cn
 */
public class FileHelper {

	/********************
	 * 创建在应用目录下的临时文件 temporary目录
	 */
	public static File createWebTempFile() {
		return createTempFile("tmp");

	}

	public static File getWebTempPath() {
		File f = new File(SpringHelper.getWebTemporaryPath(LocalDate.now()));
		f.mkdirs();
		return f;
	}

	/********************
	 * 创建在应用目录下的临时文件 temporary目录
	 */
	public static File createWebTempFile(String suffix) {
		try {
			File file = new File(SpringHelper.getWebTemporaryPath(LocalDate.now()) + "hm2soft_"
					+ RandomHelper.getRandomValue(8) + suffix == null ? null : ("." + suffix));
			return file;
		} catch (Exception e) {
			throw new BusinessException("无法创建临时文件");
		}
	}

	/*****************
	 * 创建默认的临时文件
	 */
	public static File createTempFile() {
		return createTempFile("tmp");
	}

	/****************
	 * 创建临时文件
	 * 
	 * @param suffix
	 *            后缀名
	 */
	public static File createTempFile(String suffix) {
		try {
			return File.createTempFile("hm2soft_" + RandomHelper.getRandomValue(8),
					suffix == null ? null : ("." + suffix));
		} catch (Exception e) {
			throw new BusinessException("无法创建临时文件");
		}
	}

	/*********************
	 * 将上传文件转换到临时文件中
	 */
	public static File fromUpload(MultipartFile uploadFile) {
		return fromUpload(uploadFile, false);

	}

	/*********************
	 * 将上传文件转换到临时文件中
	 */
	public static File fromUpload(MultipartFile uploadFile, boolean suffix) {
		File toFile = null;
		if (suffix) {
			// 保留后缀名
			String sf = FileHelper.getFileSuffix(uploadFile);
			toFile = createTempFile(sf);
		} else
			toFile = createTempFile();
		return fromUpload(toFile, uploadFile);

	}

	/*****************************
	 * 将上传文件转换到指定的文件里
	 * 
	 * @param toFile
	 *            需要保存的文件
	 * @param uploadFile
	 *            上传的文件
	 * @return
	 */
	public static File fromUpload(File toFile, MultipartFile uploadFile) {
		try {
			uploadFile.transferTo(toFile);
			return toFile;
		} catch (Exception e) {
			throw new BusinessException("无法保存上传文件：临时空间不足，请联系系统管理员！");
		}
	}

	/**
	 * 转换文件大小
	 */
	public static String formatFileSize(long fileS) {
		DecimalFormat df = new DecimalFormat("#.##");
		String fileSizeString = "";
		String wrongSize = "0B";
		if (fileS == 0) {
			return wrongSize;
		}
		if (fileS < 1024) {
			fileSizeString = df.format((double) fileS) + "B";
		} else if (fileS < 1048576) {
			fileSizeString = df.format((double) fileS / 1024) + "KB";
		} else if (fileS < 1073741824) {
			fileSizeString = df.format((double) fileS / 1048576) + "MB";
		} else {
			fileSizeString = df.format((double) fileS / 1073741824) + "GB";
		}
		return fileSizeString;
	}

	public static final HashMap<String, String> FrameFileType = new HashMap<String, String>();
	static {
		// images
		FrameFileType.put("FFD8FF", "jpg");
		FrameFileType.put("FFD8FFE0", "jpg");
		FrameFileType.put("FFD8FFE1", "jpg");
		//
		FrameFileType.put("89504E47", "png");
		FrameFileType.put("47494638", "gif");
		FrameFileType.put("49492A00", "tif");
		FrameFileType.put("424D", "bmp");
		//
		FrameFileType.put("41433130", "dwg"); // CAD
		FrameFileType.put("38425053", "psd");
		FrameFileType.put("7B5C727466", "rtf"); // 日记本
		FrameFileType.put("3C3F786D6C", "xml");
		FrameFileType.put("68746D6C3E", "html");
		FrameFileType.put("44656C69766572792D646174653A", "eml"); // 邮件
		FrameFileType.put("D0CF11E0", "doc");
		FrameFileType.put("D0CF11E0", "xls");// excel2003版本文件
		FrameFileType.put("5374616E64617264204A", "mdb");
		FrameFileType.put("252150532D41646F6265", "ps");
		FrameFileType.put("255044462D312E", "pdf");
		FrameFileType.put("504B0304", "docx");
		FrameFileType.put("504B0304", "xlsx");// excel2007以上版本文件
		FrameFileType.put("52617221", "rar");
		FrameFileType.put("57415645", "wav");
		FrameFileType.put("41564920", "avi");
		FrameFileType.put("2E524D46", "rm");
		FrameFileType.put("000001BA", "mpg");
		FrameFileType.put("000001B3", "mpg");
		FrameFileType.put("6D6F6F76", "mov");
		FrameFileType.put("3026B2758E66CF11", "asf");
		FrameFileType.put("4D546864", "mid");
		FrameFileType.put("1F8B08", "gz");
	}

	/********************
	 * 获取文件真实后缀名
	 */
	public static String getFileSuffix(File file) {
		FileInputStream is = null;
		String value = null;
		try {
			is = new FileInputStream(file);
			byte[] b = new byte[4];
			is.read(b, 0, b.length);
			value = ByteHelper.bytesToHexString(b);
		} catch (Exception e) {
		} finally {
			if (null != is) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
		}
		// System.out.println(value);
		if (FrameFileType.containsKey(value))
			return FrameFileType.get(value);
		return file.getName().indexOf(".") > 0 ? (file.getName().substring(file.getName().lastIndexOf(".") + 1)) : null;
	}

	/********************
	 * 获取文件真实后缀名
	 */
	public static String getFileSuffix(MultipartFile file) {
//		InputStream is = null;
//		String value = null;
//		try {
//			is = file.getInputStream();
//			byte[] b = new byte[4];
//			is.read(b, 0, b.length);
//			value = ByteHelper.bytesToHexString(b);
//		} catch (Exception e) {
//		} finally {
//			if (null != is) {
//				try {
//					is.close();
//				} catch (IOException e) {
//				}
//			}
//		}
//		if (FrameFileType.containsKey(value))
//			return FrameFileType.get(value);
		return file.getOriginalFilename().indexOf(".") > 0
				? (file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1))
				: null;
	}

	/************
	 * 文件重命名
	 */
	public static File rename(File file, String file_name) {
		if (!file.exists() || !file.isFile())
			return null;
		String suffix = getFileSuffix(file);
		File newFile = new File(file.getParent() + File.separator + file_name + "." + suffix);
		file.renameTo(newFile);
		return newFile;
	}

	/*************************************************
	 * 拷贝文件到指定目录 <span> source -> path </span>
	 */
	public static boolean copyFile(String source, String path) {
		File file = new File(source);
		if (!file.exists())
			return false;
		File target = new File(path);
		if (target.exists() && target.isFile())
			return false;
		target.mkdirs();
		copyFile(file, new File(target.getPath() + File.separator + file.getName()));
		return true;
	}

	/*************************************************
	 * 移动文件到指定目录 <span> source -> path </span>
	 */
	public static boolean moveFile(String source, String path) {
		if (copyFile(source, path)) {
			deleteFile(source);
		}
		return true;
	}

	/*************************************************
	 * 删除文件
	 */
	public static boolean deleteFile(String source) {
		File file = new File(source);
		if (!file.exists())
			return false;
		file.delete();
		return true;
	}

	/**********************************
	 * 复制文件夹， source -> target cover是否覆盖
	 */
	public static boolean copyFolder(String source, String target, boolean cover) {
		File file = new File(source);
		if (!file.exists() || file.isFile())
			return false;
		File path = new File(target);
		if (path.exists() && path.isFile())
			return false;
		if (!path.exists())
			path.mkdirs();
		for (File f : file.listFiles()) {
			String tar = target + File.separator + f.getName();
			if (f.isDirectory())
				copyFolder(f.getPath(), tar, cover);
			else {
				File toFile = new File(tar);
				if (toFile.exists() && cover == false)
					continue;
				copyFile(f, toFile);
			}
		}
		return true;
	}

	/*************************************
	 * 文件拷贝，使用通道方式，提高性能
	 */
	public static void copyFile(File source, File target) {
		FileInputStream fi = null;
		FileOutputStream fo = null;
		FileChannel in = null;
		FileChannel out = null;
		try {
			if (!target.getParentFile().exists())
				target.getParentFile().mkdirs();
			fi = new FileInputStream(source);
			fo = new FileOutputStream(target);
			in = fi.getChannel();// 得到对应的文件通道
			out = fo.getChannel();// 得到对应的文件通道
			in.transferTo(0, in.size(), out);// 连接两个通道，并且从in通道读取，然后写入out通道
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				fi.close();
				in.close();
				fo.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

	}

	/**
	 * 读取文件内容，作为字符串返回
	 */
	public static String readFileAsString(String filePath) throws IOException {
		File file = new File(filePath);
		if (!file.exists()) {
			throw new FileNotFoundException(filePath);
		}

		if (file.length() > 1024 * 1024 * 1024) {
			throw new IOException("File is too large");
		}

		StringBuilder sb = new StringBuilder((int) (file.length()));
		// 创建字节输入流
		FileInputStream fis = new FileInputStream(filePath);
		// 创建一个长度为10240的Buffer
		byte[] bbuf = new byte[10240];
		// 用于保存实际读取的字节数
		int hasRead = 0;
		while ((hasRead = fis.read(bbuf)) > 0) {
			sb.append(new String(bbuf, 0, hasRead));
		}
		fis.close();
		return sb.toString();
	}

	/**
	 * 根据文件路径读取byte[] 数组
	 */
	public static byte[] readFileByBytes(String filePath) throws IOException {
		File file = new File(filePath);
		if (!file.exists()) {
			throw new FileNotFoundException(filePath);
		} else {
			ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
			BufferedInputStream in = null;

			try {
				in = new BufferedInputStream(new FileInputStream(file));
				short bufSize = 1024;
				byte[] buffer = new byte[bufSize];
				int len1;
				while (-1 != (len1 = in.read(buffer, 0, bufSize))) {
					bos.write(buffer, 0, len1);
				}

				byte[] var7 = bos.toByteArray();
				return var7;
			} finally {
				try {
					if (in != null) {
						in.close();
					}
				} catch (IOException var14) {
					var14.printStackTrace();
				}

				bos.close();
			}
		}
	}
}
