package com.ruoyi.ptxlib.service.impl;

import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.MyUtils;
import com.ruoyi.ptxlib.domain.PTXLabelCode;
import com.ruoyi.ptxlib.domain.PTXLabelInfo;
import com.ruoyi.ptxlib.domain.PTXLabelText;
import com.ruoyi.ptxlib.service.PTXLib;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.List;

import static com.ruoyi.ptxlib.constant.PTXConstants.MaxPrintWidth;

@Service
public class PTXService {
    /**
     * 打印标签内容过滤
     *
     * @param ptxLabelInfo 打印标签信息
     * @param filterData 过滤数据
     * @return 打印标签数据
     */
    public PTXLabelInfo filterInfo(PTXLabelInfo ptxLabelInfo, Object filterData) {
        String epc = ptxLabelInfo.getEpc();
        String[] symbolContent = MyUtils.getSymbolContent(epc);
        epc = MyUtils.replaceBrackets(filterData, epc, symbolContent);
        ptxLabelInfo.setEpc(epc);

        List<PTXLabelText> ptxLabelTexts = ptxLabelInfo.getPtxLabelTexts();
        if (!ptxLabelTexts.isEmpty()) {
            for (PTXLabelText ptxLabelText : ptxLabelTexts) {
                // 拥有占位符的打印字符串
                String printData = ptxLabelText.getPrintData();
                // 获取占位符中的字符串集
                String[] symbolContents = MyUtils.getSymbolContent(printData);

                printData = MyUtils.replaceBrackets(filterData, printData, symbolContents);
                ptxLabelText.setPrintData(printData);
            }
        }

        List<PTXLabelCode> ptxLabelCodes = ptxLabelInfo.getPtxLabelCodes();
        if (!ptxLabelCodes.isEmpty()) {
            for (PTXLabelCode ptxLabelCode : ptxLabelCodes) {
                String data = ptxLabelCode.getData();
                // 获取占位符中的字符串集
                String[] symbolContents = MyUtils.getSymbolContent(data);
                data = MyUtils.replaceBrackets(filterData, data, symbolContents);
                ptxLabelCode.setData(data);
            }
        }

        return ptxLabelInfo;
    }

    /**
     * 打印标签
     *
     * @param labelInfo 标签信息
     */
    public void printLabel(PTXLabelInfo labelInfo) {
        // 初始化
        PTXLib.INSTANCE.PTXA_DLLinit();

        // 获取连接类型
        Integer connectType = labelInfo.getConnectType();
        // 本地连接
        if (connectType == null || connectType == 0) {
            String printerName = labelInfo.getPrinterName();
            if (StrUtil.isBlank(printerName)) {
                throw new RuntimeException("驱动程序名称不能为空");
            }
            PTXLib.INSTANCE.openport(printerName);
        } else if (connectType == 1) { // 远程连接
            String connectIpAddress = labelInfo.getConnectIpAddress();
            Integer connectPort = labelInfo.getConnectPort();
            if (StrUtil.isBlank(connectIpAddress)) {
                throw new RuntimeException("连接地址不能为空");
            }
            if (connectPort == null) {
                connectPort = 80;
            }
            PTXLib.INSTANCE.openethernet(connectIpAddress, connectPort);
        }

        Integer pid = labelInfo.getPid();
        // 创建表单
        createForm(pid);

        // 加粗
        Boolean isBold = labelInfo.getIsBold();
        if (isBold != null && isBold) {
            setBold(true);
        }

        // 写入EPC
        String epc = labelInfo.getEpc();
        if (StrUtil.isNotBlank(epc)) {
            writeRFID(epc);
        }

        // 打印文字
        List<PTXLabelText> ptxLabelTexts = labelInfo.getPtxLabelTexts();
        if (ptxLabelTexts != null && !ptxLabelTexts.isEmpty()) {
            for (PTXLabelText labelText : ptxLabelTexts) {
                Integer textType = labelText.getTextType();
                if (textType == 1) {
                    printText(labelText);
                    continue;
                }
                printTextEn(labelText);
            }
        }

        // 打印二维码
        List<PTXLabelCode> ptxLabelCodes = labelInfo.getPtxLabelCodes();
        if (ptxLabelCodes != null && !ptxLabelCodes.isEmpty()) {
            for (PTXLabelCode labelCode : ptxLabelCodes) {
                Integer codeType = labelCode.getCodeType();
                if (codeType == 1) {
                    printCode128(labelCode);
                }
                if (codeType == 2) {
                    printQrCode(labelCode);
                }
            }
        }

        // 打印此表单
        printForm();
        // 关闭端口
        PTXLib.INSTANCE.closeport();
    }

