package com.joe.print.mvp.print;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;

import com.epson.epos2.Epos2Exception;
import com.epson.epos2.printer.Printer;
import com.epson.epos2.printer.PrinterStatusInfo;
import com.epson.epos2.printer.ReceiveListener;
import com.gingersoft.gsa.cloud.print.PrintExecutor;
import com.gingersoft.gsa.cloud.print.PrintSocketHolder;
import com.joe.print.mvp.model.bean.PrintInfoBean;
import com.joe.print.mvp.print.utils.MyPrintUtils;

import java.util.ArrayList;
import java.util.List;

public class EpsonPrint implements ReceiveListener {

    private final String TAG = this.getClass().getSimpleName();
    private Printer mPrinter = null;

    private ReceiveListener receiveListener;
    private PrintExecutor.OnPrintResultListener resultListener;

    private static EpsonPrint epsonPrint;

    public static EpsonPrint

    getInstance() {
        synchronized (EpsonPrint.class) {
            if (epsonPrint == null) {
                epsonPrint = new EpsonPrint();
            }
        }
        return epsonPrint;
    }

    /**
     * 初始化
     *
     * @return
     */
    public boolean initializeObject(Context context, ReceiveListener receiveListener,PrintExecutor.OnPrintResultListener resultListener) {
        try {
            this.resultListener = resultListener;
            this.receiveListener = receiveListener;
            //第一個參數是機型，第二個參數是語言，
            mPrinter = new Printer(Printer.TM_U220, Printer.MODEL_KOREAN, context);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        mPrinter.setReceiveEventListener(this);
        return true;
    }

    /**
     * 斷開連接
     */
    public void disconnectPrinter() {
        if (mPrinter == null) {
            return;
        }
        while (true) {
            try {
                mPrinter.disconnect();
                break;
            } catch (final Exception e) {
                Log.e(TAG, "斷開連接報錯" + e.getMessage() + e.getClass().getName());
                if (e instanceof Epos2Exception) {
                    //Note: If printer is processing such as printing and so on, the disconnect API returns ERR_PROCESSING.
                    if (((Epos2Exception) e).getErrorStatus() == Epos2Exception.ERR_PROCESSING) {

                    } else {
                        break;
                    }
                } else {
                    break;
                }
            }
        }
    }

    public void finalizeObject() {
        if (mPrinter == null) {
            return;
        }
        mPrinter.clearCommandBuffer();
        mPrinter.setReceiveEventListener(null);
        mPrinter = null;
    }

    /**
     * 創建打印數據
     *
     * @return
     */
    private boolean createPrintData(Bitmap bitmap) {
        try {
            mPrinter.addTextAlign(Printer.ALIGN_CENTER);
            mPrinter.addImage(bitmap, 0, 0,
                    bitmap.getWidth(),
                    bitmap.getHeight(),
                    Printer.COLOR_1,
                    Printer.MODE_MONO_HIGH_DENSITY,//高密度
                    Printer.HALFTONE_DITHER,//半色調抖動
                    Printer.PARAM_DEFAULT,
                    Printer.COMPRESS_NONE);//壓縮
            mPrinter.addCut(Printer.CUT_FEED);
            //COLOR_NONE 為普通顏色 COLOR_2為紅色
//            mPrinter.addTextSize(2, 2);
//            mPrinter.addTextStyle(0,0,1, Printer.COLOR_1);
//            mPrinter.addText("炒爐打印測試\n");
        } catch (Exception e) {
            e.printStackTrace();
            mPrinter.clearCommandBuffer();
            return false;
        }
        return true;
    }

    /**
     * true 打印中
     * false 未打印
     */
    private boolean isPrint = false;
    private String ipAddress;
    private List<Bitmap> bitmaps = new ArrayList<>();

    public void putPrintString(String ip, int paperWidth, List<PrintInfoBean> printInfoBeans) {
        if (mPrinter == null) {
            return;
        }
        connectByIp(ip, mPrinter.getStatus());
        if (mPrinter == null) {
            return;
        }
        mPrinter.clearCommandBuffer();
        try {
            for (PrintInfoBean printInfoBean : printInfoBeans) {
                if (printInfoBean.getGravity() == 0) {
                    mPrinter.addTextAlign(Printer.ALIGN_LEFT);
                }
                if (printInfoBean.getGravity() == 1) {
                    mPrinter.addTextAlign(Printer.ALIGN_CENTER);
                }
                if (printInfoBean.getGravity() == 2) {
                    mPrinter.addTextAlign(Printer.ALIGN_RIGHT);
                }
                //如果打印多列內容，並且字體大小配置多個，則每一列取自己對應的字體大小
                for (int i = 0; i < printInfoBean.getContent().length; i++) {
                    print(printInfoBean, i, paperWidth);
                }
                mPrinter.addFeedLine(1);
            }
            mPrinter.addPulse(Printer.DRAWER_LOW, Printer.PULSE_100);
            mPrinter.addCut(Printer.CUT_FEED);
            mPrinter.sendData(Printer.PARAM_DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
            mPrinter.clearCommandBuffer();
        }
    }

    public void putPrintString(String ip, int paperWidth, List<PrintInfoBean> printInfoBeans, PrintExecutor.OnPrintResultListener printResultListener) {
        if (mPrinter == null) {
            printResultListener.onResult(0, null);
            return;
        }
        connectByIp(ip, mPrinter.getStatus());
        if (mPrinter == null) {
            printResultListener.onResult(0, null);
            return;
        }
        mPrinter.clearCommandBuffer();
        try {
            for (PrintInfoBean printInfoBean : printInfoBeans) {
                if (printInfoBean.getGravity() == 0) {
                    mPrinter.addTextAlign(Printer.ALIGN_LEFT);
                }
                if (printInfoBean.getGravity() == 1) {
                    mPrinter.addTextAlign(Printer.ALIGN_CENTER);
                }
                if (printInfoBean.getGravity() == 2) {
                    mPrinter.addTextAlign(Printer.ALIGN_RIGHT);
                }
                //如果打印多列內容，並且字體大小配置多個，則每一列取自己對應的字體大小
                for (int i = 0; i < printInfoBean.getContent().length; i++) {
                    print(printInfoBean, i, paperWidth);
                }
                mPrinter.addFeedLine(1);
            }
            mPrinter.addCut(Printer.CUT_FEED);
            mPrinter.sendData(Printer.PARAM_DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
            printResultListener.onResult(0, null);
            mPrinter.clearCommandBuffer();
        }
    }

    private int location = 0;

    private void print(PrintInfoBean printInfoBean, int i, int paperWidth) throws Epos2Exception {
        if (i == 0) {
            location = 0;
        }
        int textSize = Double.valueOf(String.valueOf(MyPrintUtils.getContentByLength(printInfoBean.getSize(), i))).intValue();

        //是否傾斜字體
        int isItalic = ((Boolean) MyPrintUtils.getContentByLength(printInfoBean.getIsItalic(), i)) ? 1 : 0;
        int isBold = ((Boolean) MyPrintUtils.getContentByLength(printInfoBean.getIsBold(), i)) ? 1 : 0;
        int color = (int) MyPrintUtils.getContentByLength(printInfoBean.getColor(), i);
        if (color > 4) {
            color = 4;
        }
//        mPrinter.addTextRotate(isItalic);
        //reverse取值0,1沒效果，ul下劃線，em加粗,
        mPrinter.addTextStyle(1, 0, isBold, color);
        setLanguage((String) MyPrintUtils.getContentByLength(printInfoBean.getLanguage(), i));

        StringBuilder space = new StringBuilder();//縮進
        for (int j = 0; j < location / textSize; j++) {
            space.append(" ");
        }
        mPrinter.addTextSize(textSize, textSize);
        location += MyPrintUtils.getChineseValueLength(printInfoBean.getContent()[i]) * printInfoBean.getSize()[0];

        mPrinter.addText(MyPrintUtils.getFormatText(space + printInfoBean.getContent()[i], paperWidth / textSize));
//        mPrinter.addLineSpace(100);//行間距
    }


    private void setLanguage(String language) throws Epos2Exception {
        if ("en".equals(language)) {
            //切換對應語言
            mPrinter.addTextLang(Printer.LANG_EN);//英语
        } else if ("ja".equals(language)) {
            mPrinter.addTextLang(Printer.LANG_JA);//日本
        } else if ("cn".equals(language)) {
            mPrinter.addTextLang(Printer.LANG_ZH_CN);//简体
        } else if ("tw".equals(language)) {
            mPrinter.addTextLang(Printer.LANG_ZH_TW);//台湾
        } else if ("ko".equals(language)) {
            mPrinter.addTextLang(Printer.LANG_KO);//韩语
        } else if ("th".equals(language)) {
            mPrinter.addTextLang(Printer.LANG_TH);//泰国
        } else if ("vi".equals(language)) {
            mPrinter.addTextLang(Printer.LANG_VI);//越南
        } else if ("multi".equals(language)) {
            mPrinter.addTextLang(Printer.LANG_MULTI);//其他
        }
    }

    public void putPrintData(String ip, Bitmap bitmap) {
        //把bitmap存隊列中，下次打印
        bitmaps.add(bitmap);
        if (isPrint) {
            return;
        }
        isPrint = true;
        printData(ip, bitmap);
    }

    //重試次數5次
    private int resetCount = 5;
    private void printData(String ip, Bitmap bitmap) {
        mPrinter.clearCommandBuffer();
        if (!createPrintData(bitmap)) {
            updatePrintState(PrintSocketHolder.ERROR_1);
            return;
        }
        connectByIp(ip, mPrinter.getStatus());
        if (mPrinter == null) {
            updatePrintState(PrintSocketHolder.ERROR_2);
            return;
        }
        PrinterStatusInfo statusInfo = mPrinter.getStatus();
        if (statusInfo.getPaper() == 2) {
            //沒紙了
            updatePrintState(PrintSocketHolder.ERROR_2);
            return;
        } else if(statusInfo.getConnection() != 1){
            //未連接到打印機
            updatePrintState(PrintSocketHolder.ERROR_2);
        }
        try {
            mPrinter.sendData(Printer.PARAM_DEFAULT);
        } catch (Exception e) {
            updatePrintState(PrintSocketHolder.ERROR_4);

            mPrinter.clearCommandBuffer();
            disconnectPrinter();
            isPrint = false;
        }
    }

    private void connectByIp(String ip, PrinterStatusInfo statusInfo) {
        if (statusInfo != null) {
            Log.e(TAG, "連接狀態1111：" + statusInfo.getConnection());
            if (statusInfo.getConnection() != 1) {
                //未連接
                if (connectPrinter(ip)) {
                    ipAddress = ip;
                }
            } else {
                //已連接，判斷這次是否是上次的ip，如果不是，斷開連這個ip
                if (ipAddress != null && !ipAddress.equals(ip)) {
                    Log.e(TAG, "不是上次的ip，斷開重連");
                    disconnectPrinter();
                    if (connectPrinter(ip)) {
                        ipAddress = ip;
                    }
                }
            }
        } else {
            if (connectPrinter(ip)) {
                ipAddress = ip;
            }
        }
        Log.e(TAG, "連接狀態222：" + statusInfo.getConnection());
    }

    private void loginfo(PrinterStatusInfo statusInfo) {
        int connection = statusInfo.getConnection();
        int online = statusInfo.getOnline();
        int coverOpen = statusInfo.getCoverOpen();
        int paper = statusInfo.getPaper();
        int paperFeed = statusInfo.getPaperFeed();
        int panelSwitch = statusInfo.getPanelSwitch();
        int waitOnline = statusInfo.getOnline();
        int drawer = statusInfo.getDrawer();
        int errorStatus = statusInfo.getErrorStatus();
        int autoRecoverError = statusInfo.getAutoRecoverError();
        int buzzer = statusInfo.getBuzzer();
        int adapter = statusInfo.getAdapter();
        int batteryLevel = statusInfo.getBatteryLevel();
        Log.e(TAG, "connection->" + connection + "|online->" + online + "|coverOpen->" + coverOpen + "|paper->" + paper + "|paperFeed->" + paperFeed + "|panelSwitch->" + panelSwitch + "|waitOnline->" + waitOnline + "|drawer->" + drawer + "|errorStatus->" + errorStatus + "|autoRecoverError->" + autoRecoverError + "|buzzer->" + buzzer + "|adapter->" + adapter + "|batteryLevel->" + batteryLevel);
    }

    private boolean connectPrinter(String ip) {
        if (mPrinter == null) {
            return false;
        }
        try {
            mPrinter.connect("TCP:" + ip, Printer.PARAM_DEFAULT);
        } catch (Exception e) {
            Log.e(TAG, "連接打印機報錯" + e.getMessage() + e.getClass().getName());
            e.printStackTrace();
            disconnectPrinter();
            finalizeObject();
            return false;
        }
        return true;
    }

    private void updatePrintState(int code){
        if(resultListener != null){
            resultListener.onResult(code,null);
        }
    }

    public void setPrint(boolean print) {
        isPrint = print;
    }

    @Override
    public void onPtrReceive(Printer printer, int i, PrinterStatusInfo printerStatusInfo, String s) {
        this.mPrinter = printer;
        mPrinter.clearCommandBuffer();
        resetCount = 5;
        if (bitmaps.size() > 0) {
            bitmaps.remove(0);
        }
        if (bitmaps.size() > 0) {
            printData(ipAddress, bitmaps.get(0));
        } else {
            isPrint = false;
            disconnectPrinter();
            finalizeObject();
            if (receiveListener != null) {
                receiveListener.onPtrReceive(printer, i, printerStatusInfo, s);
            }
        }
    }
}
