/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.yfd.platform.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.EscapeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.system.OsInfo;
import com.alibaba.fastjson.JSON;
import com.deepoove.poi.data.PictureType;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.yfd.platform.exception.BadRequestException;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.Color;
import java.awt.Font;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;

/**
 * File工具类，扩展 hutool 工具包
 *
 *
 * @date 2018-12-27
 */
public class FileUtil extends cn.hutool.core.io.FileUtil {

    private static final Logger log = LoggerFactory.getLogger(FileUtil.class);

    /**
     * 系统临时目录
     * <br>
     * windows 包含路径分割符，但Linux 不包含,
     * 在windows \\==\ 前提下，
     * 为安全起见 同意拼装 路径分割符，
     * <pre>
     *       java.io.tmpdir
     *       windows : C:\Users/xxx\AppData\Local\Temp\
     *       linux: /temp
     * </pre>
     */
    public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
    /**
     * 定义GB的计算常量
     */
    private static final int GB = 1024 * 1024 * 1024;
    /**
     * 定义MB的计算常量
     */
    private static final int MB = 1024 * 1024;
    /**
     * 定义KB的计算常量
     */
    private static final int KB = 1024;

    /**
     * 格式化小数
     */
    private static final DecimalFormat DF = new DecimalFormat("0.00");

    public static final String IMAGE = "image";
    public static final String TXT = "document";
    public static final String MUSIC = "music";
    public static final String VIDEO = "video";
    public static final String OTHER = "other";