    /**
     * 创建表单
     *
     * @param pid 打印头，默认300
     */
    public void createForm(Integer pid) {
        if (pid == null) {
            pid = 300;
        }
        // 创建表单，分辨率为203，如是300点机器，请改为300;300
        String cmd = "~CREATE;formName;X\r\nSCALE;DOT;" + pid + ";" + pid + "\r\nFONT;SYMSET 'UTF8'\r\n";
        PTXLib.INSTANCE.sendcommand(cmd);
    }

    /**
     * 字体加粗
     *
     * @param bold 是否加粗
     */
    public void setBold(boolean bold) {
        String cmd;
        if (bold) {
            cmd = "FONT;NAME 92244.sf;BOLD 1\r\n";
        } else {
            cmd = "FONT;NAME 92244.sf;BOLD 0\r\n";
        }
        PTXLib.INSTANCE.sendcommand(cmd);

    }

    /**
     * 打印表单
     */
    public void printForm() {
        String cmd = "END\r\n~EXECUTE;formName\r\n~NORMAL\r\n";
        PTXLib.INSTANCE.sendcommand(cmd);
    }

    /**
     * 打印文字
     *
     * @param ptxLabelText 标签打印文字信息
     */
    public void printText(PTXLabelText ptxLabelText) {
        Integer spaceBetween = ptxLabelText.getSpaceBetween();
        Integer x = ptxLabelText.getX();
        Integer y = ptxLabelText.getY();
        // 检查y是否超出边界值
        y = checkY(y, spaceBetween);

        Integer xLineHeight = ptxLabelText.getxLineHeight();
        Integer yLineHeight = ptxLabelText.getyLineHeight();
        String printData = ptxLabelText.getPrintData();

        String tffFileName = ptxLabelText.getTffFileName();
        // 判断是否另外使用字体文件
        if (StrUtil.isBlank(tffFileName)) {
            // 设置默认使用字体文件
            tffFileName = "SIMHEI.TTF";
        }

        printText(x, y, xLineHeight, yLineHeight, printData, tffFileName);
    }

    /**
     * 使用中文字体进行打印
     *
     * @param X x轴坐标
     * @param Y y轴坐标
     * @param VE x轴垂直扩展间距 行高
     * @param he Y轴垂直扩展间距 行高
     * @param data 打印数据
     * @param tffFileName 字体文件名称
     */
    public void printText(Integer X, Integer Y, Integer VE, Integer he, String data, String tffFileName) {
        //使用字体为SIMHEI.TTF来打印中文，如打印内容中包含*，请修改data前后的*，变为内容中不会包含的符号
        String cmd = "FONT;NAME " + tffFileName + "\r\nTWOBYTE\r\nPOINT;"+Y+";"+X+";"+VE+";"+he+";*"+data+"*\r\nSTOP\r\n";

        byte[] data1 = new byte[1024];
        data1=cmd.getBytes(StandardCharsets.UTF_8);
        PTXLib.INSTANCE.sendBinaryDataNoCRLF(data1,data1.length);
    }

    /**
     * 打印英文
     *
     * @param ptxLabelText 标签打印文字信息
     */
    public void printTextEn(PTXLabelText ptxLabelText) {
        Integer spaceBetween = ptxLabelText.getSpaceBetween();
        Integer x = ptxLabelText.getX();
        Integer y = ptxLabelText.getY();
        // 检查y是否超出边界值
        y = checkY(y, spaceBetween);

        Integer xLineHeight = ptxLabelText.getxLineHeight();
        Integer yLineHeight = ptxLabelText.getyLineHeight();
        String printData = ptxLabelText.getPrintData();
        if (StrUtil.isNotBlank(printData)) {
            // 去除中文
            printData = printData.replaceAll("[\\u4e00-\\u9fa5]", "");
        }

        printTextEn(x, y, xLineHeight, yLineHeight, printData);
    }

    /**
     * 使用内部字体打印英文
     *
     * @param X x轴坐标
     * @param Y y轴坐标
     * @param VE x轴垂直扩展间距 行高
     * @param he Y轴垂直扩展间距 行高
     * @param data 打印数据
     */
    public void printTextEn(Integer X, Integer Y, Integer VE, Integer he, String data)
    {
        String cmd = "ALPHA\r\nPOINT;"+Y+";"+X+";"+VE+";"+he+";*"+data+"*\r\nSTOP\r\n"; // 仅可用来打印英文及数字，如打印内容中包含*，请修改data前后的*，变为内容中不会包含的符号
        //PTXLIBDLL.INSTANCE.sendcommand(cmd);

        byte[] data1;
        data1=cmd.getBytes(StandardCharsets.UTF_8);
        PTXLib.INSTANCE.sendBinaryDataNoCRLF(data1,data1.length);
    }

