package com.bcxin.signature.util;

import org.apache.commons.io.IOUtils;

import javax.imageio.stream.FileImageInputStream;
import java.io.*;
import java.util.Locale;

/**
 * 有关文件处理的工具类
 * @author       liandi
 * @see          [相关类，可选、也可多条，对于重要的类或接口建议注释]
 * @since        esign, 2017年10月24日
 */
public final class FileUtils
{
    private FileUtils()
    {
        
    }
    
    /**
     * 创建目录，如果目录已经存在，则将会返回false
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param file
     * @return 
     */
    public static boolean mkdirs(File file)
    {
        if(null == file) return false;
        
        if(file.exists()) return false;
        
        return file.mkdirs();
    }
    
    /**
     * 创建目录，如果目录已经存在，则将会返回false
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param directory
     * @return
     */
    public static boolean mkdirs(String directory)
    {
        if(StringUtils.isBlank(directory)) return false;
        
        return mkdirs(new File(directory));
    }
    
    /**
     * 删除文件
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param file
     * @return
     */
    public static boolean delete(File file)
    {
        if(null == file) return false;
        
        if(!file.exists()) return false;
        
        return file.delete();
    }
    
    /**
     * 删除文件
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param file
     * @return
     */
    public static boolean delete(String file)
    {
        if(StringUtils.isBlank(file)) return false;
        
        return delete(new File(file));
    }
    
    /**
     * 文件是否存在
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年12月18日
     * @param fileName   文件的绝对路径
     * @return
     */
    public static boolean exists(String fileName)
    {
        if (StringUtils.isBlank(fileName)) return false;
        
        File file = new File(fileName);
        
        return file.exists();
    }
    
    /**
     * 获取文件头信息
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param file   文件路径 
     * @return
     */
    public static String getFileHeader(String file)
    {
        InputStream in = null;
        try
        {
            in = new FileInputStream(file);
            byte[] header = new byte[4];
            in.read(header, 0, header.length);
            
            return StringUtils.bytes2Hex(header);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if(null != in)
                {
                    in.close();
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        
        return null;
    }
    
    /**
     * 获取文件头信息
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param fileData   文件数据
     * @return
     */
    public static String getFileHeader(byte[] fileData)
    {
        if(null == fileData) return null;
        
        byte[] header = new byte[4];
        
        System.arraycopy(fileData, 0, header, 0, header.length);
        
        return StringUtils.bytes2Hex(header);
    }
    
    /**
     * 判断文件是否为bmp文件
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param fileData   文件数据
     * @return
     */
    public static boolean isBmpFile(byte[] fileData)
    {
        if(null == fileData) return false;
        
        String header = getFileHeader(fileData).toUpperCase(Locale.ENGLISH);
        header = header.substring(0,4);
        
        return "424D".equals(header);
    }
    
    /**
     * 判断文件是否为pdf文件
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param fileData   文件数据
     * @return
     */
    public static boolean isPdfFile(byte[] fileData)
    {
        if(null == fileData) return false;
        
        String header = getFileHeader(fileData).toUpperCase(Locale.ENGLISH);
        header = header.substring(0,4);
        
        return "2550".equals(header);
    }
    
    public static boolean isPdfFile(String filePath)
    {
        if(StringUtils.isBlank(filePath)) return false;
        
        String header = getFileHeader(filePath).toUpperCase(Locale.ENGLISH);
        header = header.substring(0,4);
        
        return "2550".equals(header);
    }
    /**
     * 判断文件是否为word excel文件
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param fileData   文件数据
     * @return
     */
    public static boolean isWordOrExcel(byte[] fileData)
    {
        if(null == fileData) return false;
        
        String header = getFileHeader(fileData).toUpperCase(Locale.ENGLISH);
        header = header.substring(0,4);
        
        return "D0CF".equals(header);
    }
    
    /**
     * 判断文件是否为pfx文件
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年11月16日
     * @param fileData    文件数据
     * @return
     */
    public static boolean isPfxFile(byte[] fileData)
    {
        if(null == fileData) return false;
        
        String header = getFileHeader(fileData).toUpperCase(Locale.ENGLISH);
        header = header.substring(0,4);
        
        return "3082".equals(header);
    }
    
    
    /**
     * 通过文件名获取文件的扩展名
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2017年10月24日
     * @param fileName
     * @return
     */
    public static String getExpandedNameByFileName(String fileName)
    {
        if(StringUtils.isBlank(fileName)) return null;
        
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

	public byte[] image2byte(String path) {
		byte[] data = null;
		FileImageInputStream input = null;
		try {
			input = new FileImageInputStream(new File(path));
			ByteArrayOutputStream output = new ByteArrayOutputStream();
			byte[] buf = new byte[1024];
			int numBytesRead = 0;
			while ((numBytesRead = input.read(buf)) != -1) {
				output.write(buf, 0, numBytesRead);
			}
			data = output.toByteArray();
			output.close();
			input.close();
		} catch (FileNotFoundException ex1) {
     	   ex1.printStackTrace();
		} catch (IOException ex1) {
			ex1.printStackTrace();
		}
		return data;
	}
	
	public static byte[] readInputStreamToBytes(InputStream in) throws IOException
    {
        if(null == in)
        {
            return null;
        }
        
        ByteArrayOutputStream out = null;
        try
        {
            out = new ByteArrayOutputStream(4096);
            
            byte[] data = new byte[4096];
            int len = 0;
            while((len = in.read(data)) > 0)
            {
                out.write(data,0,len);
                
            }
            
            return out.toByteArray();
        }
        finally
        {
            IOUtils.closeQuietly(out);
        }
    }
	/**
     * 将文件内容读取成二进制
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2018年1月9日
     * @param filePath    文件的绝对路径
     * @return
     */
    public static byte[] readFileTobytes(String filePath)
    {
        InputStream in = null;
        
        try
        {
            in = new FileInputStream(filePath);
            return IOUtils.toByteArray(in);
        }
        catch (Throwable e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (null != in)
                {
                    in.close();
                }
            }
            catch (IOException e)
            {
               e.printStackTrace();
            }
        }
        
        return null;
    }
    /**
     * 将二进制数据写入一个文件
     * @author       liandi
     * @see          相关函数，对于重要的函数建议注释
     * @since        esign, 2018年1月9日
     * @param data
     * @param filePath
     */
    public static void write(byte[] data, String filePath)
    {
        OutputStream out = null;
        try
        {
            out = new FileOutputStream(filePath);
            IOUtils.write(data, out);
        }
        catch (Throwable e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (null != out)
                {
                    out.close();
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    
    public static boolean copyFile(String srcFileName, String destFileName,boolean overlay) {
		File srcFile = new File(srcFileName);
		if (!srcFile.exists()) {
			return false;
		} 
		if (!srcFile.isFile()) {
			return false;
		}
		File destFile = new File(destFileName);
		if (destFile.exists()) {
			if (overlay) {
				new File(destFileName).delete();
			}
		} else if (!destFile.getParentFile().exists()){
			if (!destFile.getParentFile().mkdirs()) {
				return false;
			}
		}
		int byteread = 0;  
		InputStream in = null;
		OutputStream out = null;

		try {
			in = new FileInputStream(srcFile);
			out = new FileOutputStream(destFile);
			byte[] buffer = new byte[1024];

			while ((byteread = in.read(buffer)) != -1) {
				out.write(buffer, 0, byteread);
			}
			buffer=null;
			return true;
		} catch (FileNotFoundException e) {
			return false;
		} catch (IOException e) {
			return false;
		} finally {
			try {
				if (out != null)
					out.close();
				if (in != null)
					in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