    /**
     * MultipartFile转File
     */
    public static File toFile(MultipartFile multipartFile) {
        // 获取文件名
        String fileName = multipartFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = "." + getExtensionName(fileName);
        File file = null;
        try {
            // 用uuid作为文件名，防止生成的临时文件重复
            file = File.createTempFile(IdUtil.simpleUUID(), prefix);
            // MultipartFile to File
            multipartFile.transferTo(file);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return file;
    }

    /**
     * 获取文件扩展名，不带 .
     */
    public static String getExtensionName(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                return filename.substring(dot + 1);
            }
        }
        return filename;
    }

    /**
     * Java文件操作 获取不带扩展名的文件名
     */
    public static String getFileNameNoEx(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length()))) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }

    /**
     * 文件大小转换
     */
    public static String getSize(long size) {
        String resultSize;
        if (size / GB >= 1) {
            //如果当前Byte的值大于等于1GB
            resultSize = DF.format(size / (float) GB) + "GB   ";
        } else if (size / MB >= 1) {
            //如果当前Byte的值大于等于1MB
            resultSize = DF.format(size / (float) MB) + "MB   ";
        } else if (size / KB >= 1) {
            //如果当前Byte的值大于等于1KB
            resultSize = DF.format(size / (float) KB) + "KB   ";
        } else {
            resultSize = size + "B   ";
        }
        return resultSize;
    }

    /**
     * inputStream 转 File
     */
    static File inputStreamToFile(InputStream ins, String name) throws Exception {
        File file = new File(SYS_TEM_DIR + name);
        if (file.exists()) {
            return file;
        }
        OutputStream os = new FileOutputStream(file);
        int bytesRead;
        int len = 8192;
        byte[] buffer = new byte[len];
        while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
        return file;
    }

    /**
     * 将文件名解析成文件的上传路径
     */
    public static File upload(MultipartFile file, String filePath) {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
        String name = getFileNameNoEx(file.getOriginalFilename());
        String suffix = getExtensionName(file.getOriginalFilename());
        String nowStr = "-" + format.format(date);
        try {
            String fileName = name + "." + suffix;
            String path = filePath +File.separator + fileName;
            // getCanonicalFile 可解析正确各种路径
            File dest = new File(path).getCanonicalFile();
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                if (!dest.getParentFile().mkdirs()) {
                    log.info("was not successful.");
                }
            }
            // 文件写入
            file.transferTo(dest);
            return dest;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将文件名解析成文件的上传路径
     * file         上传的文件
     * filePath     存储路径
     * tofilename   保存文件名称

     */
    public static File upload(MultipartFile file, String filePath,String tofilename) {
        try {
           String filename = filePath  + File.separator  + tofilename;
            File dest = new File(filename).getCanonicalFile();
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                if (!dest.getParentFile().mkdirs()) {
                }
            }
            // 文件写入
            file.transferTo(dest);
            return dest;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }


    /**
     * 导出excel
     */
    public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
        String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
        String filename = "record" + cn.hutool.core.date.DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        File file = new File(tempPath);
        BigExcelWriter writer = ExcelUtil.getBigWriter(file);
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(list, true);
        SXSSFSheet sheet = (SXSSFSheet) writer.getSheet();
        //上面需要强转SXSSFSheet  不然没有trackAllColumnsForAutoSizing方法
        sheet.trackAllColumnsForAutoSizing();
        //列宽自适应
        //        writer.autoSizeColumnAll();
        sheet.setDefaultColumnWidth(20);
        CellStyle headCellStyle = writer.getHeadCellStyle();
        org.apache.poi.ss.usermodel.Font headFont = writer.createFont();
        headFont.setFontName("宋体");
        //大小
        headFont.setFontHeightInPoints((short) 14);
        //加粗
        headFont.setBold(true);
        headCellStyle.setFont(headFont);
        //response为HttpServletResponse对象
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
        response.setHeader("Content-Disposition", "attachment;filename=" + filename + ".xlsx");
        ServletOutputStream out = response.getOutputStream();
        // 终止后删除临时文件
        file.deleteOnExit();
        writer.flush(out, true);
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }

    /**
     * 导出excel包含图片
     */
    public static void downloadExcelContainImg(int x, List<Map<String, Object>> list, HttpServletResponse response)
            throws IOException {
        String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
        String filename = "record" + cn.hutool.core.date.DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        File file = new File(tempPath);
        BigExcelWriter writer = ExcelUtil.getBigWriter(file);
        //设置默认高度
        // 一次性写出内容，使用默认样式，强制输出标题
        for (int i = 0; i < list.size(); i++) {
            if (Objects.isNull(list.get(i).get("column9"))) {
                continue;
            }
            String imgPath = list.get(i).get("column9").toString();
            imgPath = URLDecoder.decode(imgPath, "utf-8");
            imgPath = "D:/riis/video/" + imgPath;

            boolean exist = FileUtil.exist(new File(imgPath));
            if (!exist) {
                continue;
            }
            //读取图片
            byte[] pictureData = FileUtil.readBytes(imgPath);
            //写入图片
            writePic(writer, x + 1, i + 1, pictureData, getImageType(imgPath));
        }
        for (int i1 = 0; i1 < x; i1++) {
            writer.setColumnWidth(i1, 20);
        }
        writer.write(list, true);
        //response为HttpServletResponse对象
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
        response.setHeader("Content-Disposition", "attachment;filename=" + filename + ".xlsx");
        ServletOutputStream out = response.getOutputStream();
        // 终止后删除临时文件
        file.deleteOnExit();
        writer.flush(out, true);
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }

    /**
     * 导出
     *
     * @param list         数据列表
     * @param excelHeaders 表头
     * @param keys         导出字段属性
     * @param imgs         导出图片字段属性，用逗号隔开
     * @param fileName     文件名称
     * @param response     相应对象
     * @return
     */
    public static void excelImg(List<Map<String, Object>> list, String[] excelHeaders, String[] keys, String imgs,
                                String fileName, HttpServletResponse response) throws IOException {
        // 获取数据列表
        // 创建一个工作簿，对应文件
        XSSFWorkbook workBook = new XSSFWorkbook();

        // 创建一个sheet工作表
        String filename = "record" + cn.hutool.core.date.DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        XSSFSheet sheet = workBook.createSheet(filename);
        // 设置表头单元格样式
        XSSFCellStyle headstyle = workBook.createCellStyle();
        // 设置居中
        headstyle.setAlignment(HorizontalAlignment.CENTER);
        headstyle.setVerticalAlignment(VerticalAlignment.CENTER);
        XSSFFont headFont = workBook.createFont();
        headFont.setFontHeight(14);
        headFont.setBold(true);
        headstyle.setFont(headFont);

        // 创建一般单元格样式
        XSSFCellStyle cellstyle = workBook.createCellStyle();
        cellstyle.setAlignment(HorizontalAlignment.CENTER);
        cellstyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellstyle.setWrapText(true);
        XSSFFont cellFont = workBook.createFont();
        cellFont.setFontHeight(11);
        cellstyle.setFont(cellFont);
        XSSFRow headRow = sheet.createRow(0);
        for (int i = 0; i < excelHeaders.length; i++) {
            XSSFCell cell = headRow.createCell(i);
            cell.setCellValue(excelHeaders[i]);
            cell.setCellStyle(headstyle);
            sheet.setColumnWidth(i, (20 * 256));
        }
        // 创建内容
        XSSFRow row = null;
        for (int rowIndex = 0; rowIndex < list.size(); rowIndex++) {
            row = sheet.createRow(rowIndex + 1);
            row.setHeight((short) (40 * 20));
            // 单元格
            XSSFCell cell = null;
            String s = JSONUtil.toJsonStr(list.get(rowIndex));
            // 转成map
            Map map = (Map) JSON.parse(s);
            for (int j = 0; j < keys.length; j++) {
                cell = row.createCell(j);
                cell.setCellStyle(cellstyle);
                String key = keys[j];
                if (StrUtil.isNotBlank(imgs) && imgs.equals(key)) {
                    cell.setCellValue("");
                    try {
                        //URL photoFile = new URL((String) map.get(keys[j]));
                        // 先把读进来的图片放到一个ByteArrayOutputStream中，以便产生ByteArray
                        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
                        String originfilename = (String) map.get(keys[j]);

                        String temp = StrUtil.subBefore(originfilename, "_", true);
                        String tofilename = temp + "_small.jpg";
                        Thumbnails.of(originfilename)
                                .size(480, 480)
                                .toFile(tofilename);
                        File photoFile = new File(tofilename);
                        boolean exist = FileUtil.exist(photoFile);
                        if (!exist) {
                            throw new RuntimeException("暂无图片");
                        }
                        //将图片读入BufferedImage对象
                        BufferedImage bufferImg = ImageIO.read(photoFile);
                        // 将图片写入流中
                        ImageIO.write(bufferImg, "jpg", byteArrayOut);
                        // 利用HSSFPatriarch将图片写入EXCEL
                        XSSFDrawing patriarch = sheet.createDrawingPatriarch();
                        // 图片一导出到单元格I3-5中 列开始：8 行开始：2 列结束：9 行结束：5
                        XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, j, rowIndex + 1, j, rowIndex + 1);
                        anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
                        // 插入图片内容
                        Picture picture = patriarch.createPicture(anchor, workBook.addPicture(byteArrayOut
                                .toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG));
                        picture.resize(1.05, 1.10);
                        //将图片插入工作表
                    } catch (Exception e) {
                        cell.setCellValue("暂无图片");
                    }
                } else {
                    cell.setCellValue((String) map.get(keys[j]));
                }
            }
        }
        OutputStream out = null;
        try {
            //最终已流的形式返回
            out = response.getOutputStream();
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition",
                    "attachment; filename=" + URLEncoder.encode(fileName + cn.hutool.core.date.DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss") + ".xlsx", "UTF-8"));
            workBook.write(out);

        } catch (Exception e) {
            log.error(e.getMessage());;
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
        }
    }

    /**
     * @param writer
     * @param x           单元格x轴坐标
     * @param y           单元格y轴坐标
     * @param pictureData 图片二进制数据
     * @param picType     图片格式
     */
    private static void writePic(BigExcelWriter writer, int x, int y, byte[] pictureData, int picType) {
        Sheet sheet = writer.getSheet();
        sheet.setDefaultRowHeight((short) 30);
        Drawing drawingPatriarch = sheet.createDrawingPatriarch();
        //设置图片单元格位置
        ClientAnchor anchor = drawingPatriarch.createAnchor(0, 0, 0, 0, x, y, x + 1, y + 1);
        //随单元格改变位置和大小
        //anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);

        //添加图片
        int pictureIndex = sheet.getWorkbook().addPicture(pictureData, picType);
        sheet.setColumnHidden(x - 1, true);
        drawingPatriarch.createPicture(anchor, pictureIndex);
    }

    public static String getFileType(String type) {
        String documents = "txt doc pdf ppt pps xlsx xls docx";
        String music = "mp3 wav wma mpa ram ra aac aif m4a";
        String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
        String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
        if (image.contains(type)) {
            return IMAGE;
        } else if (documents.contains(type)) {
            return TXT;
        } else if (music.contains(type)) {
            return MUSIC;
        } else if (video.contains(type)) {
            return VIDEO;
        } else {
            return OTHER;
        }
    }

    public static void checkSize(long maxSize, long size) {
        // 1M
        int len = 1024 * 1024;
        if (size > (maxSize * len)) {
            throw new BadRequestException("文件超出规定大小");
        }
    }

    /**
     * 判断两个文件是否相同
     */
    public static boolean check(File file1, File file2) {
        String img1Md5 = getMd5(file1);
        String img2Md5 = getMd5(file2);
        return img1Md5.equals(img2Md5);
    }

    /**
     * 判断两个文件是否相同
     */
    public static boolean check(String file1Md5, String file2Md5) {
        return file1Md5.equals(file2Md5);
    }

    private static byte[] getByte(File file) {
        // 得到文件长度
        byte[] b = new byte[(int) file.length()];
        try {
            InputStream in = new FileInputStream(file);
            try {
                log.info(in.read(b)+"");
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        } catch (FileNotFoundException e) {
            log.error(e.getMessage(), e);
            return null;
        }
        return b;
    }

    private static String getMd5(byte[] bytes) {
        // 16进制字符
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(bytes);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char[] str = new char[j * 2];
            int k = 0;
            // 移位 输出字符串
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 下载文件
     *
     * @param request  /
     * @param response /
     * @param file     /
     */
    public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
        if (request != null) {
            response.setCharacterEncoding(request.getCharacterEncoding());
            response.setContentType("application/octet-stream");
        }
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
            IOUtils.copy(fis, response.getOutputStream());
            response.flushBuffer();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                    if (deleteOnExit) {
                        file.deleteOnExit();
                    }
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
    /**
     * 预览PDF文件
     *
     * @param filepath  /
     * @param response /
     */
    public static void viewPDF(String filepath, HttpServletResponse response) throws IOException {
        response.setContentType("application/pdf;charset=UTF-8");
        response.setHeader("Content-Disposition", "inline");
        File file = new File(filepath);
        String originFileName = file.getName();        //中文编码
        //        response.setCharacterEncoding("UTF-8");
        String showName = StrUtil.isNotBlank(originFileName) ? originFileName : file.getName();
        showName = URLDecoder.decode(showName, "UTF-8");
        //        response.setHeader("Content-Disposition","inline;fileName="+new String(showName.getBytes(),
        //        "ISO8859-1")+";fileName*=UTF-8''"+ new String(showName.getBytes(), "ISO8859-1"));
        FileInputStream fis = new FileInputStream(file);
        //        response.setHeader("content-type", "application/msword");
        //        response.setContentType("application/pdf; charset=utf-8");
        ServletOutputStream outputStream = response.getOutputStream();
        IOUtils.copy(fis, outputStream);
        fis.close();
        outputStream.close();
    }

    public static String getMd5(File file) {
        return getMd5(getByte(file));
    }

    /**
     * 获取网络图片流
     *
     * @param url
     * @return
     */
    public static InputStream getImageStream(String url) {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setReadTimeout(5000);
            connection.setConnectTimeout(5000);
            connection.setRequestMethod("GET");
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream inputStream = connection.getInputStream();
                return inputStream;
            }
        } catch (IOException e) {
            log.info("获取网络图片出现异常，图片路径为：" + url);
            log.error(e.getMessage());;
        }
        return null;
    }

    public static void convertBase64ToImage(String base64String, String outputFilePath) {
        try {
            // 解码Base64字符串
            byte[] imageBytes = Base64.getDecoder().decode(base64String);

            // 创建多级目录
            FileUtil.touch(outputFilePath);

            // 创建一个输入流
            try (InputStream inputStream = new ByteArrayInputStream(imageBytes)) {
                // 创建一个输出流，将图像写入文件
                try (FileOutputStream outputStream = new FileOutputStream(outputFilePath)) {
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                }
            }
        } catch (IOException e) {
            log.error(e.getMessage());;
        }
    }

    /**
     * 在原始图片上标注矩形框，并返回图片名称
     *
     * @param originfilename，jsonStr
     * @return
     */
    public static void  MarkImageRectangle(String originfilename,String jsonStr,String markedfilename) {
        try {
            log.info("pos:" + jsonStr);
            BufferedImage image = ImageIO.read(new File(originfilename));
            Graphics g = image.getGraphics();
            Graphics2D g2 = (Graphics2D) g; //将g转换为Graphics2D
            BasicStroke stroke = new BasicStroke(5.0f); //创建一个粗细为5的BasicStroke对象
            g2.setStroke(stroke); //设置画线的粗细
            g2.setColor(Color.RED);//画笔颜色

            //: [{"coors": [{"x": 10,"y": 15}, {"x": 100,"y": 150},{"x": 110,"y": 170},{"x": 200,
            //"y": 270}]},{"coors": [{"x": 30,"y": 20}, {"x": 150,"y": 200}]}]
            //pos:[{"coors":[{"x":216,"y":480},{"x":584,"y":156}]}]
            JSONArray rectangles= JSONUtil.parseArray(jsonStr);
            for (int i = 0; i < rectangles.size(); i++) {
                JSONObject jobj = rectangles.getJSONObject(i);
                JSONArray points = jobj.getJSONArray("areas");
                if (points.size() == 1) {
                    //画笔颜色设置为绿色
                    g2.setColor(Color.GREEN);
                    JSONObject point = points.getJSONObject(0);
                    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
                    BasicStroke stroke1 = new BasicStroke(3.0f);
                    g2.setStroke(stroke1);
                    Integer x = point.getInt("x");
                    Integer y = point.getInt("y");
                    // 画十字
                    g2.drawLine(x - 10, y, x + 10, y);
                    g2.drawLine(x, y - 10, x, y + 10);
                } else if (points.size() == 2) {
                    //矩形框
                    JSONObject leftuppoint = points.getJSONObject(0);
                    JSONObject rightdownpoint = points.getJSONObject(1);
                    int width = rightdownpoint.getInt("x") - leftuppoint.getInt("x");
                    int height = Math.abs(rightdownpoint.getInt("y") - leftuppoint.getInt("y"));
                    log.info("width" + width);
                    log.info("height" + height);
                    //矩形框(原点x坐标，原点y坐标，矩形的长，矩形的宽)
                    g2.drawRect(leftuppoint.getInt("x"), leftuppoint.getInt("y"), width, height);
                } else {
                    //多边形
                    int size = points.size();
                    int[] x = new int[size];
                    int[] y = new int[size];
                    for (int j = 0; j < points.size(); j++) {
                        JSONObject point = points.getJSONObject(j);
                        x[i] = point.getInt("x");
                        y[i] = point.getInt("y");
                    }
                    g2.drawPolygon(x, y, points.size());//画多边形
                }

            }
           // 释放资源
            g.dispose();
            g2.dispose();
            FileOutputStream out = new FileOutputStream(markedfilename);//输出图片的地址
            ImageIO.write(image, "jpg", out);
            out.close();
        } catch (FileNotFoundException ex) {
            log.error(ex.getMessage());
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }

    /**
     * 在原始图片上标注矩形框，并返回图片名称
     *
     * @param originfilename，jsonStr
     * @return
     */
    public static void  MarkImageRectangle1(String originfilename,String jsonStr,String markedfilename) {
        try {
            log.info("pos:" + jsonStr);
            BufferedImage image = ImageIO.read(new File(originfilename));
            Graphics g = image.getGraphics();
            Graphics2D g2 = (Graphics2D) g; //将g转换为Graphics2D
            BasicStroke stroke = new BasicStroke(5.0f); //创建一个粗细为5的BasicStroke对象
            g2.setStroke(stroke); //设置画线的粗细
            g2.setColor(Color.RED);//画笔颜色

            //: [{"coors": [{"x": 10,"y": 15}, {"x": 100,"y": 150},{"x": 110,"y": 170},{"x": 200,
            //"y": 270}]},{"coors": [{"x": 30,"y": 20}, {"x": 150,"y": 200}]}]
            //pos:[{"coors":[{"x":216,"y":480},{"x":584,"y":156}]}]
            JSONArray rectangles= JSONUtil.parseArray(jsonStr);
            for (int i = 0; i < rectangles.size(); i++) {
                JSONObject jobj = rectangles.getJSONObject(i);
                JSONArray points = jobj.getJSONArray("areas");
                if (points.size() == 1) {
                    //画笔颜色设置为绿色
                    g2.setColor(Color.GREEN);
                    JSONObject point = points.getJSONObject(0);
                    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
                    BasicStroke stroke1 = new BasicStroke(3.0f);
                    g2.setStroke(stroke1);
                    Integer x = point.getInt("x");
                    Integer y = point.getInt("y");
                    // 画十字
                    g2.drawLine(x - 10, y, x + 10, y);
                    g2.drawLine(x, y - 10, x, y + 10);
                } else if (points.size() == 2) {
                    // 字体、样式和大小
                    Font font = new Font("微软雅黑", Font.PLAIN, 20);
                    //画笔颜色设置为绿色
                    g2.setFont(font);
                    // 要绘制的文字
                    String text = "表盘破损";
                    //矩形框
                    JSONObject leftuppoint = points.getJSONObject(0);
                    JSONObject rightdownpoint = points.getJSONObject(1);
                    int width = rightdownpoint.getInt("x") - leftuppoint.getInt("x");
                    int height = Math.abs(rightdownpoint.getInt("y") - leftuppoint.getInt("y"));
                    log.info("width" + width);
                    log.info("height" + height);
                    // 绘制缺陷文字
                    g2.drawString(text, leftuppoint.getInt("x"), leftuppoint.getInt("y")-10);
                    //矩形框(原点x坐标，原点y坐标，矩形的长，矩形的宽)
                    g2.drawRect(leftuppoint.getInt("x"), leftuppoint.getInt("y"), width, height);
                } else {
                    //多边形
                    int size = points.size();
                    int[] x = new int[size];
                    int[] y = new int[size];
                    for (int j = 0; j < points.size(); j++) {
                        JSONObject point = points.getJSONObject(j);
                        x[i] = point.getInt("x");
                        y[i] = point.getInt("y");
                    }
                    g2.drawPolygon(x, y, points.size());//画多边形
                }

            }
            // 释放资源
            g.dispose();
            g2.dispose();
            FileOutputStream out = new FileOutputStream(markedfilename);//输出图片的地址
            ImageIO.write(image, "jpg", out);
            out.close();
        } catch (FileNotFoundException ex) {
            log.error(ex.getMessage());
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }

    /**
     * 根据图片后缀返回图片类型
     *
     * @param url
     * @return
     */
    public static PictureType getPictureType(String url) {
        if (StrUtil.isBlank(url)) {
            return null;
        }
        if (url.endsWith(".jpeg") || url.endsWith(".jpg")) {
            return PictureType.JPEG;
        }
        if (url.endsWith(".png")) {
            return PictureType.PNG;
        }
        return null;
    }

    /**
     * 根据图片后缀返回图片类型(excel)
     *
     * @param url
     * @return
     */
    public static int getImageType(String url) {
        if (StrUtil.isBlank(url)) {
            return 0;
        }

        if (url.endsWith(".jpeg") || url.endsWith(".jpg")) {
            return HSSFWorkbook.PICTURE_TYPE_JPEG;
        }
        if (url.endsWith(".png")) {
            return HSSFWorkbook.PICTURE_TYPE_PNG;
        }
        return 0;
    }

    /**********************************
     * 用途说明: 解析二维码
     * 参数说明 file
     * 返回值说明: java.lang.String
     ***********************************/
    public static String resolveCodeByFile(String path) {
        String content = null;
        BufferedImage image;
        try {
            File file = new File(path);
            boolean exist = FileUtil.exist(file);
            if (!exist) {
                return null;
            }
            image = ImageIO.read(file);
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            Result result = new MultiFormatReader().decode(binaryBitmap, hints);//解码
            log.info("图片中内容：  ");
            log.info("content： " + result.getText());
            content = result.getText();
        } catch (IOException e) {
            log.error(e.getMessage());;
        } catch (NotFoundException e) {
            //这里判断如果识别不了带LOGO的图片，重新添加上一个属性
            try {
                File file = new File(path);
                boolean exist = FileUtil.exist(file);
                if (!exist) {
                    return null;
                }
                image = ImageIO.read(file);
                LuminanceSource source = new BufferedImageLuminanceSource(image);
                Binarizer binarizer = new HybridBinarizer(source);
                BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
                Map<DecodeHintType, Object> hints = new HashMap<>();
                //设置编码格式
                hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
                //设置优化精度
                hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
                //设置复杂模式开启（我使用这种方式就可以识别微信的二维码了）
                hints.put(DecodeHintType.PURE_BARCODE, Boolean.TYPE);
                Result result = new MultiFormatReader().decode(binaryBitmap, hints);//解码
                log.info("图片中内容：  ");
                log.info("content： " + result.getText());
                content = result.getText();
            } catch (Exception e1) {
                log.error(e1.getMessage());
            }
        }
        return content;
    }

    /**
     * 预览Image文件
     *
     * @param filepath  /
     * @param response /
     */
    public static void viewImage(String filepath, HttpServletResponse response) throws IOException {
        response.setHeader("Content-type", "jpeg");
        response.setHeader("Content-Disposition", "inline; filename=111.jpg");
        File file = new File(filepath);
        FileInputStream in = new FileInputStream(file);
        ServletOutputStream out = response.getOutputStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len=in.read(buf)) != -1) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();

    }

    /**
     * 播放音频
     *
     * @param filepath  /
     * @param response /
     */
    public static void playAudio(String filepath, HttpServletResponse response) throws IOException {
        response.setHeader("Content-type", "audio/wav");
        response.setHeader("Content-Disposition", "inline; filename=111.wav");
        File file = new File(filepath);
        FileInputStream in = new FileInputStream(file);
        ServletOutputStream out = response.getOutputStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len=in.read(buf)) != -1) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
    }

    public static void addWaterMark(String srcImgPath, String tarImgPath, String waterMarkContent,
                                    int pos_x,int pos_y,
                                    Color markContentColor,
                                    Font font) {

        try {
            // 读取原图片信息
            File srcImgFile = new File(srcImgPath);//得到文件
            boolean exist = FileUtil.exist(srcImgFile);
            if (!exist) {
                return;
            }

            Image srcImg = ImageIO.read(srcImgFile);//文件转化为图片
            int srcImgWidth = srcImg.getWidth(null);//获取图片的宽
            int srcImgHeight = srcImg.getHeight(null);//获取图片的高
            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            g.setColor(markContentColor); //根据图片的背景设置水印颜色
            g.setFont(font);              //设置字体

            //画出水印
            if(pos_y>0) {
                g.drawString(waterMarkContent, pos_x, pos_y);
            }else{
                g.drawString(waterMarkContent, pos_x, srcImgHeight+pos_y);
            }

            g.dispose();
            // 输出图片
            FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
            ImageIO.write(bufImg, "jpg", outImgStream);
            outImgStream.flush();
            outImgStream.close();

        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    public static String parseNodeToXML(List<Map<String, Object>> mapList, String filePath, String Node) throws IOException {
        StringBuilder xml = new StringBuilder();
        xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        xml.append("<").append(Node).append(">\n");
        for (Map<String, Object> map : mapList) {
            xml.append("<Item ");
            for (String key : map.keySet()) {
                String value = "";
                if (ObjectUtil.isNotEmpty(map.get(key))) {
                    value = EscapeUtil.escapeXml(map.get(key).toString());
                }
                xml.append(key).append("=\"").append(value).append("\" ");
            }
            xml.append("/>\n");
        }
        xml.append("</").append(Node).append(">");
        // 分离文件名和目录路径
        File file = new File(filePath);
        File directory = file.getParentFile();

        // 如果目录不存在，则创建它
        if (!directory.exists() && !directory.mkdirs()) {
            throw new IOException("无法创建目录: " + directory.getAbsolutePath());
        }

        FileWriter writer = new FileWriter(filePath);
        writer.write(xml.toString());
        writer.flush();
        writer.close();
        log.info("写入完成！");
        return filePath;
    }



    public static void convertCsvToBinary(String csvFilePath,String binaryFilePath) {
           try {
               FileInputStream csvInputStream = new FileInputStream(csvFilePath);
               FileOutputStream binaryOutputStream = new FileOutputStream(binaryFilePath);

               // 写入文件头部分（64个字节）
               byte[] header = new byte[64];
               binaryOutputStream.write(header);

               // 逐行读取CSV文件，解析温度数据并转换为二进制写入
               BufferedReader csvReader = new BufferedReader(new InputStreamReader(csvInputStream));
               String line;
               while ((line = csvReader.readLine()) != null) {
                   String[] temperatures = line.split(",");
                   for (String temperatureStr : temperatures) {
                       float temp = Float.parseFloat(temperatureStr);
                       int intValue = (int) (temp * 10);
                       short temperature = (short) intValue;
                       binaryOutputStream.write(temperature & 0xFF);      // 低位
                       binaryOutputStream.write((temperature >> 8) & 0xFF); // 高位
                   }
               }

                // 关闭流
                csvReader.close();
               csvInputStream.close();
               binaryOutputStream.close();

               log.info("Conversion complete.");
           } catch (IOException e) {
               log.error(e.getMessage());;
           }

    }

    public static void downloadFile(String fileURL, String saveDir, String fileName) {
        try {
            OsInfo osInfo = new OsInfo();
            saveDir = saveDir.replace("/", "\\");
            if (osInfo.isLinux()) {
                saveDir = saveDir.replace("\\", "/");
            }
            URL url = new URL(fileURL);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            int responseCode = httpConn.getResponseCode();

            // 总是检查HTTP响应码
            if (responseCode == HttpURLConnection.HTTP_OK) {
                String disposition = httpConn.getHeaderField("Content-Disposition");
                String contentType = httpConn.getContentType();
                int contentLength = httpConn.getContentLength();

                // 提示信息
                log.info("Content-Type = " + contentType);
                log.info("Content-Disposition = " + disposition);
                log.info("Content-Length = " + contentLength);
                log.info("filename=" + fileName);
                log.info("fileURL=" + fileURL);
                // 打开一个流以读取服务器上的文件数据
                InputStream inputStream = httpConn.getInputStream();
                String saveFilePath = saveDir + fileName;
                log.info("saveFilePath=" + saveFilePath);
                // 创建File对象
                //                File file = new File(saveFilePath);
                //                File file = cn.hutool.core.io.FileUtil.touch(saveFilePath);
                cn.hutool.core.io.FileUtil.mkdir(saveDir);
                // 检查并创建父目录
                //                if (!file.getParentFile().exists()) {
                //                    if (!file.getParentFile().mkdirs()) {
                //                        return; // 或者抛出异常，根据你的需求
                //                    }
                //                }
                // 打开一个流以写入本地文件
                FileOutputStream outputStream = new FileOutputStream(saveFilePath);

                int bytesRead = -1;
                byte[] buffer = new byte[4096];
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                outputStream.close();
                inputStream.close();

               log.info("File downloaded");

            } else {
                log.error("No file to download. Server replied HTTP code: " + responseCode);
            }
            httpConn.disconnect();
        } catch (IOException e) {
            log.error(e.getMessage());;
        }
    }

}
