package com.miya.print;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;

import com.hisense.hs650service.aidl.HS650Api;
import com.miya.print.exception.PrinterException;
import com.miya.print.utils.AccumulateUtils;
import com.miya.print.utils.BitmapUtils;
import com.miya.print.utils.ESCUtil;
import com.miya.print.utils.PrintLogger;

public class HisensePrinter extends BasePrinter {

    final static String TAG = HisensePrinter.class.getSimpleName();

    final static String SERVICE_PACKAGE = "com.hisense.hs650api";
    final static String SERVICE_ACTION = "com.hisense.hs650api";
    /**
     * 波特率
     */
    final static int BAUD_RATE = 115200;
    /**
     * 串口号
     */
    final static int COM = 0;
    /**
     * 58mm打印纸机器
     */
    final static int PRINTER_TYPE_58 = 0;
    /**
     * 80mm打印纸机器
     */
    final static int PRINTER_TYPE_80 = 1;
    /**
     * 打印机类型
     */
    final static int PRINTER_TYPE = PRINTER_TYPE_80;

    HS650Api hs650Api;
    Context context;
    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            hs650Api = HS650Api.Stub.asInterface(service);
            if (hs650Api == null) {
                //连接打印进程服务失败
                PrintLogger.e(TAG, "连接海信打印进程服务失败");
            } else {
                PrintLogger.i(TAG, "连接海信打印进程服务成功");
            }
            try {
                initPrinter();
                PrintLogger.i(TAG, "海信打印机初始化成功");
            } catch (Exception ex) {
                ex.printStackTrace();
                PrintLogger.e(TAG, "海信打印机初始化失败");
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            hs650Api = null;
        }
    };

    @Override
    public boolean init(Context context) {
        PrintLogger.i(TAG, "开始初始化海信打印机");
        this.context = context.getApplicationContext();
        Intent intent = new Intent();
        intent.setPackage(SERVICE_PACKAGE);
//        intent.setAction(SERVICE_ACTION);
//        context.getApplicationContext().startService(intent);
        boolean result = this.context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        if (result == false) {
            PrintLogger.e(TAG, "海信打印机服务连接失败");
        } else {
            PrintLogger.i(TAG, "海信打印机服务连接成功");
        }
        return result;
    }

    @Override
    public boolean release() {
        try {
            hs650Api.getPrinter().closePrinter();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public int beginPrint() {
        AccumulateUtils.clearAccmulateString();
        return PrinterStatusEnum.CODE_SUCCESS.status;
    }

    @Override
    public int endPrint() {
        printAccumulateString();
        AccumulateUtils.clearAccmulateString();
        return PrinterStatusEnum.CODE_SUCCESS.status;
    }

    @Override
    public int printText(int align, int size, String content, boolean isFeed) {
        int ret = setAlign(align);
        //使用累加器进行累加,暂只支持80mm打印纸
        AccumulateUtils.accumulateString(AccumulateUtils.PAGE_MODE_80MM, this.align, size, content, isFeed);
        return ret;
    }

    @Override
    public int printImage(int align, Bitmap bm, boolean isFeed) {
        //先打印之前累积的字符串
        int ret = printAccumulateString();
        //接着打印图片
        ret = setAlign(align);
        Bitmap actualBm = null;
        try {
            if (bm.getWidth() > MAX_IMG_WIDTH_80MM) {
                actualBm = BitmapUtils.scaleBitmap(bm, MAX_IMG_WIDTH_80MM, 0);
                ret = hs650Api.getPrinter().printImage(actualBm, this.align);
            } else {
                ret = hs650Api.getPrinter().printImage(bm, this.align);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, ex.getMessage());
        }
        if (actualBm != null) {
            actualBm.recycle();
        }
        if (ret < 0) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, PrinterStatusEnum.CODE_FAILED.desc);
        }
        return PrinterStatusEnum.CODE_SUCCESS.status;
    }

    @Override
    public int printBarcode(int align, String content, boolean isFeed) {
        //先打印之前累积的字符串
        int ret = printAccumulateString();
        //接着打印一维条码
        ret = setAlign(align);
        try {
            ret = hs650Api.getPrinter().printBar(content);
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
        return PrinterStatusEnum.CODE_SUCCESS.status;
    }

    @Override
    public int printQrcode(int align, String content, boolean isFeed) {
        //先打印之前累积的字符串
        int ret = printAccumulateString();
        //接着打印二维条码
        ret = setAlign(align);
        try {
            //printQR方法第二个参数为放大倍数，取值3～6
            ret = hs650Api.getPrinter().printQR(content, 6);
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
        if (ret < 0) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, PrinterStatusEnum.CODE_FAILED.desc);
        }
        return PrinterStatusEnum.CODE_SUCCESS.status;
    }

    @Override
    public int getPrinterStatus() {
        return super.getPrinterStatus();
    }

    @Override
    public int cutPaper() {
        checkService();
        //先打印之前累积的字符
        printAccumulateString();
        try {
            hs650Api.getPrinter().cutPaper();
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
        return PrinterStatusEnum.CODE_SUCCESS.status;
    }

    @Override
    public int feedPaper() {
        checkService();
        int ret = 0;
        try {
            ret = hs650Api.getPrinter().feedPaper(1, 0);
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
        if (ret < 0) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, PrinterStatusEnum.CODE_FAILED.desc);
        }
        return PrinterStatusEnum.CODE_SUCCESS.status;
    }

    @Override
    public int setAlign(int align) {
        checkService();
        int ret = PrinterStatusEnum.CODE_SUCCESS.getStatus();
        if (this.align != align &&
                (align == 0 || align == 1 || align == 2)) {
            this.align = align;
            try {
                switch (this.align) {
                    case IPrinter.ALIGN_LEFT:
                        ret = hs650Api.getPrinter().printSend(ESCUtil.alignLeft(), ESCUtil.alignLeft().length);
                        break;
                    case IPrinter.ALIGN_CENTER:
                        ret = hs650Api.getPrinter().printSend(ESCUtil.alignCenter(), ESCUtil.alignLeft().length);
                        break;
                    case IPrinter.ALIGN_RIGHT:
                        ret = hs650Api.getPrinter().printSend(ESCUtil.alignRight(), ESCUtil.alignLeft().length);
                        break;
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, ex.getMessage());
            }
        }
        return ret;
    }

    /**
     * 打印累积的字符串
     *
     * @return 状态码或抛出异常
     */
    private int printAccumulateString() {
        String accumulateStr = AccumulateUtils.getAccumulatedString();
        if (!TextUtils.isEmpty(accumulateStr)) {
            checkService();
            int ret = 0;
            try {
                ret = hs650Api.getPrinter().printTextStr(accumulateStr, 0, IPrinter.ALIGN_LEFT);
                //恢复当前排版格式
                ret = hs650Api.getPrinter().printTextStr("", 0, this.align);
            } catch (RemoteException e) {
                e.printStackTrace();
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
            }
            if (ret < 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, PrinterStatusEnum.CODE_FAILED.desc);
            }
        }
        //清空累积值
        AccumulateUtils.clearAccmulateString();
        return PrinterStatusEnum.CODE_SUCCESS.status;
    }

    /**
     * 初始化连接打印机，app起来的时候调用
     */
    @Deprecated
    public void connectPrinterService(Context context) {
        this.context = context.getApplicationContext();
        Intent intent = new Intent();
        intent.setPackage(SERVICE_PACKAGE);
//        intent.setAction(SERVICE_ACTION);
//        this.context.startService(intent);
        this.context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    /**
     * 是否已经连接打印机
     *
     * @return
     */
    @Deprecated
    public boolean isConnected() {
        return hs650Api != null;
    }

    /**
     * 断开服务
     *
     * @param context context
     */
    public void disconnectPrinterService(Context context) {
        if (hs650Api != null) {
            context.getApplicationContext().unbindService(serviceConnection);
            hs650Api = null;
        }
    }

    /**
     * 配置打印者，打印的第一步
     *
     * @param baudrate 波特率
     * @param port     端口
     * @param ctrlOPen RTS/CTS true打开 false关闭
     */
    public void configPrinter(int baudrate, int port, boolean ctrlOPen) {
        checkService();
        try {
            int ret = hs650Api.getPrinter().printerConfig(baudrate, port, ctrlOPen);
            if (ret != 0) {
                new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "配置打印机失败！");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 检查服务是否正常，正常就通过，不正常就抛异常
     */
    public void checkService() {
        if (hs650Api == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
    }

    public void getPrinterType() {

    }

    /**
     * 检查是否缺纸
     *
     * @return true==>有纸；false==>缺纸
     */
    public void checkPaper() {
        checkService();
        try {
            int ret = hs650Api.getPrinter().printStatus();
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "缺纸");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 打印初始化，包括获取打印机型号getPrnType->配置打印机printerConfig->初始化打印机initPrinter
     * 注：本地先写死波特率为115200，串口为2
     */
    public void initPrinter() {
        checkService();
        try {
            long tmp1 = System.currentTimeMillis();
            String printerType = hs650Api.getPrinter().getPrnType(BAUD_RATE, COM, 500);
            long tmp2 = System.currentTimeMillis();
            int ret = hs650Api.getPrinter().printerConfig(BAUD_RATE, COM, false);
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印机配置失败!");
            }
            ret = hs650Api.getPrinter().initPrinter(PRINTER_TYPE);
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印机初始化失败!");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印机异常!");
        }
    }

    /**
     * 打印字符(带换行)
     *
     * @param content 字符内容
     * @param size    字符大小 0==正常大小；1==2倍大小
     * @param align   字符对齐方式 0==居左；1==居中；2==居右
     */
    public void printTextWithLF(String content, int size, int align) {
        checkService();
        checkPaper();
        printText(content, size, align);
        LF();
    }

    /**
     * 打印字符
     *
     * @param content 字符内容
     * @param size    字符大小 0==正常大小；1==2倍大小
     * @param align   字符对齐方式 0==居左；1==居中；2==居右
     */
    @Deprecated
    public void printText(String content, int size, int align) {
        checkService();
        checkPaper();
        try {
            int ret = hs650Api.getPrinter().printTextStr(content, size, align);
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印失败");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印失败");
        }
    }

//    /**
//     * 默认居中 正常大小
//     *
//     * @param content
//     */
//    public void printText(String content) {
//        printText(content, 0, 1);
//    }

    /**
     * 强制打印机走纸一行
     */
    public void LF() {
        checkService();
        checkPaper();
        try {
            int ret = hs650Api.getPrinter().feedPaper(1, 0);
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "换行失败");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "换行失败");
        }
    }

    /**
     * 强制切纸
     */
    @Deprecated
    public void cutPaperOld() {
        checkService();
        try {
            hs650Api.getPrinter().cutPaper();
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "切纸失败");
        }
    }

    /**
     * 打印二维码
     *
     * @param code 二维码内容
     * @param mode 放大倍数（3~6）
     */
    public void printQrCode(String code, int mode) {
        checkService();
        checkPaper();
        try {
            int ret = hs650Api.getPrinter().printQR(code, mode);
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印二维码失败！");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }


    /**
     * 打印图片
     *
     * @param bitmap 指定图片
     * @param mode   mode：0：左对齐1：居中2：右对齐
     */
    public void printBitmap(Bitmap bitmap, int mode) {
        checkService();
        checkPaper();
        try {
            int ret = hs650Api.getPrinter().printImage(bitmap, mode);
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印图片失败！");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 打印一维码
     *
     * @param code 一维码内容
     */
    public void printBarCode(String code) {
        checkService();
        checkPaper();
        try {
            int ret = hs650Api.getPrinter().printBar(code);
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印一维条码失败");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 打印图片
     *
     * @param bitmap
     * @param mode   0==居左；1==居中；2==居右
     */
    public void printImage(Bitmap bitmap, int mode) {
        checkService();
        checkPaper();
        try {
            int ret = hs650Api.getPrinter().printImage(bitmap, mode);
            if (ret != 0) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印图片失败！");
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 关闭打印机
     */
    public void closePrinter() {
        checkService();
        try {
            hs650Api.getPrinter().closePrinter();
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }
}
