package com.joe.print.mvp.print;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.util.Xml;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.ColorRes;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.epson.epos2.printer.Printer;
import com.epson.epos2.printer.PrinterStatusInfo;
import com.epson.epos2.printer.ReceiveListener;
import com.gingersoft.gsa.cloud.base.adapter.print.BillAdapter;
import com.gingersoft.gsa.cloud.base.adapter.print.BillTypeAdapter;
import com.gingersoft.gsa.cloud.base.adapter.print.FoodAdapter;
import com.gingersoft.gsa.cloud.base.application.GsaCloudApplication;
import com.gingersoft.gsa.cloud.base.common.bean.BillingBean;
import com.gingersoft.gsa.cloud.base.common.bean.OrderDetail;
import com.gingersoft.gsa.cloud.base.common.bean.PayMethod;
import com.gingersoft.gsa.cloud.base.threadPool.ThreadPoolManager;
import com.gingersoft.gsa.cloud.base.utils.AidlUtil;
import com.gingersoft.gsa.cloud.base.utils.RestaurantExpandInfoUtils;
import com.gingersoft.gsa.cloud.base.utils.okhttpUtils.OkHttp3Utils;
import com.gingersoft.gsa.cloud.base.utils.other.TextUtil;
import com.gingersoft.gsa.cloud.base.utils.time.TimeUtils;
import com.gingersoft.gsa.cloud.base.utils.view.ImageUtils;
import com.gingersoft.gsa.cloud.base.utils.view.LayoutToBitmapUtils;
import com.gingersoft.gsa.cloud.base.utils.view.QRCodeUtil;
import com.gingersoft.gsa.cloud.bean.WiseposBean;
import com.gingersoft.gsa.cloud.constans.ExpandConstant;
import com.gingersoft.gsa.cloud.constans.PrintConstans;
import com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean;
import com.gingersoft.gsa.cloud.print.PrintExecutor;
import com.gingersoft.gsa.cloud.print.PrintSocketHolder;
import com.gingersoft.gsa.cloud.print.PrinterWriter58mm;
import com.gingersoft.gsa.cloud.print.bean.OrderDetails;
import com.google.zxing.WriterException;
import com.hyweb.n5.lib.constant.PrinterConstant;
import com.hyweb.n5.lib.util.PrinterUtil;
import com.hyweb.n5.server.aidl.IOnPrintCallback;
import com.joe.print.R;
import com.joe.print.mvp.model.bean.PrintBillBean;
import com.joe.print.mvp.print.common.PrinterFinderCallback;
import com.joe.print.mvp.print.common.SendResultCode;
import com.joe.print.mvp.print.usb.EscCommand;
import com.joe.print.mvp.print.usb.UsbPrint;
import com.joe.print.mvp.print.usb.UsbPrinter;
import com.joe.print.mvp.print.usb.UsbPrinterFinder;
import com.joe.print.mvp.ui.adapter.BillItemAdapter;
import com.sunmi.peripheral.printer.InnerResultCallbcak;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

public abstract class PrinterRoot implements PrintSocketHolder.OnStateChangedListener, PrintExecutor.OnPrintResultListener, ReceiveListener {


    protected final String MONETARY_UNIT = "$";
    private final static int SUNMI_PAPER_WIDTH = 360;//商米打印機紙張寬度
    private final static int N5_PAPER_WIDTH = 500;//N5打印機紙張寬度

    final static String DELIMITER = "/";//將打印位置區分開來。。。。，暫時只有廚房單用到

    private PrintListener printListener;

    public static PrinterRoot getPrinterByType(int type) {
        //初始化USB打印
        if (type == PrintConstans.PRINT_TEST) {
            return new PrintTest();
        } else if (type == PrintConstans.PRINT_SERVE) {
            return new PrintServe();
        } else if (type == PrintConstans.PRINT_SLIP) {
            return new PrintSlip();
        } else if (type == PrintConstans.PRINT_BILL) {
            return new PrintBill();
        } else if (type == PrintConstans.PRINT_KITCHEN) {
            return new PrintPrjKitchen();
        } else if (type == PrintConstans.PRINT_CLEAN_MACHINE) {
            return new PrintCleanMachine();
        } else if (type == PrintConstans.PRINT_OTHER_ORDER) {
            return new PrintOtherOrder();
        } else if (type == PrintConstans.PRINT_INSTRUCTION) {
            return new PrintInstruction();
        } else if (type == PrintConstans.PRINT_OTHER_CLOSING) {
            return new PrintOtherOrderClosing();
        }
        return null;
    }