    private Integer checkY(Integer Y, Integer spaceBetween) {
        int i = (spaceBetween / 2) - 5;
        if (Y >= i) {
            return Y;
        }
        return i;
    }

    public void writeRFID(String EPC) {
        String RFID_format = "H"; // 十六进
        String regex="^[A-Fa-f0-9]+$";

        if (StrUtil.isBlank(EPC)) {
            throw new RuntimeException("EPC不能为空");
        }

        // 删除字符串中前导的零
        EPC = EPC.replaceFirst("^0+", "");

        if (EPC.length() % 4 != 0) {
            throw new RuntimeException("EPC的长度必须为4的倍数");
        }

        // 大写英文
        EPC = EPC.toUpperCase();

        if (!EPC.matches(regex)) {
            throw new RuntimeException("EPC格式非16进制");
        }

        String cmd2="RFWTAG;96;EPC\n96;"+ RFID_format +";*"+EPC+"*\nSTOP\n";//向EPC内写入数据指令，其中的96参数为写入数据长度*4

        // 将EPC写入指令发送至打印机，其余PGL指令均可有sendcommand方法发送至打印机内使用
        PTXLib.INSTANCE.sendcommand(cmd2);
    }

    public void printQrCode(PTXLabelCode ptxLabelCode) {
        Integer spaceBetween = ptxLabelCode.getSpaceBetween();
        Integer x = ptxLabelCode.getX();
        Integer y = ptxLabelCode.getY();
        y = checkY(y, spaceBetween);
        Integer width = ptxLabelCode.getWidth();
        String data = ptxLabelCode.getData();
        printQrCode(x, y, width, data);
    }

    /**
     * 打印二维码
     *
     * @param X x轴坐标
     * @param Y y轴坐标
     * @param width 宽度 5等于1厘米
     * @param data 存入的数据
     */
    public void printQrCode(Integer X, Integer Y, Integer width, String data){
        // 打印QRCODE二维码，如打印内容中包含*，请修改data前后的*，变为内容中不会包含的符号
        String cmd = "BARCODE\r\nQRCODE;XD"+width+";"+Y+";"+X+"\r\n*"+data+"*\r\nSTOP\r\n";
        byte[] data1;
        data1=cmd.getBytes(StandardCharsets.UTF_8);
        PTXLib.INSTANCE.sendBinaryDataNoCRLF(data1,data1.length);
    }

    private void printCode128(PTXLabelCode ptxLabelCode) {
        Integer spaceBetween = ptxLabelCode.getSpaceBetween();
        Integer x = ptxLabelCode.getX();
        Integer y = ptxLabelCode.getY();
        y = checkY(y, spaceBetween);
        Integer width = ptxLabelCode.getWidth();
        if (width > MaxPrintWidth) {
            width = MaxPrintWidth;
        }
        String data = ptxLabelCode.getData();

        Boolean isShowText = ptxLabelCode.getIsShowText();
        if (isShowText == null || isShowText) {
            isShowText = true;
        }
        Double height = ptxLabelCode.getHeight();

        if (StrUtil.isNotBlank(data)) {
            // 去除中文
            data = data.replaceAll("[\\u4e00-\\u9fa5]", "");
            if (height < 4) {
                height = 4.0;
            }
        }
        if (StrUtil.isBlank(data)) {
            if (height < 3) {
                height = 3.0;
            }
        }
        if (height >= 99) {
            height = 98.9;
        }

        printCode128(x, y, width, data, isShowText, height);
    }

    /**
     * 打印128一维码
     *
     * @param X x轴坐标
     * @param Y y轴坐标
     * @param width 宽度 最大为4
     * @param data 存入的数据 不支持中文
     * @param isShowText 是否显示文字
     * @param height 条码高度（毫米）
     */
    public void printCode128(Integer X, Integer Y, Integer width, String data, Boolean isShowText, double height) {
        String cmd;
        if(isShowText){
            cmd = "BARCODE\r\nC128A;XRD" + width + ":" + width + ":" + width * 2 + ":" + width * 2 + ":" + width * 3 + ":" + width * 3 + ":" + width * 4 + ":" + width * 4 + ";H" + height + ";" + Y + ";" + X + "\r\n*" + data + "*\r\nPDF\r\nSTOP\r\n";
        }
        else{
            cmd = "BARCODE\r\nC128A;XRD" + width + ":" + width + ":" + width * 2 + ":" + width * 2 + ":" + width * 3 + ":" + width * 3 + ":" + width * 4 + ":" + width * 4 + ";H" + height + ";" + Y + ";" + X + "\r\n*" + data + "*\r\nSTOP\r\n";
        }
        PTXLib.INSTANCE.sendcommand(cmd);

    }
}
