package com.kozen.printerhelper.helper;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import com.kozen.printerhelper.R;
import com.kozen.printerhelper.activity.ActivitySettings;
import com.kozen.printerhelper.utils.ESCUtil;
import com.kozen.printerlibrary.InnerPrinterException;
import com.kozen.printerlibrary.PrinterConsts;
import com.xcheng.printerservice.IPrinterCallback;
import com.xcheng.printerservice.IPrinterService;
import com.kozen.printerlibrary.InnerPrinterCallback;
import com.kozen.printerlibrary.InnerPrinterManager;
import com.kozen.printerlibrary.InnerResultCallback;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class KozenPrintHelper {
    private static final String TAG = "KozenPrintHelper";

    public static int NoKozenPrinter = 0x00000000;
    public static int CheckKozenPrinter = 0x00000001;
    public static int FoundKozenPrinter = 0x00000002;
    public static int LostKozenPrinter = 0x00000003;
    public static int TYPEFACE_NOMAL = 0;
    public static int TYPEFACE_BOLD = 1;
    public static int UNDERLINE_ENABLE = 1;
    public static int UNDERLINE_DISABLE = 0;
    public static int ALIGN_LEFT = 0;
    public static int ALIGN_CENTER = 1;
    public static int ATTRIBUTES_NULL = -1;
    /**
     *  kozenPrinter means checking the printer connection status
     */
    public static int kozenPrinter = CheckKozenPrinter;
    /**
     *  IPrinterService for API
     */
    public static IPrinterService mIPrinterService;

    private static KozenPrintHelper helper = new KozenPrintHelper();

    public KozenPrintHelper() { }

    public static KozenPrintHelper getInstance() {
        return helper;
    }

    private InnerPrinterCallback innerPrinterCallback = new InnerPrinterCallback() {
        @Override
        protected void onConnected(IPrinterService service) {
            mIPrinterService = service;
            checkIPrinterService(service);
        }

        @Override
        protected void onDisconnected() {
            mIPrinterService = null;
            kozenPrinter = LostKozenPrinter;
        }
    };

    private static IPrinterCallback mCallback = new IPrinterCallback.Stub() {
        @Override
        public void onException(int code, final String msg) throws RemoteException {
            Log.i(TAG, "onException code = " + code + " msg = " + msg);
        }

        @Override
        public void onLength(long current, long total) throws RemoteException {
            Log.i(TAG, "onLength current = " + current + " total = " + total);
            //new add for display speed start
            setCurrentEndPrintTime(current, total);
            //new add for display speed end
        }

        @Override
        public void onComplete() throws RemoteException {
            Log.i(TAG,"onComplete");
        }
        /*
		@Override
		public void onStart() throws RemoteException {
			// TODO Auto-generated method stub
			LogUtils.i(TAG,"onStart");
			//new add for display speed start
			setCurrentStartPrintTime();
			//new add for display speed end
		}
		*/
    };

    /**
     * init kozen print service
     */
    public void initIPrinterService(Context context){
        try {
            boolean ret =  InnerPrinterManager.getInstance().bindService(context, innerPrinterCallback);
            if(!ret){
                kozenPrinter = NoKozenPrinter;
            }
        } catch (InnerPrinterException e) {
            e.printStackTrace();
        }
    }

    /**
     *  deInit kozen print service
     */
    public void deInitIPrinterService(Context context){
        try {
            if(mIPrinterService != null){
                InnerPrinterManager.getInstance().unBindService(context, innerPrinterCallback);
                mIPrinterService = null;
                kozenPrinter = LostKozenPrinter;
            }
        } catch (InnerPrinterException e) {
            e.printStackTrace();
        }
    }

    /**
     * Check the printer connection,
     * like some devices do not have a printer but need to be connected to the cash drawer through a print service
     */
    public static void checkIPrinterService(IPrinterService service){
        boolean ret = false;
        ret = hasPrinter(service);
        kozenPrinter = ret?FoundKozenPrinter:NoKozenPrinter;
    }

    private static boolean hasPrinter(IPrinterService service){
        if(service == null){
            return false;
        }
        try {
            boolean status = mIPrinterService.printerPaper(mCallback);
            return status;
        } catch (RemoteException e) {
            if(Build.SERIAL.toUpperCase(Locale.ENGLISH).contains("V1")){
                return true;
            }else{
                return false;
            }
        }
    }

    private void handleRemoteException(RemoteException e){
        //TODO process when get one exception
    }

    /**
     * send esc cmd
     */
    public void sendRawData(byte[] data) {
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }
        try {
            mIPrinterService.sendRAWData(data, mCallback);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    public void setPrintEncode(String encode){
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }
        try {
            mIPrinterService.setPrintEncode(encode, mCallback);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     *  Printer cuts paper and throws exception on machines without a cutter
     */
    public void cutpaper(Context context){
        try {
            if(ActivitySettings.doCheckIsCutPaperSupport(context)){
                mIPrinterService.sendRAWData(ESCUtil.FeedPaperCutPartial(), mCallback);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     *  Initialize the printer
     *  All style settings will be restored to default
     */
    public void initPrinter(){
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }
        try {
            mIPrinterService.printerInit(mCallback);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Set printer alignment
     */
    public void setAlign(int align){
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }
        try {
            mIPrinterService.setAlignment(align, mCallback);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    public void feedPaper(){
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }

        try {
            mIPrinterService.printWrapPaper(3, mCallback);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * Get printer serial number
     */
    public String getPrinterSerialNo(){
//        if(mIPrinterService == null){
        //TODO Service disconnection processing
        return "";
//        }
//        try {
//            return mIPrinterService.getPrinterSerialNo();
//        } catch (RemoteException e) {
//            handleRemoteException(e);
//            return "";
//        }
    }

    /**
     * Get device model
     */
    public String getDeviceModel(){
//        if(mIPrinterService == null){
        //TODO Service disconnection processing
        return "";
//        }
//        try {
//            return mIPrinterService.getPrinterModal();
//        } catch (RemoteException e) {
//            handleRemoteException(e);
//            return "";
//        }
    }

    /**
     * Get firmware version
     */
    public String getPrinterVersion(){
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return "";
        }
        try {
            return mIPrinterService.getFirmwareVersion();
        } catch (RemoteException e) {
            handleRemoteException(e);
            return "";
        }
    }

    /**
     * Get paper specifications
     */
    public String getPrinterPaper(){
//        if(mIPrinterService == null){
        //TODO Service disconnection processing
        return "";
//        }
//        try {
//            return mIPrinterService.getPrinterPaper() == 1?"58mm":"80mm";
//        } catch (RemoteException e) {
//            handleRemoteException(e);
//            return "";
//        }
    }

    /**
     * Get paper specifications
     */
    public void getPrinterHead(InnerResultCallback callbcak){
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return;
//        }
//        try {
//             mIPrinterService.getPrinterFactory(callbcak);
//        } catch (RemoteException e) {
//            handleRemoteException(e);
//        }
    }

    /**
     * Get printing distance since boot
     * Get printing distance through interface callback since 1.0.8(printerlibrary)
     */
    public void getPrinterDistance(InnerResultCallback callback){
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return;
//        }
//        try {
//            mIPrinterService.getPrintedLength(callback);
//        } catch (RemoteException e) {
//            handleRemoteException(e);
//        }
    }

    /**
     * print text
     * setPrinterStyle Api require V4.2.22 or later, So use esc cmd instead when not supported
     *  More settings reference documentation {@link PrinterConsts}
     */
    public void printText(String content, int size, boolean isBold, boolean isUnderLine) {
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }

        try {
            final Map<String,Integer> maptext = new HashMap<String,Integer>();
            maptext.put(PrinterConsts.KEY_TEXTSIZE, size);
            maptext.put(PrinterConsts.KEY_ALIGN, ALIGN_LEFT);
            maptext.put(PrinterConsts.KEY_TYPEFACE, isBold ? TYPEFACE_BOLD : TYPEFACE_NOMAL);
            maptext.put(PrinterConsts.KEY_UNDERLINE, isUnderLine ? UNDERLINE_ENABLE : UNDERLINE_DISABLE);

            mIPrinterService.printTextWithAttributes(content, maptext, mCallback);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

    /**
     * print Bar Code
     */
    public void  printBarCode(String data, int width, int height, int contentPos, int format) {
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }

        try {
            mIPrinterService.printBarCodeWithPos(data, ALIGN_LEFT, width, height, contentPos, format, mCallback);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     * print Qr Code
     */
    public void printQr(String data, int size, int error) {
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }

        try {
            mIPrinterService.printQRCodeWithErr(data, ALIGN_LEFT, size, error, mCallback);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     * Print a row of a table
     */
    public void printTable(String[] text, int[] weight, int[] align) {
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }

        try {
            final List<Map<String, Integer>> attributes = new ArrayList<Map<String,Integer>>();
            int length = 3;
            final int[] linespace = new int[]{10, 10, 10};
            final int[] size = new int[]{24, 24, 24};
            final int[] attDefault = new int[]{0, 0, 0};
            for(int i = 0; i < length; i++){
                final Map<String,Integer> attrColsMap = new HashMap<String,Integer>();
                attrColsMap.put(PrinterConsts.KEY_LINESPACE, linespace[i]);
                attrColsMap.put(PrinterConsts.KEY_TEXTSIZE, size[i]);
                attrColsMap.put(PrinterConsts.KEY_TYPEFACE, attDefault[i]);
                attrColsMap.put(PrinterConsts.KEY_ALIGN, align[i]);
                attrColsMap.put(PrinterConsts.KEY_MARGINLEFT, attDefault[i]);
                attrColsMap.put(PrinterConsts.KEY_MARGINRIGHT, attDefault[i]);
                attrColsMap.put(PrinterConsts.KEY_WEIGHT, weight[i]);
                attributes.add(attrColsMap);
            }
            mIPrinterService.printColumnsTextWithAttributes(text, attributes, mCallback);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     *  Print pictures and text in the specified orde
     *  After the picture is printed,
     *  the line feed output needs to be called,
     *  otherwise it will be saved in the cache
     *  In this example, the image will be printed because the print text content is added
     */
    public void printBitmap(Bitmap bitmap, int orientation) {
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }

        try {
            if(orientation == 0){
                mIPrinterService.printBitmap(bitmap, mCallback);
                mIPrinterService.printText("横向排列", mCallback);
                mIPrinterService.printBitmap(bitmap, mCallback);
                mIPrinterService.printText("横向排列\n", mCallback);
            }else{
                mIPrinterService.printBitmap(bitmap, mCallback);
                mIPrinterService.printText("纵向排列", mCallback);
                mIPrinterService.printBitmap(bitmap, mCallback);
                mIPrinterService.printText("纵向排列", mCallback);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     * Gets whether the current printer is in black mark mode
     */
    public boolean isBlackLabelMode(){
//        if(mIPrinterService == null){
        //TODO Service disconnection processing
        return false;
//        }
//        try {
//            return mIPrinterService.getPrinterMode() == 1;
//        } catch (RemoteException e) {
//            return false;
//        }
    }

    /**
     * Gets whether the current printer is in label-printing mode
     */
    public boolean isLabelMode(){
//        if(mIPrinterService == null){
        //TODO Service disconnection processing
        return false;
//        }
//        try {
//            return mIPrinterService.getPrinterMode() == 2;
//        } catch (RemoteException e) {
//            return false;
//        }
    }

    /**
     *  Transaction printing:
     *  enter->print->exit(get result) or
     *  enter->first print->commit(get result)->twice print->commit(get result)->exit(don't care
     *  result)
     */
    public void printTrans(Context context, InnerResultCallback callbcak){
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return;
//        }
//
//        try {
//            mIPrinterService.enterPrinterBuffer(true);
//            printExample(context);
//            mIPrinterService.exitPrinterBufferWithCallback(true, callbcak);
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }
    }

    private final static byte[] mOpenCashBox = new byte[] {0x1b,0x70,0x00};
    public void openCashBox(){
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return;
        }

        try {
//            mIPrinterService.openDrawer(mCallback);
            mIPrinterService.sendRAWData(mOpenCashBox, mCallback);
        } catch (RemoteException e) {
            handleRemoteException(e);
        }
    }

    /**
     * LCD screen control
     * @param flag 1 —— Initialization
     *             2 —— Light up screen
     *             3 —— Extinguish screen
     *             4 —— Clear screen contents
     */
    public void controlLcd(int flag){
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return;
//        }
//
//        try {
//            mIPrinterService.sendLCDCommand(flag);
//        } catch (RemoteException e) {
//            handleRemoteException(e);
//        }
    }

    /**
     * Display text SUNMI,font size is 16 and format is fill
     * sendLCDFillString(txt, size, fill, callback)
     * Since the screen pixel height is 40, the font should not exceed 40
     */
    public void sendTextToLcd(){
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return;
//        }
//
//        try {
//            mIPrinterService.sendLCDFillString("SUNMI", 16, true, new InnerLcdCallback() {
//                @Override
//                public void onRunResult(boolean show) throws RemoteException {
//                    //TODO handle result
//                }
//            });
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }

    }

    /**
     * Display two lines and one empty line in the middle
     */
    public void sendTextsToLcd(){
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return;
//        }
//
//        try {
//            String[] texts = {"SUNMI", null, "SUNMI"};
//            int[] align = {2, 1, 2};
//            mIPrinterService.sendLCDMultiString(texts, align, new InnerLcdCallback() {
//                @Override
//                public void onRunResult(boolean show) throws RemoteException {
//                    //TODO handle result
//                }
//            });
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }

    }

    /**
     * Display one 128x40 pixels and opaque picture
     */
    public void sendPicToLcd(Bitmap pic){
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return;
//        }
//
//        try {
//            mIPrinterService.sendLCDBitmap(pic, new InnerLcdCallback() {
//                @Override
//                public void onRunResult(boolean show) throws RemoteException {
//                    //TODO handle result
//                }
//            });
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }

    }

    /**
     *  Sample print receipt
     */
    public void printExample(Context context){
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return ;
        }

        try {
//            int paper = mIPrinterService.getPrinterPaper();
            int paper = 1;
            mIPrinterService.printerInit(mCallback);
            mIPrinterService.setAlignment(ALIGN_CENTER, mCallback);
            mIPrinterService.printText("测试样张", mCallback);
            Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.image);
            mIPrinterService.printBitmap(bitmap, mCallback);
//            mIPrinterService.printWrapPaper(1, mCallback);
            mIPrinterService.setAlignment(ALIGN_LEFT, mCallback);
            try {
                mIPrinterService.setPrinterStyle(PrinterConsts.KEY_LINESPACE, 0, mCallback);
            } catch (RemoteException e) {
                mIPrinterService.sendRAWData(new byte[]{0x1B, 0x33, 0x00}, mCallback);
            }
            mIPrinterService.printTextWithFont("说明：这是一个自定义的小票样式例子,开发者可以仿照此进行自己的构建\n",
                    0, 20, mCallback);
            if(paper == 1){
                mIPrinterService.printText("--------------------------------\n", mCallback);
            }else{
                mIPrinterService.printText("------------------------------------------------\n",
                        mCallback);
            }
            try {
                mIPrinterService.setPrinterStyle(PrinterConsts.KEY_TYPEFACE, TYPEFACE_BOLD, mCallback);
//                mIPrinterService.setPrinterStyle(PrinterConsts.ENABLE_BOLD, PrinterConsts.ENABLE);
            } catch (RemoteException e) {
                mIPrinterService.sendRAWData(ESCUtil.boldOn(), mCallback);
            }
            String txts[] = new String[]{"商品", "价格"};
            int width[] = new int[]{1, 1};
            int align[] = new int[]{0, 2};
            mIPrinterService.printColumnsString(txts, width, align, mCallback);
            try {
                mIPrinterService.setPrinterStyle(PrinterConsts.KEY_TYPEFACE, TYPEFACE_NOMAL, mCallback);
            } catch (RemoteException e) {
                mIPrinterService.sendRAWData(ESCUtil.boldOff(), mCallback);
            }
            if(paper == 1){
                mIPrinterService.printText("--------------------------------\n", mCallback);
            }else{
                mIPrinterService.printText("------------------------------------------------\n",
                        mCallback);
            }
            txts[0] = "汉堡";
            txts[1] = "17¥";
            mIPrinterService.printColumnsString(txts, width, align, mCallback);
            txts[0] = "可乐";
            txts[1] = "10¥";
            mIPrinterService.printColumnsString(txts, width, align, mCallback);
            txts[0] = "薯条";
            txts[1] = "11¥";
            mIPrinterService.printColumnsString(txts, width, align, mCallback);
            txts[0] = "炸鸡";
            txts[1] = "11¥";
            mIPrinterService.printColumnsString(txts, width, align, mCallback);
            txts[0] = "圣代";
            txts[1] = "10¥";
            mIPrinterService.printColumnsString(txts, width, align, mCallback);
            if(paper == 1){
                mIPrinterService.printText("--------------------------------\n", mCallback);
            }else{
                mIPrinterService.printText("------------------------------------------------\n",
                        mCallback);
            }
            mIPrinterService.printTextWithFont("总计:          59¥\b", 0, 40, mCallback);
            mIPrinterService.setAlignment(ALIGN_CENTER, mCallback);
            mIPrinterService.printQRCodeWithErr("谢谢惠顾", ATTRIBUTES_NULL, 3, 3, mCallback);
            mIPrinterService.printWrapPaper(1, mCallback);
            mIPrinterService.setFontSize(36, mCallback);
            mIPrinterService.printText("谢谢惠顾", mCallback);
            mIPrinterService.printWrapPaper(3, mCallback);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     * Used to report the real-time query status of the printer, which can be used before each
     * printing
     */
    public void showPrinterStatus(Context context){
        if(mIPrinterService == null){
            //TODO Service disconnection processing
            return ;
        }
        String result = "Interface is too low to implement interface";
        try {
            int res = mIPrinterService.updatePrinterState(mCallback);
            switch (res){
                case 1:
                    result = "printer is running";
                    break;
                case 2:
                    result = "printer found but still initializing";
                    break;
                case 3:
                    result = "printer hardware interface is abnormal and needs to be reprinted";
                    break;
                case 4:
                    result = "printer is out of paper";
                    break;
                case 5:
                    result = "printer is overheating";
                    break;
                case 6:
                    result = "printer's cover is not closed";
                    break;
                case 7:
                    result = "printer's cutter is abnormal";
                    break;
                case 8:
                    result = "printer's cutter is normal";
                    break;
                case 9:
                    result = "not found black mark paper";
                    break;
                case 505:
                    result = "printer does not exist";
                    break;
                default:
                    break;
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        Toast.makeText(context, result, Toast.LENGTH_LONG).show();
    }

    /**
     * Demo printing a label
     * After printing one label, in order to facilitate the user to tear the paper, call
     * labelOutput to push the label paper out of the paper hatch
     * 演示打印一张标签
     * 打印单张标签后为了方便用户撕纸可调用labelOutput,将标签纸推出纸舱口
     */
    public void printOneLabel() {
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return ;
//        }
//        try {
//            mIPrinterService.labelLocate();
//            printLabelContent();
//            mIPrinterService.labelOutput();
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }
    }

    /**
     * Demo printing multi label
     *
     After printing multiple labels, choose whether to push the label paper to the paper hatch according to the needs
     * 演示打印多张标签
     * 打印多张标签后根据需求选择是否推出标签纸到纸舱口
     */
    public void printMultiLabel(int num) {
//        if(mIPrinterService == null){
//            //TODO Service disconnection processing
//            return ;
//        }
//        try {
//            for(int i = 0; i < num; i++){
//                mIPrinterService.labelLocate();
//                printLabelContent();
//            }
//            mIPrinterService.labelOutput();
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }
    }

    /**
     *
     *  Custom label ticket content
     *  In the example, not all labels can be applied. In actual use, please pay attention to adapting the size of the label. You can adjust the font size and content position.
     *  自定义的标签小票内容
     *  例子中并不能适用所有标签纸，实际使用时注意要自适配标签纸大小，可通过调节字体大小，内容位置等方式
     */
    private void printLabelContent() throws RemoteException {
//        mIPrinterService.setPrinterStyle(PrinterConsts.ENABLE_BOLD, PrinterConsts.ENABLE);
//        mIPrinterService.lineWrap(1, mCallback);
//        mIPrinterService.setAlignment(0, mCallback);
//        mIPrinterService.printText("商品         豆浆\n", mCallback);
//        mIPrinterService.printText("到期时间         12-13  14时\n", mCallback);
//        mIPrinterService.printBarCode("{C1234567890123456",  8, 90, 2, 2, mCallback);
//        mIPrinterService.lineWrap(1, mCallback);
    }

    //new add for display speed start
    private static boolean startRecordTime		= false;
    private static long startPrintTime			= 0;
    private static long endPrintTime			= 0;
    private static long currentTotalLength		= 0;
    private static long totalPrintLength		= 0;
    public void setStartRecordFlag(){
        startRecordTime = true;
    }
    public long getCurrentStartPrintTime(){
        return startPrintTime;
    }
    public void setCurrentStartPrintTime(){
        if(startRecordTime){
            startPrintTime = System.currentTimeMillis();
        }
    }
    public long getCurrentEndPrintTime(){
        return endPrintTime;
    }
    public static void setCurrentEndPrintTime(long current, long total){
        if(startRecordTime){
            if(current == total){
                currentTotalLength = 0;
            }
            endPrintTime = System.currentTimeMillis();
            totalPrintLength = total - currentTotalLength;
            currentTotalLength = total;
            startRecordTime = false;
        }
    }
    public long getCurrentTotalLength(){
        return totalPrintLength;
    }
    //new add for display speed end
}