    public PrinterRoot setPrintListener(PrintListener printListener) {
        this.printListener = printListener;
        return this;
    }

    /**
     * 把Map中Key相同，则各个value添加到一起，汇总值
     * 把partMap数据合并放到resultMap中。
     *
     * @param resultMap
     */
    public static <T, F, K extends Collection<F>> Map merge2ResultMap(Map<T, K> resultMap, T key2, K value) {
        for (Map.Entry<T, K> entry : resultMap.entrySet()) {
            T key = entry.getKey();
            if (resultMap.containsKey(key2)) {
                Objects.requireNonNull(resultMap.get(key2)).addAll(value);
            } else {
                resultMap.put(key2, value);
            }
        }
        if (resultMap.size() == 0) {
            resultMap.put(key2, value);
        }
        return resultMap;
    }

    /**
     * 獲取打印數據，根據打印次數
     *
     * @param mContext
     * @param deviceBean
     * @return
     */
    public Map<String, List<Bitmap>> getPrintBitmapByCount(Context mContext, PrinterDeviceBean deviceBean) {
        int printCount = getPrintCount(mContext);
        if (printCount <= 0) {
            return null;
        }
        Map<String, List<Bitmap>> printBitmap = getPrintBitmap(mContext, deviceBean);
        List<Bitmap> bitmapList = printBitmap.get("");
        if (bitmapList != null) {
            int bitmapSize = bitmapList.size();
            for (int i = 0; i < printCount - 1; i++) {
                for (int j = 0; j < bitmapSize; j++) {
                    bitmapList.add(bitmapList.get(j));
                }
            }
            printBitmap.put("", bitmapList);
        }
        return printBitmap;
    }

    /**
     * @param mContext
     * @return key為打印位置，值為圖片集合的map
     */
    public abstract Map<String, List<Bitmap>> getPrintBitmap(Context mContext, PrinterDeviceBean deviceBean);

    /**
     * 獲取打印次數
     *
     * @param context
     * @return
     */
    public abstract int getPrintCount(Context context);

