package xn.hxp.utils;

import android.graphics.Bitmap;
import android.util.Log;
import android.widget.Toast;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.caysn.autoreplyprint.AutoReplyPrint;
import com.sun.jna.Pointer;

import xn.hxp.R;
import xn.hxp.ui.PrintBean;

public enum PrintTool {
    INSTANCE;

    private Pointer pointer = Pointer.NULL;
    private AutoReplyPrint.CP_OnPortOpenedEvent_Callback openedEventCallback;
    private AutoReplyPrint.CP_OnPortOpenFailedEvent_Callback openFailedEventCallback;
    private AutoReplyPrint.CP_OnPrinterStatusEvent_Callback statusEventCallback;
    private AutoReplyPrint.CP_OnPrinterReceivedEvent_Callback receivedEventCallback;

    public void print(boolean isGR, boolean isBelong, PrintBean printBean) throws Exception {
        try {
            if (null != openedEventCallback) {
                openedEventCallback = (handle, name, private_data) -> LogUtils.d("打印机打开成功");
                AutoReplyPrint.INSTANCE.CP_Port_AddOnPortOpenedEvent(openedEventCallback, pointer);
            }
            if (null != openFailedEventCallback) {
                openFailedEventCallback = (handle, name, private_data) -> {
                    pointer = AutoReplyPrint.INSTANCE.CP_Port_OpenUsb("VID:0x0FE6,PID:0x811E", 1);
                    LogUtils.d("打开打印机失败");
                };
                AutoReplyPrint.INSTANCE.CP_Port_AddOnPortOpenFailedEvent(openFailedEventCallback, pointer);
            }

            if (null != statusEventCallback) {
                statusEventCallback = (handle, printer_error_status, printer_info_status, private_data) -> {
                    AutoReplyPrint.CP_PrinterStatus status = new AutoReplyPrint.CP_PrinterStatus(printer_error_status, printer_info_status);
                    String error_status_string = String.format(" Printer Error Status: 0x%04X", printer_error_status & 0xffff);
                    if (status.ERROR_OCCURED()) {
                        if (status.ERROR_CUTTER())
                            error_status_string += "[ERROR_CUTTER]";
                        if (status.ERROR_FLASH())
                            error_status_string += "[ERROR_FLASH]";
                        if (status.ERROR_NOPAPER())
                            error_status_string += "[ERROR_NOPAPER]";
                        if (status.ERROR_VOLTAGE())
                            error_status_string += "[ERROR_VOLTAGE]";
                        if (status.ERROR_MARKER())
                            error_status_string += "[ERROR_MARKER]";
                        if (status.ERROR_ENGINE())
                            error_status_string += "[ERROR_MOVEMENT]";
                        if (status.ERROR_OVERHEAT())
                            error_status_string += "[ERROR_OVERHEAT]";
                        if (status.ERROR_COVERUP())
                            error_status_string += "[ERROR_COVERUP]";
                        if (status.ERROR_MOTOR())
                            error_status_string += "[ERROR_MOTOR]";
                    }
                    String info_status_string = String.format(" Printer Info Status: 0x%04X", printer_info_status & 0xffff);
                    if (status.INFO_LABELMODE())
                        info_status_string += "[Label Mode]";
                    if (status.INFO_LABELPAPER())
                        info_status_string += "[Label Paper]";
                    if (status.INFO_PAPERNOFETCH())
                        info_status_string += "[Paper Not Fetch]";
                    LogUtils.d("打印机状态", error_status_string, info_status_string);
                };
                AutoReplyPrint.INSTANCE.CP_Printer_AddOnPrinterStatusEvent(statusEventCallback, pointer);
            }
            if (null != receivedEventCallback) {
                receivedEventCallback = (handle, printer_received_byte_count, private_data) -> LogUtils.d("打印机回传", printer_received_byte_count);
                AutoReplyPrint.INSTANCE.CP_Printer_AddOnPrinterReceivedEvent(receivedEventCallback, pointer);
            }
            // 判断是否打开打印机
            if (AutoReplyPrint.INSTANCE.CP_Port_IsOpened(pointer)) {
                if (isGR) {
                    startPrintGR(isBelong, printBean);
                } else {
                    startPrint(isBelong, printBean);
                }
            } else {
                pointer = AutoReplyPrint.INSTANCE.CP_Port_OpenUsb("VID:0x0FE6,PID:0x811E", 1);
                LogUtils.d("打开打印机", pointer);
                if (isGR) {
                    startPrintGR(isBelong, printBean);
                } else {
                    startPrint(isBelong, printBean);
                }
            }
        } catch (Exception e) {
            LogUtils.d(Log.getStackTraceString(e));
        }
    }

