package com.qmth.distributed.print.business.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.awt.AsianFontMapper;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.qmth.distributed.print.business.bean.dto.PdfPackageDto;
import com.qmth.distributed.print.business.bean.dto.PdfSignDto;
import com.qmth.distributed.print.business.entity.BasicTemplate;
import com.qmth.distributed.print.business.service.PrintCommonService;
import com.qmth.teachcloud.common.contant.SpringContextHolder;
import com.qmth.teachcloud.common.enums.ClassifyEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
 * pdf模板内容填充
 */
public class PdfFillUtils {
    private final static Logger log = LoggerFactory.getLogger(PdfFillUtils.class);

    // 定义全局的字体静态变量
    public static Font textFont28;
    public static Font textFont24;
    public static Font textFont22;
    public static Font textFont18;
    public static Font textFont16;
    public static Font textFont14;
    public static Font textFont12;
    public static Font textFont11;
    public static Font textFont10;
    public static Font textFont9;
    public static Font textFont8;

    // 静态代码块
    static {
        try {
            //解决中文不显示问题
            BaseFont bfChinese = BaseFont.createFont(AsianFontMapper.ChineseSimplifiedFont, AsianFontMapper.ChineseSimplifiedEncoding_H, BaseFont.NOT_EMBEDDED);
            textFont28 = new Font(bfChinese, 28);
            textFont24 = new Font(bfChinese, 24);
            textFont22 = new Font(bfChinese, 22);
            textFont18 = new Font(bfChinese, 18);
            textFont16 = new Font(bfChinese, 16);
            textFont14 = new Font(bfChinese, 14);
            textFont12 = new Font(bfChinese, 12);
            textFont11 = new Font(bfChinese, 11);
            textFont10 = new Font(bfChinese, 10);
            textFont9 = new Font(bfChinese, 9);
            textFont8 = new Font(bfChinese, 8);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 签到表预览数据
     *
     * @param basicTemplate 数据内容
     * @param fileName      文件名
     */
    public static File parseSignTempData(BasicTemplate basicTemplate, String fileName) {
        PdfSignDto pdfFillDto = new PdfSignDto();
        pdfFillDto.setTitle("签到表样例");
        pdfFillDto.setPackageNumber("123456789");
        pdfFillDto.setTextDesc(basicTemplate.getTextDesc());

        JSONObject jsonObject = JSON.parseObject(basicTemplate.getDisplayRange());
        // 基础信息
        List<Map<String, String>> basicPlate = new ArrayList<>();
        String basicData = jsonObject.getString("basic");
        List<JSONObject> basicObjectList = JSON.parseArray(basicData, JSONObject.class).stream().filter(m -> m.getBoolean("enable")).collect(Collectors.toList());

        boolean isCourseHasTwo = basicObjectList.stream().filter(m -> "courseCode".equals(m.getString("code")) || "courseName".equals(m.getString("code"))).count() == 2;
        boolean isDateHasTwo = basicObjectList.stream().filter(m -> "examDate".equals(m.getString("code")) || "examTime".equals(m.getString("code"))).count() == 2;
        boolean isPlaceHasTwo = basicObjectList.stream().filter(m -> "examPlace".equals(m.getString("code")) || "examRoom".equals(m.getString("code"))).count() == 2;


        boolean isCourseFill = false;
        boolean isDateFill = false;
        boolean isPlaceFill = false;

        Map<String, String> basicMap;
        for (JSONObject object : basicObjectList) {
            String code = object.getString("code");
            String name = object.getString("name");

            if ("courseCode".equals(code) || "courseName".equals(code)) {
                basicMap = new HashMap<>();
                if (isCourseHasTwo) {
                    if (isCourseFill) {
                        continue;
                    }
                    basicMap.put("code", "courseName");
                    basicMap.put("name", "课程名称");
                    basicMap.put("value", "xxx(xxx)");
                    isCourseFill = true;
                } else {
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", "xxx");
                }
                basicPlate.add(basicMap);
            } else if ("examDate".equals(code) || "examTime".equals(code)) {
                basicMap = new HashMap<>();
                if (isDateHasTwo) {
                    if (isDateFill) {
                        continue;
                    }
                    String examTime;
                    basicMap.put("code", "examTime");
                    basicMap.put("name", "考试时间");
                    basicMap.put("value", "xxxx-xx-xx xx:xx-xx:xx");
                    isDateFill = true;
                } else {
                    String examTime = "";
                    if ("examDate".equals(code)) {
                        examTime = "xxxx-xx-xx";
                    } else if ("examTime".equals(code)) {
                        examTime = "xx:xx-xx:xx";
                    }
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", examTime);
                }
                basicPlate.add(basicMap);
            } else if ("examPlace".equals(code) || "examRoom".equals(code)) {
                basicMap = new HashMap<>();
                if (isPlaceHasTwo) {
                    if (isPlaceFill) {
                        continue;
                    }
                    basicMap.put("code", "examRoom");
                    basicMap.put("name", "考试地点");
                    basicMap.put("value", "xx地点 xx教室");
                    isPlaceFill = true;
                } else {
                    String string = null;
                    if ("examPlace".equals(code)) {
                        string = "xx地点";
                    }
                    if ("examRoom".equals(code)) {
                        string = "xx教室";
                    }
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", string);
                }
                basicPlate.add(basicMap);
            } else {
                basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", "xxx");
                basicPlate.add(basicMap);
            }
        }

        pdfFillDto.setBasicPlate(basicPlate);

        // 表头信息
        String studentData = jsonObject.getString("table");
        List<JSONObject> studentObjectList = JSON.parseArray(studentData, JSONObject.class).stream().filter(m -> m.getBoolean("enable")).collect(Collectors.toList());
        Map<String, String> studentHeadPlateMap = new LinkedHashMap<>();
        for (JSONObject object : studentObjectList) {
            studentHeadPlateMap.put(object.getString("code"), object.getString("name"));
        }
        studentHeadPlateMap.put("studentSign", "签名");
        pdfFillDto.setStudentHeadPlate(studentHeadPlateMap);


        // 考生信息
        List<Map<String, String>> studentPlate = new ArrayList<>();
        int studentCount = basicTemplate.getDiallel() == null || basicTemplate.getDiallel() ? 80 : 40;
        for (int i = 0; i < studentCount; i++) {
            Map<String, String> studentMap = new HashMap<>();
            for (JSONObject object : studentObjectList) {
                studentMap.put(object.getString("code"), "xxx");
            }
            studentMap.put("studentSign", "");
            studentPlate.add(studentMap);
        }
        pdfFillDto.setStudentPlate(studentPlate);
        try {
            CreatePrintPdfUtil createPrintPdfUtil = new CreatePrintPdfUtil();
            return createPrintPdfUtil.createSignPdf(pdfFillDto, fileName, basicTemplate);

        } catch (
                Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 卷袋贴临时数据
     *
     * @param data data
     */
    public static File packageTempData(String data, String fileName) {
        PdfPackageDto pdfPackageDto = new PdfPackageDto();
        pdfPackageDto.setTitle("卷袋贴样例");
        pdfPackageDto.setTag(true);
        pdfPackageDto.setPackageNumber("123456789");

        JSONObject objectList = JSON.parseObject(data);
        List<JSONObject> titleObjectList = JSON.parseArray(objectList.getString("title"), JSONObject.class);
        List<Map<String, String>> titlePlate = new ArrayList<>();
        for (JSONObject object : titleObjectList) {
            if (object.getBoolean("enable")) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", object.getString("code"));
                basicMap.put("name", object.getString("name"));
                basicMap.put("value", "xxx-xxx学期 课程考试");
                titlePlate.add(basicMap);
            }
        }
        pdfPackageDto.setTitlePlate(titlePlate);
        // 基础信息
        List<JSONObject> basicObjectList = JSON.parseArray(objectList.getString("basic"), JSONObject.class).stream().filter(m -> m.getBoolean("enable")).collect(Collectors.toList());
        boolean isCourseHasTwo = basicObjectList.stream().filter(m -> "courseCode".equals(m.getString("code")) || "courseName".equals(m.getString("code"))).count() == 2;
        boolean isDateHasTwo = basicObjectList.stream().filter(m -> "examDate".equals(m.getString("code")) || "examTime".equals(m.getString("code"))).count() == 2;
        boolean isCourseFill = false;
        boolean isDateFill = false;

        List<Map<String, String>> basicPlate = new ArrayList<>();
        for (JSONObject object : basicObjectList) {
            String code = object.getString("code");
            String name = object.getString("name");
            if ("examDate".equals(code) || "examTime".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                if (isDateHasTwo) {
                    if (isDateFill) {
                        continue;
                    }
                    basicMap.put("code", "examTime");
                    basicMap.put("name", "考试时间");
                    basicMap.put("value", "xxxx-xx-xx xx:xx-xx:xx");
                    isDateFill = true;
                } else {
                    String examTime = "";
                    if ("examDate".equals(code)) {
                        examTime = "xxxx-xx-xx";
                    } else if ("examTime".equals(code)) {
                        examTime = "xx:xx-xx:xx";
                    }
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", examTime);
                }
                basicPlate.add(basicMap);
            } else if ("courseCode".equals(code) || "courseName".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                if (isCourseHasTwo) {
                    if (isCourseFill) {
                        continue;
                    }
                    basicMap.put("code", "courseName");
                    basicMap.put("name", "课程名称");
                    basicMap.put("value", "xxx(xxx)");
                    isCourseFill = true;
                } else {
                    basicMap.put("code", code);
                    basicMap.put("name", name);
                    basicMap.put("value", "xxx");
                }
                basicPlate.add(basicMap);
            } else if ("examPlace".equals(code) || "campusName".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", "xxx");
                basicPlate.add(basicMap);
            } else if ("examRoom".equals(code) || "examClassroomName".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", "xxx");
                basicPlate.add(basicMap);
            } else if ("examCount".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", "xxx + x");
                basicPlate.add(basicMap);
            } else if ("actualExamCount".equals(code)) {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", "");
                basicPlate.add(basicMap);
            } else {
                Map<String, String> basicMap = new HashMap<>();
                basicMap.put("code", code);
                basicMap.put("name", name);
                basicMap.put("value", "xxx");
                basicPlate.add(basicMap);
            }
        }
        pdfPackageDto.setBasicPlate(basicPlate);

        try {
            CreatePrintPdfUtil createPrintPdfUtil = new CreatePrintPdfUtil();
            return createPrintPdfUtil.createPackagePdf(pdfPackageDto, fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 填充table
     *
     * @param value     cell内容
     * @param font      字体
     * @param cellColor 背景色
     */
    public static PdfPCell createCell(String value, Font font, BaseColor cellColor, int horizontalAlignment, int disableBorderSide, int rowspan, int colspan) {
        PdfPCell cell = new PdfPCell();
        cell.setBorderWidth(0.5F);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(horizontalAlignment);
        cell.setUseAscender(true);
//        cell.setNoWrap(false);
        if (font != null) {
            cell.setPhrase(new Phrase(value, font));
        } else {
            cell.setPhrase(new Phrase(value));
        }
        if (cellColor != null) {
            cell.setBackgroundColor(cellColor);
        }
//        cell.setMinimumHeight(20f);
        if (disableBorderSide > 0) {
            cell.disableBorderSide(disableBorderSide);
        }
        if (rowspan > 0) {
            cell.setRowspan(rowspan);
        }
        if (colspan > 0) {
            cell.setColspan(colspan);
        }
        return cell;
    }

    /**
     * 填充table
     * <p>
     * +     * @param value     cell内容
     * +     * @param font      字体
     * +     * @param cellColor 背景色
     * +
     */
    public static PdfPCell createCell1(Double lineHeightTimes, String value, Font font, BaseColor cellColor, int horizontalAlignment, int disableBorderSide, int rowspan, int colspan) {
        PdfPCell cell = new PdfPCell();
        cell.setBorderWidth(0.5F);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(horizontalAlignment);
        cell.setUseAscender(true);
        //        cell.setNoWrap(false);
        if (font != null) {
            cell.setPhrase(new Phrase(value, font));
        } else {
            cell.setPhrase(new Phrase(value));
        }
        if (cellColor != null) {
            cell.setBackgroundColor(cellColor);
        }
        //                cell.setFixedHeight(18f);
        BigDecimal bigDecimal = new BigDecimal(cell.getPhrase().getFont().getSize() * lineHeightTimes * 1.5).setScale(1, RoundingMode.HALF_UP);
        cell.setMinimumHeight(bigDecimal.floatValue());
        //        cell.setMinimumHeight(20f);
        if (disableBorderSide > 0) {
            cell.disableBorderSide(disableBorderSide);
        }
        if (rowspan > 0) {
            cell.setRowspan(rowspan);
        }
        if (colspan > 0) {
            cell.setColspan(colspan);
        }
        return cell;
    }

    /**
     * 填充table
     *
     * @param value cell内容
     * @param font  字体
     */
    public static PdfPCell createTitleCell(String value, Font font, float fixedHeight, int disableBorderSide, int rowspan, int colspan) {
        PdfPCell cell = new PdfPCell();
        cell.setBorderWidth(0.5F);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setFixedHeight(fixedHeight);
//        cell.setUseAscender(true);
//        cell.setNoWrap(false);
        if (font != null) {
            cell.setPhrase(new Phrase(value, font));
        } else {
            cell.setPhrase(new Phrase(value));
        }
        if (disableBorderSide > 0) {
            cell.disableBorderSide(disableBorderSide);
        }
        if (rowspan > 0) {
            cell.setRowspan(rowspan);
        }
        if (colspan > 0) {
            cell.setColspan(colspan);
        }
        return cell;
    }

    /**
     * 填充table
     *
     * @param value       cell内容
     * @param font        字体
     * @param fixedHeight 垂直对齐方式
     */
    public static PdfPCell createCell(String value, Font font, float fixedHeight, int horizontalAlignment, float paddingLeft) {
        PdfPCell cell = new PdfPCell();
        cell.setBorderWidth(0.5F);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(horizontalAlignment);
        cell.setUseAscender(true);
        cell.setPaddingTop(10f);
        cell.setPaddingBottom(10f);
        if (font != null) {
            cell.setPhrase(new Phrase(value, font));
        } else {
            cell.setPhrase(new Phrase(value));
        }
        cell.disableBorderSide(15);
        if (paddingLeft > 0) {
            cell.setPaddingLeft(paddingLeft);
        }
        return cell;
    }

    /**
     * 填充table
     *
     * @param image       cell内容
     * @param fixedHeight 垂直对齐方式
     */
    public static PdfPCell createCell(Image image, float fixedHeight, int horizontalAlignment, int disableBorderSide, int rowspan, int colspan) {
        PdfPCell cell = new PdfPCell(image);
        cell.setBorderWidth(0.5F);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setUseAscender(true);
        cell.setHorizontalAlignment(horizontalAlignment);
//        cell.setExtraParagraphSpace(10);
        if (fixedHeight > 0) {
            cell.setFixedHeight(fixedHeight);
        }
        if (disableBorderSide > 0) {
            cell.disableBorderSide(disableBorderSide);
        }
        if (rowspan > 0) {
            cell.setRowspan(rowspan);
        }
        if (colspan > 0) {
            cell.setColspan(colspan);
        }
        return cell;
    }

    /**
     * 填充table
     *
     * @param image       cell内容
     * @param fixedHeight 垂直对齐方式
     */
    public static PdfPCell createCellBarCode(Image image, float fixedHeight, int horizontalAlignment, int disableBorderSide, int rowspan, int colspan) {
        PdfPCell cell = new PdfPCell(image);
        cell.setBorderWidth(0.5F);
        cell.setVerticalAlignment(Element.ALIGN_TOP);
        cell.setUseAscender(true);
        cell.setHorizontalAlignment(horizontalAlignment);
        if (fixedHeight > 0) {
            cell.setFixedHeight(fixedHeight);
        }
        if (disableBorderSide > 0) {
            cell.disableBorderSide(disableBorderSide);
        }
        if (rowspan > 0) {
            cell.setRowspan(rowspan);
        }
        if (colspan > 0) {
            cell.setColspan(colspan);
        }
        return cell;
    }

    /**
     * 创建指定列宽、列数的表格
     *
     * @param columns 单元格数量
     */
    public static PdfPTable createTable(int columns) {
        PdfPTable table = new PdfPTable(columns);
        try {
            table.setWidthPercentage(100);// 表格宽度为100%
        } catch (Exception e) {
            e.printStackTrace();
        }
        return table;
    }

    /**
     * 创建指定列宽、列数的表格
     *
     * @param widths 宽度
     */
    public static PdfPTable createTable(float[] widths) {
        PdfPTable table = new PdfPTable(widths.length);
        try {
            table.setTotalWidth(widths);
            table.setWidthPercentage(100);// 表格宽度为100%
        } catch (Exception e) {
            e.printStackTrace();
        }
        return table;
    }

    /**
     * 创建条形码
     *
     * @param writer   writer
     * @param barCode  条形码(数字)
     * @param hideCode 是否隐藏条形码(数字)
     */
    public static Image createBarcode(PdfWriter writer, String barCode, Boolean hideCode, BaseColor barColor, BaseColor textColor) {
        Barcode128 barcode128 = new Barcode128();
        barcode128.setCode(barCode);//设置数字
        barcode128.setCodeType(Barcode.CODE128);
        barcode128.setX(1.5f); // 设置条码线条宽度
        //设置字体
        if (hideCode) {
            barcode128.setFont(null);
        }
        return barcode128.createImageWithBarcode(writer.getDirectContent(), barColor, textColor);
    }

}