    /**
     * 本機打印
     */
    public void locationPrint(List<Bitmap> bitmaps, PrintListener listener) {
        //本機打印
        String model = Build.MODEL;
        if (PrintConstans.PRINT_MODEL_V2.contains(model)) {
            sunmiPrint(bitmaps, listener);
        } else if (PrintConstans.PRINT_MODEL_N5.contains(model)) {
            //N5打印
            n5Print(bitmaps, listener);
        } else if (PrintConstans.PRINT_MODEL_WISEPOS.contains(model)) {
            //BBPOS Wisepos 打印 localhost 192.168.1.162
            OkHttp3Utils.get("http://localhost:8080/pos?transactionType=PRINT&isExternal=true&apiVersion=21&printData=<html><body><H2>BBPOS test print</H2></body></html>").subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(String s) {
                    Log.e("eee", "打印內容：" + s);
                    XmlPullParser xmlPullParser = Xml.newPullParser();
                    WiseposBean wiseposBean = new WiseposBean();
                    try {
                        xmlPullParser.setInput(new ByteArrayInputStream(s.getBytes()), "utf-8");
                        int eventType = xmlPullParser.getEventType();
                        while (eventType != XmlPullParser.END_DOCUMENT) {
                            switch (eventType) {
                                case XmlPullParser.START_DOCUMENT:
                                    //開始解析
                                    break;
                                case XmlPullParser.START_TAG:
                                    //解析到某一個節點
                                    String xmlName = xmlPullParser.getName();
                                    switch (xmlName) {
                                        case "status":
                                            wiseposBean.setState(xmlPullParser.nextText());
//                                            if (wiseposBean.getState().equals("SUCCESS")) {
//                                                listener.printSuccess();
//                                            } else {
//                                                listener.printFile("打印失敗");
//                                            }
                                            break;
                                        case "ErrorMessage":
                                            if (xmlPullParser.nextText().equals("Please login first")) {
                                                listener.printFile("請先登錄WisePay");
                                            }
                                            break;
                                        case "requestType":
                                            wiseposBean.setRequestType(xmlPullParser.nextText());
                                            break;
                                    }
                                    break;
                                case XmlPullParser.END_TAG:
                                    //這個節點解析完成
                                    if (wiseposBean.getState() != null && wiseposBean.getState().equals("SUCCESS")) {
                                        listener.printSuccess();
                                    } else {
                                        listener.printFile("打印失敗");
                                    }
                                    break;
                            }
                            eventType = xmlPullParser.next();
                        }
                    } catch (XmlPullParserException | IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    if (e instanceof ConnectException) {
                        listener.printFile("無法連接打印，請檢查WisePay是否打開");
                    }
                    Log.e("eee", "報錯信息：" + e.getMessage());
                }

                @Override
                public void onComplete() {
                    Log.e("eee", "完成");

                }
            });
        } else {
            listener.printFile("暫不支持本機型打印");
        }
    }

    /**
     * n5打印
     *
     * @param bitmaps
     * @param listener
     */
    private void n5Print(List<Bitmap> bitmaps, PrintListener listener) {
        try {
            for (int i = 0; i < bitmaps.size(); i++) {
                PrinterUtil.appendImage(ImageUtils.zoomDrawable(bitmaps.get(i), N5_PAPER_WIDTH), PrinterConstant.ALIGN_CENTER);
                PrinterUtil.appendPrnStr("\n", 24, PrinterConstant.ALIGN_CENTER, false);
                PrinterUtil.appendPrnStr("\n", 24, PrinterConstant.ALIGN_CENTER, false);
            }
            startN5Print(listener);
        } catch (RemoteException e) {
            e.printStackTrace();
            listener.printFile("打印失敗，請重試");

        }
    }

    /**
     * 商米打印
     *
     * @param bitmaps
     * @param listener
     */
    private void sunmiPrint(List<Bitmap> bitmaps, PrintListener listener) {
        //商米打印
        AidlUtil.getInstance().printBitmaps(bitmaps, SUNMI_PAPER_WIDTH, new InnerResultCallbcak() {
            @Override
            public void onRunResult(boolean isSuccess) {
                //返回接⼝执⾏的情况(并⾮真实打印):成功或失败
                if (isSuccess) {
                    listener.printSuccess();
                } else {
                    listener.printFile("打印失敗");
                }
            }

            @Override
            public void onReturnString(String result) {
                //部分接⼝会异步返回查询数据
            }

            @Override
            public void onRaiseException(int code, String msg) {
                //接⼝执⾏失败时，返回的异常状态
            }

            @Override
            public void onPrintResult(int code, String msg) {
                //事务模式下真实的打印结果返回
            }
        });
    }


    private void startN5Print(PrintListener listener) {
        try {
            PrinterUtil.startPrint(true, new IOnPrintCallback.Stub() {
                @Override
                public void onPrintResult(int i) {
                    if (i == 0) {
                        //打印成功
                        listener.printSuccess();
                    } else {
                        //打印失敗
                        listener.printFile("打印失敗");
                    }
                }

                @Override
                public IBinder asBinder() {
                    return this;
                }
            });
        } catch (RemoteException e) {
            e.printStackTrace();
            //打印失敗
            listener.printFile("打印失敗");
        }
    }

    public void ipDevicePrint(PrinterDeviceBean printerDeviceBean, List<Bitmap> bitmaps) {
        ipDevicePrint(printerDeviceBean, bitmaps, this, this);
    }


    private EpsonPrint mPrinter;
    private PrintExecutor executor;

    /**
     * ip設備打印
     */
    public void ipDevicePrint(PrinterDeviceBean
                                      printerDeviceBean, List<Bitmap> bitmaps, PrintSocketHolder.OnStateChangedListener
                                      stateChangedListener, PrintExecutor.OnPrintResultListener resultListener) {
        //獲取打印機機型，如果是EPSON的打印機，調用EPSON的打印方法
        if ((printerDeviceBean.getPrinterName() != null && printerDeviceBean.getPrinterName().toLowerCase().contains("EPSON".toLowerCase()))
                && (printerDeviceBean.getModel() != null && printerDeviceBean.getModel().toLowerCase().contains("TM-U220B".toLowerCase()))) {
            ThreadPoolManager.getInstence().putExecutableTasks(() -> {
                        mPrinter = EpsonPrint.getInstance();
                        mPrinter.setPrint(false);
                        mPrinter.initializeObject(GsaCloudApplication.getAppContext(), PrinterRoot.this, PrinterRoot.this);
                        for (int j = 0; j < bitmaps.size(); j++) {
                            mPrinter.putPrintData(printerDeviceBean.getIp(), bitmaps.get(j));
                        }
                    }
            );
        } else {
            if (executor == null) {
                executor = new PrintExecutor(printerDeviceBean);
                executor.setOnStateChangedListener(stateChangedListener);
                executor.setOnPrintResultListener(resultListener);
            }
            IpPrintMaker maker = new IpPrintMaker(480, bitmaps);
            executor.doPrinterRequestAsync(maker);
        }
    }

    public void usbPrint(Context context, List<Bitmap> bitmaps) {
        UsbPrint usbPrint = new UsbPrint(context, (code, printId) -> {
            //打印結果
            if (code == SendResultCode.SEND_SUCCESS) {
                printSuccess();
            } else if (code == SendResultCode.SEND_FAILED) {
                printFile("打印失敗");
            }
        });
        UsbPrinterFinder printerFinder = new UsbPrinterFinder(context, new PrinterFinderCallback<UsbPrinter>() {
            @Override
            public void onStart() {

            }

            @Override
            public void onFound(UsbPrinter usbPrinter) {

            }

            @Override
            public void onFinished(List<UsbPrinter> usbPrinters) {
                if (usbPrinters != null && usbPrinters.size() > 0) {
                    for (Bitmap bitmap : bitmaps) {
                        EscCommand esc = new EscCommand();
                        ArrayList<byte[]> bytes = new ArrayList<>();
                        try {
                            bytes.addAll(new PrinterWriter58mm().getImageByte(bitmap));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        bytes.add(esc.getPrintAndFeedLines((byte) 8));
                        bytes.add(esc.getCutPaper());
                        bytes.add(esc.getCleanCache());
                        if (usbPrinters.size() > 0)
                            usbPrint.sendPrintCommand(usbPrinters.get(0), bytes);
                    }
                } else {
                    boolean hasPermission = new Intent().getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
                    printListener.printFile("未找到USB打印機");
                }
            }
        });
        printerFinder.startFinder();
    }

    /**
     * view轉bitmap
     *
     * @param context
     * @param view
     * @return
     */
    final Bitmap viewToBitmap(Context context, View view) {
        LayoutToBitmapUtils.layoutView(context, view);//先测量view
        //轉為bitmap
        return LayoutToBitmapUtils.loadBitmapFromView(view);
    }

    final Bitmap viewToZoomBitmap(Context context, View view, PrinterDeviceBean printerDeviceBean) {
        LayoutToBitmapUtils.layoutView(context, view);//先测量view
        //轉為bitmap
        return zoomBitmap(printerDeviceBean, LayoutToBitmapUtils.loadBitmapFromView(view));
    }

    public Bitmap zoomBitmap(PrinterDeviceBean printerDeviceBean, Bitmap bitmap) {
        int printWidth;
        if (printerDeviceBean != null && printerDeviceBean.getPaperSpecification() != null) {
            printWidth = Double.valueOf(printerDeviceBean.getPaperSpecification()).intValue();
        } else {
            //如果打印機沒設置寬度
            printWidth = 480;
        }
        return ImageUtils.zoomDrawable(bitmap, printWidth);
    }


    @Override
    public void onResult(int errorCode, PrinterDeviceBean printerDeviceBean) {
        switch (errorCode) {
            case PrintSocketHolder.ERROR_0:
                Log.e("eee", "打印成功");
                printSuccess();
                break;
            case PrintSocketHolder.ERROR_1:
                Log.e("eee", "生成測試頁面數據失敗");
                printFile("生成打印數據失敗");
                break;
            case PrintSocketHolder.ERROR_2:
                Log.e("eee", "連接打印機失敗");
                printFile("連接打印機失敗");
                break;
            case PrintSocketHolder.ERROR_3:
                Log.e("eee", "獲取輸出流失敗");
                printFile("連接打印機失敗");
                break;
            case PrintSocketHolder.ERROR_4:
                Log.e("eee", "寫入測試頁面數據失敗");
                printFile("連接打印機失敗");
                break;
            case PrintSocketHolder.ERROR_5:
                Log.e("eee", "必要的參數不能為空");
                printFile("連接打印機失敗");
                break;
        }
        setPrintState(errorCode);
    }

    private void printSuccess() {
        if (printListener != null) {
            printListener.printSuccess();
        }
    }

    private void printFile(String state) {
        if (printListener != null) {
            printListener.printFile(state);
        }
    }

    @Override
    public void onStateChanged(int state, PrinterDeviceBean printerDeviceBean) {
        setPrintState(state);
    }

    private void setPrintState(int state) {
        if (printListener != null) {
            printListener.printStateChanged(state);
        }
    }

    @Override
    public void onPtrReceive(Printer printer, int i, PrinterStatusInfo printerStatusInfo, String s) {
        Log.e("eee", "EPSON打印結果：" + i);
        if (printListener != null) {
            if (i == 0) {
                printSuccess();
            } else {
                printFile("打印失敗");
            }
        }
//        EpsonPrint.getInstance().disconnectPrinter();
//        EpsonPrint.getInstance().finalizeObject();
    }


    public View getLine(Context mContext) {
        TextView textView = new TextView(mContext);
        textView.setMaxLines(1);
        textView.setText(mContext.getString(R.string.print_split_line));
        return textView;
    }

    /**
     * 獲取中間是文字的線條
     *
     * @param content 文字內容
     */
    public View getTextLine(Context mContext, String content) {
        View view = View.inflate(mContext, R.layout.print_model_text_line, null);
        TextView textView = view.findViewById(R.id.print_model_center_text);
        textView.setText(content);
        return view;
    }

    public View getHalfLine(Context mContext) {
        return View.inflate(mContext, R.layout.print_model_half_line, null);
    }


    public View getHeader(Context mContext) {
        View view = View.inflate(mContext, R.layout.print_model_header, null);
        TextView tvBrandName = view.findViewById(R.id.print_brand_name);
        TextView tvRestaurantName = view.findViewById(R.id.print_restaurant_name);
        tvBrandName.setText(GsaCloudApplication.getBrandName());
        tvRestaurantName.setText(GsaCloudApplication.getRestaurantName());
        return view;
    }

    public View getTakeawayOrderInfo(Context mContext, OrderDetails.DataBean data) {
        View view = View.inflate(mContext, R.layout.print_model_takeaway_order_info, null);
        // 訂單類型
        TextView tvOrderType = view.findViewById(R.id.print_model_center_text);
        TextView tvPayType = view.findViewById(R.id.tv_print_model_pay_type);
        TextView tvDeliveryTime = view.findViewById(R.id.tv_print_model_delivery_time);
        TextView tvBillNumber = view.findViewById(R.id.tv_print_model_bill_number);
        TextView tvOrderNumber = view.findViewById(R.id.tv_print_model_order_number);
        TextView tvTakeFoodCode = view.findViewById(R.id.tv_print_model_order_take_food_code);
        TextView tvCreateTime = view.findViewById(R.id.tv_print_model_order_create_time);
        TextView tvClosingTime = view.findViewById(R.id.tv_print_model_order_closing_time);
        TextView tvRemark = view.findViewById(R.id.tv_print_model_remark);
        //訂單類型
        tvOrderType.setText(data.getOrder_type() == 2 ? "外送" : "自取");
        String payType = "";
        tvClosingTime.setVisibility(View.GONE);
        if (data.getOrderPayType() == 1) {
            //貨到付款
            payType = "貨到付款";
        } else if (data.getOrderPayType() == 0) {
            payType = "店內支付";
        } else if (data.getOrderPayType() == 2) {
            if (data.getPayMultiple() != null) {
                StringBuilder payName = new StringBuilder();
                for (OrderDetails.DataBean.PayMultiple payMultiple : data.getPayMultiple()) {
                    payName.append(payMultiple.getPayName());
                    payName.append(",");
                }
                if (payName.length() > 0) {
                    payName.deleteCharAt(payName.length() - 1);
                }
                payType = "在線支付：" + payName.toString();
            } else {
                payType = "在線支付";
            }
            //支付時間，只有在線支付有
            if (!TextUtil.isEmptyOrNullOrUndefined(data.getPayTime())) {
                tvClosingTime.setText("支付時間：" + data.getPayTime());
                tvClosingTime.setVisibility(View.VISIBLE);
            }
        }
        //支付類型
        tvPayType.setText(payType);
        //送達時間
        tvDeliveryTime.setText(data.getOrder_type() == 2 ? data.getSEND_TIME() : data.getTakeTime());
        if (TextUtil.isEmptyOrNullOrUndefined(tvDeliveryTime.getText().toString())) {
            tvDeliveryTime.setVisibility(View.GONE);
        }
        tvBillNumber.setText("單號：" + data.getORDER_NO());

        if (TextUtil.isEmptyOrNullOrUndefined(data.getBillNo())) {
            tvOrderNumber.setVisibility(View.GONE);
        } else {
            tvOrderNumber.setText("訂單碼：" + data.getBillNo());
        }

        //取餐碼
        if (data.getOrder_type() == 7) {
            //自取  顯示 取餐碼+訂單碼
            if (!TextUtil.isEmptyOrNullOrUndefined(data.getTakeFoodCode())) {
                tvTakeFoodCode.setText("取餐碼：" + data.getTakeFoodCode());
            }
        } else {
            //外送  顯示訂單碼
            tvTakeFoodCode.setText("訂單碼：" + data.getTakeFoodCode());
        }
        if (data.getTakeFoodCode() == null || data.getTakeFoodCode().equals("0")) {
            tvTakeFoodCode.setVisibility(View.GONE);
        }

        tvCreateTime.setText("開單時間：" + TimeUtils.parseTimeRepeat(data.getCREATE_TIME(), TimeUtils.DEFAULT_DATE_FORMAT));

        //備註
        if (!TextUtil.isEmptyOrNullOrUndefined(data.getRemark())) {
            tvRemark.setText("備註：" + data.getRemark());
            tvRemark.setVisibility(View.VISIBLE);
        } else {
            tvRemark.setVisibility(View.GONE);
        }
        return view;
    }

    protected View getTableMealMemberIntegerView(Context mContext, OrderDetails.DataBean data, String integralQrcode) {
        View view = View.inflate(mContext, R.layout.print_model_meal_member_integer_info, null);
        LinearLayout ll_member_info = view.findViewById(R.id.ll_member_info);
        TextView tvMemberNum = view.findViewById(R.id.tv_print_model_member_number);//會員號碼
        TextView tvMemberName = view.findViewById(R.id.tv_print_model_member_name);//會員名稱
        TextView tvMemberPhone = view.findViewById(R.id.tv_print_model_member_phone);//會員電話
        TextView tvNowPoint = view.findViewById(R.id.tv_print_model_nowPoints);//現在的積分
        TextView tvAddPoints = view.findViewById(R.id.tv_print_model_addPoints);//本次添加積分
        TextView tvOldPoints = view.findViewById(R.id.tv_print_model_oldPoints);//之前的積分

        LinearLayout llIntegralQrcode = view.findViewById(R.id.ll_integral_qrcode);
        ImageView ivIntegralQrcode = view.findViewById(R.id.iv_integral_qrcode);

        if (data.getAddPoints() != 0 || data.getOldPoints() != 0 || data.getAddPoints() != 0) {
            tvAddPoints.setText("本次積分：" + data.getAddPoints());
            tvNowPoint.setText("結餘積分：" + data.getNowPoints());
            tvOldPoints.setText("上次積分：" + data.getOldPoints());
            //名稱中間替換為*號
            if (data.getMEMBER_NAME() != null && data.getMEMBER_NAME().length() > 0) {
                tvMemberName.setText("會員名稱：" + getReplaceAfter(data.getMEMBER_NAME()));
            }
            if (data.getPHONE() != null && data.getPHONE().length() > 0) {
                tvMemberPhone.setText("會員電話：" + getReplaceAfter(data.getPHONE()));
            }
            ll_member_info.setVisibility(View.VISIBLE);
        } else {
            ll_member_info.setVisibility(View.GONE);
        }
        //生成積分QRCode碼（飯糰APP掃碼獲得積分）
        if (TextUtils.isEmpty(integralQrcode)) {
            llIntegralQrcode.setVisibility(View.GONE);
        } else {
            llIntegralQrcode.setVisibility(View.VISIBLE);
            try {
                Bitmap QRImage = QRCodeUtil.makeQRImage(integralQrcode, 180, 180);
                ivIntegralQrcode.setImageBitmap(QRImage);
            } catch (WriterException e) {
                e.printStackTrace();
            }
        }
        return view;
    }

    protected View getTakeawayMemberIntegerView(Context mContext, OrderDetails.DataBean data) {
        View view = View.inflate(mContext, R.layout.print_model_takeaway_member_integer_info, null);

        if (RestaurantExpandInfoUtils.getValue(ExpandConstant.PrintMemberInfo, false)) {
            TextView tvMemberNum = view.findViewById(R.id.tv_print_model_member_number);//會員號碼
            TextView tvMemberName = view.findViewById(R.id.tv_print_model_member_name);//會員名稱
            TextView tvMemberPhone = view.findViewById(R.id.tv_print_model_member_phone);//會員電話
            TextView tvNowPoint = view.findViewById(R.id.tv_print_model_nowPoints);//現在的積分
            TextView tvAddPoints = view.findViewById(R.id.tv_print_model_addPoints);//本次添加積分
            TextView tvOldPoints = view.findViewById(R.id.tv_print_model_oldPoints);//之前的積分

            if (data.getAddPoints() != 0 || data.getOldPoints() != 0 || data.getAddPoints() != 0) {
                tvAddPoints.setText("本次積分：" + data.getAddPoints());
                tvNowPoint.setText("結餘積分：" + data.getNowPoints());
                tvOldPoints.setText("上次積分：" + data.getOldPoints());
                //名稱中間替換為*號
                if (data.getMEMBER_NAME() != null && data.getMEMBER_NAME().length() > 0) {
                    tvMemberName.setText("會員名稱：" + getReplaceAfter(data.getMEMBER_NAME()));
                }
                if (data.getPHONE() != null && data.getPHONE().length() > 0) {
                    tvMemberPhone.setText("會員電話：" + getReplaceAfter(data.getPHONE()));
                }
            } else {
                view.setVisibility(View.GONE);
            }
        } else {
            view.setVisibility(View.GONE);
        }
        return view;
    }

    private String getReplaceAfter(String str) {
        if (str != null && str.length() > 0) {
            int replaceStrCount = str.length() / 2;
            StringBuilder buffer = new StringBuilder();
            if (replaceStrCount >= 5) {
                replaceStrCount = str.length() - 5;
            }
            for (int i = 0; i < replaceStrCount; i++) {
                buffer.append("*");
            }
            String header = str.substring(0, 1);
            String tail = str.substring(replaceStrCount + 1);
            return header + buffer.toString() + tail;
        }
        return "";
    }

    protected View getTakeawayLargeAmount(Context mContext, String title, String amount) {
        View view = View.inflate(mContext, R.layout.print_model_takeaway_total_amount, null);
        TextView tvTitle = view.findViewById(R.id.tv_total_text);
        TextView tvAmount = view.findViewById(R.id.tv_total);
        tvTitle.setText(title);
        tvAmount.setText(amount);
        return view;
    }

    protected View getTakeawayBillInfoView(Context mContext, List<PrintBillBean> data) {
        return getVerticalRecyclerView(mContext, new BillItemAdapter(data));
    }

    protected void addTakeawayPayViews(Context mContext, ViewGroup parent, List<OrderDetails.DataBean.PayMultiple> payMultiples, double payAmount) {
        if (payMultiples != null && payMultiples.size() > 0) {
            for (OrderDetails.DataBean.PayMultiple payMultiple : payMultiples) {
                if (!TextUtil.isEmptyOrNullOrUndefined(payMultiple.getPayName())) {
                    parent.addView(getTakeawayLargeAmount(mContext, payMultiple.getPayName(), MONETARY_UNIT + payMultiple.getAmount()));
                }
            }
            parent.addView(getLine(mContext));
        }
        //支付金額
        parent.addView(getTakeawayLargeAmount(mContext, "支付金額：", MONETARY_UNIT + payAmount));
        parent.addView(getLine(mContext));
    }

    protected View getTakeawayMemberInfoView(Context mContext, String address, String receiver, String phone) {
        LinearLayout layout = new LinearLayout(mContext);
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.topMargin = getDimensionPixelSize(mContext, R.dimen.dp_5);
        if (!TextUtil.isEmptyOrNullOrUndefined(address)) {
            View addressView = getTakeawayTextView(mContext, address);
            addressView.setLayoutParams(layoutParams);
            layout.addView(addressView);
        }
        if (!TextUtil.isEmptyOrNullOrUndefined(receiver)) {
            View receiverView = getTakeawayTextView(mContext, receiver);
            receiverView.setLayoutParams(layoutParams);
            layout.addView(receiverView);
        }
        if (!TextUtil.isEmptyOrNullOrUndefined(phone)) {
            View phoneView = getTakeawayTextView(mContext, phone);
            phoneView.setLayoutParams(layoutParams);
            layout.addView(phoneView);
        }
        return layout;
    }

    protected void getTakeawayReceiver(Context mContext, OrderDetails.DataBean data, LinearLayout layout) {
        String address = "";
        String receiver = "";
        if (data.getOrder_type() == 2) {
            //收貨地址
            address = "地址：" + data.getAddressDetail();
            //收貨人
            receiver = "收貨人：" + data.getRECEIVER();
        }
        if (!TextUtil.isEmptyOrNullOrUndefined(address)) {
            layout.addView(getTakeawayTextView(mContext, address));
        }
        if (!TextUtil.isEmptyOrNullOrUndefined(receiver)) {
            layout.addView(getTakeawayTextView(mContext, receiver));
        }

        layout.addView(getTakeawayTextView(mContext, "手機號：" + data.getPHONE()));
    }

    protected View getTakeawayTextView(Context mContext, String text) {
        return getTextView(mContext, text, Gravity.LEFT, 26, getColor(mContext, R.color.black));
    }


    public View getDiningTableOrderInfo(Context mContext, String diningTable, String people, String orderNum, String createTime) {
        View view = View.inflate(mContext, R.layout.print_model_dining_table_order_info, null);
        TextView tvDiningTable = view.findViewById(R.id.tv_print_model_dining_table);
        TextView tvPeople = view.findViewById(R.id.tv_print_model_people);
        TextView tvOrderNum = view.findViewById(R.id.tv_print_model_order_number);
        TextView tvCreateTime = view.findViewById(R.id.tv_print_model_data);
        tvDiningTable.setVisibility(diningTable == null ? View.GONE : View.VISIBLE);
        tvPeople.setVisibility(people == null ? View.GONE : View.VISIBLE);
        tvOrderNum.setVisibility(orderNum == null ? View.GONE : View.VISIBLE);
        tvCreateTime.setVisibility(createTime == null ? View.GONE : View.VISIBLE);

        tvDiningTable.setText(diningTable);
        tvPeople.setText(people);
        tvOrderNum.setText(orderNum);
        tvCreateTime.setText(createTime);
        return view;
    }

    /**
     * @param mContext
     * @param foodList
     * @param deviceBean
     * @param type       0 食品清單，1 結賬單
     * @param showPrice  是否顯示價格
     * @return
     */
    public View getDiningFoodList(Context mContext, List<OrderDetail> foodList, PrinterDeviceBean deviceBean, int type, boolean showPrice) {
//        List<OrderDetail> newsFoodList = new ArrayList<>();
//        for (OrderDetail orderDetail : foodList) {
//            //如果食品設置了0元不打印並且食品等於0元，或者設置了不打印到單，就不打印
//            if (!(orderDetail.getPrintToBill() == 0 && orderDetail.getPrice() == 0)
//                    || OrderDetail.isPrint((int) orderDetail.getPrintTo(), type)) {
//                newsFoodList.add(orderDetail);
//            }
//        }
        return getVerticalRecyclerView(mContext, new FoodAdapter(foodList, deviceBean, showPrice));
    }


    public View getDiningBillInfo(Context mContext, List<BillingBean> billingBeans) {
        return getVerticalRecyclerView(mContext, new BillAdapter(billingBeans));

    }

    public View getDiningBillPayMethod(Context mContext, List<PayMethod> payBillMoneys) {
        return getVerticalRecyclerView(mContext, new BillTypeAdapter(payBillMoneys));
    }

    public View getVerticalRecyclerView(Context mContext, RecyclerView.Adapter adapter) {
        RecyclerView recyclerView = new RecyclerView(mContext);
        recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
        recyclerView.setAdapter(adapter);
        return recyclerView;

    }

    public View getAmountText(Context mContext, String text) {
        return getTextView(mContext, text, Gravity.RIGHT, 24, ContextCompat.getColor(mContext, R.color.black));
    }

    public TextView getTextView(Context mContext, String text, int gravity, float textSize) {
        TextView textView = new TextView(mContext);
        textView.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
        textView.setText(text);
        textView.setTextColor(Color.BLACK);
        textView.setTextSize(textSize);
        textView.setGravity(gravity);
        return textView;
    }

    public TextView getTextView(Context mContext, String text, int gravity, float textSize, int textColor) {
        TextView textView = new TextView(mContext);
        textView.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
        textView.setText(text);
        textView.setTextColor(textColor);
        textView.setTextSize(textSize);
        textView.setGravity(gravity);
        return textView;
    }

    public int getDimensionPixelSize(Context mContext, int textSizeId) {
        return mContext.getResources().getDimensionPixelSize(textSizeId);
    }

    public int getColor(Context mContext, @ColorRes int colorId) {
        return ContextCompat.getColor(mContext, colorId);
    }


    public void setText(View parentView, int viewId, String text) {
        ((TextView) parentView.findViewById(viewId)).setText(text);
    }

    public void setIsShow(View parentView, int viewId, boolean isShow) {
        parentView.findViewById(viewId).setVisibility(isShow ? View.VISIBLE : View.GONE);
    }
}