    private void startPrintGR(boolean isBelong, PrintBean printBean) {
        LogUtils.json("打印", printBean);
        Bitmap bitmap = BitmapUtils.generateBarBitmap(isBelong, printBean);

        if (AutoReplyPrint.INSTANCE.CP_Label_BackPaperToPrintPosition(pointer)) {
            LogUtils.d("打印机退纸成功");
            if (AutoReplyPrint.CP_Pos_PrintRasterImageFromData_Helper.PrintRasterImageFromBitmap(pointer,
                    bitmap.getWidth(),
                    bitmap.getHeight(),
                    bitmap,
                    AutoReplyPrint.CP_ImageBinarizationMethod_Thresholding,
                    AutoReplyPrint.CP_ImageCompressionMethod_None
            )) {
                LogUtils.d("打印机打印图片成功");
                if (AutoReplyPrint.INSTANCE.CP_Label_PagePrint(pointer, 1)) {
                    LogUtils.d("打印机文字成功");
                    if (AutoReplyPrint.INSTANCE.CP_Pos_HalfCutPaper(pointer)) {
                        LogUtils.d("打印机切割成功");
                        AudioPlayer.getInstance().play(R.raw.label_to_the_package);
                    } else {
                        ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机切割失败", Toast.LENGTH_LONG).show());
                    }
                } else {
                    ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机文字失败", Toast.LENGTH_LONG).show());
                }
            } else {
                ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机打印图片失败", Toast.LENGTH_LONG).show());
            }
        } else {
            ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机退纸失败", Toast.LENGTH_LONG).show());
        }
    }

    private void startPrint(boolean isBelong, PrintBean printBean) {
        Bitmap bitmap = BitmapUtils.generateBitmap(isBelong, printBean);

        if (AutoReplyPrint.INSTANCE.CP_Label_BackPaperToPrintPosition(pointer)) {
            LogUtils.d("打印机退纸成功");
            if (AutoReplyPrint.CP_Pos_PrintRasterImageFromData_Helper.PrintRasterImageFromBitmap(pointer,
                    bitmap.getWidth(),
                    bitmap.getHeight(),
                    bitmap,
                    AutoReplyPrint.CP_ImageBinarizationMethod_Thresholding,
                    AutoReplyPrint.CP_ImageCompressionMethod_None
            )) {
                LogUtils.d("打印机打印图片成功");
                if (AutoReplyPrint.INSTANCE.CP_Label_PagePrint(pointer, 1)) {
                    LogUtils.d("打印机文字成功");
                    if (AutoReplyPrint.INSTANCE.CP_Pos_HalfCutPaper(pointer)) {
                        LogUtils.d("打印机切割成功");
                        AudioPlayer.getInstance().play(R.raw.label_to_the_package);
                    } else {
                        ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机切割失败", Toast.LENGTH_LONG).show());
                    }
                } else {
                    ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机文字失败", Toast.LENGTH_LONG).show());
                }
            } else {
                ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机打印图片失败", Toast.LENGTH_LONG).show());
            }
        } else {
            ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机退纸失败", Toast.LENGTH_LONG).show());
        }
    }

    public void print(String string) {
        try {
            // 判断是否打开打印机
            if (AutoReplyPrint.INSTANCE.CP_Port_IsOpened(pointer)) {
                startPrint(string);
            } else {
                pointer = AutoReplyPrint.INSTANCE.CP_Port_OpenUsb("VID:0x0FE6,PID:0x811E", 1);
                AutoReplyPrint.INSTANCE.CP_Port_AddOnPortOpenedEvent(new AutoReplyPrint.CP_OnPortOpenedEvent_Callback() {
                    @Override
                    public void CP_OnPortOpenedEvent(Pointer handle, String name, Pointer private_data) {
                        startPrint(string);
                    }
                }, pointer);
                LogUtils.d("打开打印机");
            }
        } catch (Exception e) {
            LogUtils.d(Log.getStackTraceString(e));
        }
    }

    private void startPrint(String string) {
        LogUtils.d("打印机打开成功");
        Bitmap bitmap = BitmapUtils.airBottlePrint(string);
        if (AutoReplyPrint.INSTANCE.CP_Label_BackPaperToPrintPosition(pointer)) {
            LogUtils.d("打印机退纸成功");
            if (AutoReplyPrint.CP_Pos_PrintRasterImageFromData_Helper.PrintRasterImageFromBitmap(pointer,
                    bitmap.getWidth(),
                    bitmap.getHeight(),
                    bitmap,
                    AutoReplyPrint.CP_ImageBinarizationMethod_Thresholding,
                    AutoReplyPrint.CP_ImageCompressionMethod_None
            )) {
                LogUtils.d("打印机打印图片成功");
                if (AutoReplyPrint.INSTANCE.CP_Label_PagePrint(pointer, 1)) {
                    LogUtils.d("打印机文字成功");
                    if (AutoReplyPrint.INSTANCE.CP_Pos_HalfCutPaper(pointer)) {
                        LogUtils.d("打印机切割成功");
                        AudioPlayer.getInstance().play(R.raw.label_to_the_package);
                    } else {
                        ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机切割失败", Toast.LENGTH_LONG).show());
                    }
                } else {
                    ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机文字失败", Toast.LENGTH_LONG).show());
                }
            } else {
                ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机打印图片失败", Toast.LENGTH_LONG).show());
            }
        } else {
            ThreadUtils.runOnUiThread(() -> Toast.makeText(ActivityUtils.getTopActivity(), "打印机退纸失败", Toast.LENGTH_LONG).show());
        }
    }

}
