/**
 * FileName: MyCertificateUtil
 * Author:   wenjunlong
 * Date:     2018/5/18 14:55
 * Description: 解析证书
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.yizhi.application.Certificate.util;

import com.yizhi.application.Certificate.constant.LogError;
import com.yizhi.application.Certificate.constant.UtilConstants;
import com.yizhi.certificate.application.vo.domain.TrUserCertificateVo;
import com.yizhi.core.application.exception.FileReadException;
import com.yizhi.system.application.vo.AccountVO;
import com.yizhi.util.application.zip.ZipUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 〈一句话功能简述〉<br>
 * 〈解析证书〉
 *
 * @author wenjunlong
 * @create 2018/5/18
 * @since 1.0.0
 */
public class MyCertificateUtil {

    private static final Logger logger = LoggerFactory.getLogger(MyCertificateUtil.class);

    /**
     * @param trUserCertificate
     * @param templateUrl
     * @param templateName      如果是自定义证书，才传该值，否则不传
     * @return
     */
    public static String generatingCertificateImage(TrUserCertificateVo trUserCertificate, String templateUrl, AccountVO accountVO, List<String> orgNameList) {

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

        Map<String, String> parameter = new HashMap<>();

        if (StringUtils.isEmpty(trUserCertificate.getUserName())){
            parameter.put("%姓名%", trUserCertificate.getAccountName());
            parameter.put("%Name%", trUserCertificate.getAccountName());
        }else {
            parameter.put("%姓名%", trUserCertificate.getUserName());
            parameter.put("%Name%", trUserCertificate.getUserName());
        }


        parameter.put("%用户名%", trUserCertificate.getAccountName());
        parameter.put("%User name%", trUserCertificate.getAccountName());

        parameter.put("%证书名称%", trUserCertificate.getCertificateTitle());
        parameter.put("%Name of Certificate%", trUserCertificate.getCertificateTitle());

        parameter.put("%企业名称%", trUserCertificate.getCompanyName());
        parameter.put("%Name of company%", trUserCertificate.getCompanyName());

        parameter.put("%培训项目名称%", trUserCertificate.getTrainingProjectName());
        parameter.put("%Name of training programme%", trUserCertificate.getTrainingProjectName());

        parameter.put("%课程名称%", trUserCertificate.getTpPlanName());
        parameter.put("%Name of course%", trUserCertificate.getTpPlanName());

        parameter.put("%发行机构%", trUserCertificate.getIssuer());
        parameter.put("%Licensing Authority%", trUserCertificate.getIssuer());

        parameter.put("%当前时间%", formatter.format(trUserCertificate.getCreateTime()));
        parameter.put("%当前时间%", formatter.format(trUserCertificate.getCreateTime()));

        parameter.put("%得分%", trUserCertificate.getScore());
        parameter.put("%得分%", trUserCertificate.getScore());

        parameter.put("%站点名称%", trUserCertificate.getCreateByName());
        parameter.put("%Name of site%", trUserCertificate.getCreateByName());

        parameter.put("%证书编号%", trUserCertificate.getCertificateCode());
        parameter.put("%Certificate No.%", trUserCertificate.getCertificateCode());

        parameter.put("%学习计划%", trUserCertificate.getTpPlanName());
        parameter.put("%Study Plan%", trUserCertificate.getTpPlanName());

        //改版添加字段
        if (orgNameList.size() > 0) {
            parameter.put("%1级部门%", orgNameList.get(0));
            parameter.put("% Level 1 division%", orgNameList.get(0));
        }

        if (orgNameList.size() > 1) {
            parameter.put("%2级部门%", orgNameList.get(1));
            parameter.put("% Level 2 division%", orgNameList.get(1));
        }

        if (orgNameList.size() > 2) {
            parameter.put("%3级部门%", orgNameList.get(2));
            parameter.put("% Level 3division%", orgNameList.get(2));
        }

        if (orgNameList.size() > 3) {
            parameter.put("%4级部门%", orgNameList.get(3));
            parameter.put("% Level 4 division%", orgNameList.get(3));
        }


        parameter.put("%职务%", accountVO.getPosition());
        parameter.put("%Position%", accountVO.getPosition());

        parameter.put("%手机号%", accountVO.getMobile());
        parameter.put("%Cell phone number%", accountVO.getMobile());

        parameter.put("%邮箱%", accountVO.getEmail());
        parameter.put("%Mailboxes%", accountVO.getEmail());

        parameter.put("%备注1%", accountVO.getRemarkFirst());
        parameter.put("%Note 1%", accountVO.getRemarkFirst());

        parameter.put("%备注2%", accountVO.getRemarkSecond());
        parameter.put("%Note 2%", accountVO.getRemarkSecond());

        parameter.put("%备注3%", accountVO.getRemarkThird());
        parameter.put("%Note 3%", accountVO.getRemarkThird());


        //如果证书为0，设置永不过期，否则1或者2 即固定时间和固定失效时间可设值
        if (trUserCertificate.getType() != null && trUserCertificate.getType().equals(0)) {
            parameter.put("%有效期：%", "有效期：长期有效");
            parameter.put("%Period of validity%", "Period of validity：Permanent");

            parameter.put("%证书获取时间%", formatter.format(trUserCertificate.getCreateTime()).substring(0, 10));
            parameter.put("%Certificate acquisition time%", formatter.format(trUserCertificate.getCreateTime()).substring(0, 10));

        } else {
            parameter.put("%有效期：%", "有效期：" + formatter.format(trUserCertificate.getCreateTime()).substring(0, 10) + " - " + formatter.format(trUserCertificate.getEndTime()).substring(0, 10));
            parameter.put("%Period of validity%", "Period of validity：" + formatter.format(trUserCertificate.getCreateTime()).substring(0, 10) + " - " + formatter.format(trUserCertificate.getEndTime()).substring(0, 10));

            parameter.put("%证书获取时间%", formatter.format(trUserCertificate.getCreateTime()).substring(0, 10));
            parameter.put("%Certificate acquisition time%", formatter.format(trUserCertificate.getCreateTime()).substring(0, 10));
        }
        logger.info("证书：parameter：{}", parameter);

        String result = "";
        File fileInfo = null;
        try {
            // 证书模板 文件目录(解压后都放在这里面)
            File templateBaseDir = new File(UtilConstants.CERTIFICATE_SAVE_PATH);

            // 若 模板 文件夹不存在
            if (!templateBaseDir.exists()) {
                if (!templateBaseDir.mkdir()) {
                    return LogError.CERTIFICATE_ANALYSIS_ERROR;
                }
            }

            // 没有后缀的文件名
            String fileSaveName = UUID.randomUUID().toString().replace("-", "");

            // 下载文件
            fileInfo = read(templateUrl, UtilConstants.CERTIFICATE_SAVE_PATH, fileSaveName.concat(".zip"));

            // 当前 模板 课件解压后的根目录
            String currentFilePath = fileInfo.getAbsolutePath();
            String currentUnzipRootPath = templateBaseDir.getAbsolutePath().concat(File.separator).concat(fileSaveName);

            // 解压文件
            ZipUtil.unZip(currentFilePath, currentUnzipRootPath);

            // 找寻解压后多一层目录的文件夹
            File file = new File(currentUnzipRootPath);
        /*    File[] fileList = file.listFiles();
            if (fileList != null && fileList.length > 0) {
                for (File f : fileList) {
                    if (f.isDirectory() && trUserCertificate.getCertificateLogourl().indexOf(f.getName()) != -1) {
                        currentUnzipRootPath = currentUnzipRootPath.concat(File.separator).concat(f.getName());
                    }
                }
            }*/
            logger.debug("-----------------------------------------------------");
            logger.debug("证书：currentUnzipRootPath: {}", currentUnzipRootPath);
            logger.debug(trUserCertificate.toString());
            logger.debug("-----------------------------------------------------");
            // 获取模板内容
            //找到index文件  //循环这个文件夹
            File pathFile = new File(currentUnzipRootPath);
            String parentPath = pointFile(pathFile);

            String content = readfile(parentPath);
            // 组装证书图像
            File fileParent = new File(currentUnzipRootPath);
            String indexPath = pointFile(fileParent);
            boolean flag = generateHtml(parameter, content, indexPath);


            File fileparentPath = new File(parentPath);
            currentUnzipRootPath = fileparentPath.getParent();
            String converterFilePath = fileparentPath.getParent();

            if (flag) {
                //定义宽高
                int height = 0;
                int width = 0;
                File imgFile = new File(currentUnzipRootPath.concat(File.separator).concat("Diploma.jpg"));
                if (imgFile.exists()) {
                    try {
                        BufferedImage bufferedImage = ImageIO.read(new FileInputStream(imgFile));
                        height = bufferedImage.getHeight() + 40;
                        width = bufferedImage.getWidth();
                    } catch (IOException e) {
                        //LOG.info("获取图片信息异常{}",e);
                        logger.info("获取图片信息异常", e);
                    }
                }//转化

                else {
                    imgFile = new File(currentUnzipRootPath.concat(File.separator).concat("background.jpg"));
                    BufferedImage bufferedImage = ImageIO.read(new FileInputStream(imgFile));
                    height = bufferedImage.getHeight();
                    width = bufferedImage.getWidth();
                }


                HtmltopdfAndImage.convert(currentUnzipRootPath.concat("/index.html"), converterFilePath.concat(".pdf"), 1, height, width);

                PdfToPng.pdfToPng(converterFilePath.concat(".pdf"), currentUnzipRootPath, 100, 1, fileSaveName);

                String pngPath = converterFilePath.concat(File.separator).concat(fileSaveName).concat(".png");

                result = OssUpload.upload(pngPath, fileSaveName.concat(".png"));

                File fileDelete = new File(converterFilePath);
                if (fileDelete.exists()) {
                    fileDelete = new File(fileDelete.getParent());
                    if (fileDelete.exists()) {
                        DeleteFolder(fileDelete.toString());

                    }
                }
                fileInfo.deleteOnExit();
                return !result.equals("error")?result:"";
            } else {
                return LogError.CERTIFICATE_ANALYSIS_ERROR;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return LogError.CERTIFICATE_ANALYSIS_ERROR;
        } finally {
            fileInfo.delete();
        }

    }

    /**
     * @param urlStr
     * @param savePath
     * @param fileName
     * @return fileInfo 的 properties 中含有一个 absolutePath
     */
    public static File read(String urlStr, String savePath, String fileName) {

        File fileInfo = null;
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到输入流
            InputStream inputStream = conn.getInputStream();
            //获取自己数组
            byte[] buffer = new byte[1024];
            int len = 0;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            while ((len = inputStream.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            bos.close();

            byte[] getData = bos.toByteArray();
            //文件保存位置
            File saveDir = new File(savePath);
            if (!saveDir.exists()) {
                saveDir.mkdir();
            }
            fileInfo = new File(savePath.concat(File.separator).concat(fileName));
            FileOutputStream fos = new FileOutputStream(fileInfo);
            fos.write(getData);
            if (fos != null) {
                fos.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (Exception e) {
            throw new FileReadException();
        }
        return fileInfo;
    }

    //向html中填充数据
    private static boolean generateHtml(Map<String, String> parameter, String content, String outPath)
            throws IOException {
        String replacetr = content;
        for (Map.Entry<String, String> parameters : parameter.entrySet()) {
            if (content.contains(parameters.getKey())) {
                // 使用该条新闻信息替换对应占位符
                if (parameters.getValue() != null) {
                    replacetr = replacetr.replaceAll(parameters.getKey(), parameters.getValue());
                } else {
                    replacetr = replacetr.replaceAll(parameters.getKey(), "");
                    continue;
                }
            }
        }
        OutputStreamWriter op = null;
        try {
            File file = new File(outPath);
            op = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
            op.append(replacetr);
            op.flush();
            op.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            op.close();
        }
        return true;
    }

    private static String readfile(String filePath) {
        File file = new File(filePath);
        InputStream input = null;
        InputStreamReader inputStream = null;
        BufferedReader reader = null;
        try {
            input = new FileInputStream(file);
            inputStream = new InputStreamReader(input, "utf-8");
            reader = new BufferedReader(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        StringBuffer buffer = new StringBuffer();
        try {
            String line = null;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return buffer.toString();
    }


    private static String pointFile(File file) {
        String name = null;
        if (file.exists()) {
            if (file.isFile()) {
                name = file.getAbsolutePath();
                if (name.indexOf("index.html") > 0 && name.indexOf("_index.html") == -1) {
                    return name;
                }
            } else {
                File[] list = file.listFiles();
                if (list.length == 0) {
                    System.out.println(file.getAbsolutePath() + " is null");
                } else {
                    for (int i = 0; i < list.length; i++) {
                        name = pointFile(list[i]);
                        if (name != null) {
                            return name;
                        }
                    }
                }
            }
        } else {
            System.out.println("The directory is not exist!");
        }
        return null;
    }


    public static boolean DeleteFolder(String sPath) {
        Boolean flag = false;
        File file = new File(sPath);
        // 判断目录或文件是否存在
        if (!file.exists()) {  // 不存在返回 false
            return flag;
        } else {
            // 判断是否为文件
            if (file.isFile()) {  // 为文件时调用删除文件方法
                return deleteFile(sPath);
            } else {  // 为目录时调用删除目录方法
                return deleteDirectory(sPath);
            }
        }
    }


    public static boolean deleteFile(String sPath) {
        Boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }


    public static boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        Boolean flag = false;
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) break;
            } //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }


}
