package com.miya.print;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.IBinder;
import android.os.RemoteException;

import com.miya.print.exception.PrinterException;
import com.miya.print.utils.BitmapUtils;
import com.miya.print.utils.BytesUtil;
import com.miya.print.utils.PrintLogger;
import com.miya.print.utils.ESCUtil;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import woyou.aidlservice.jiuiv5.IWoyouService;

public class SunmiT1Printer extends BasePrinter {

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

    private static final String SERVICE＿PACKAGE = "woyou.aidlservice.jiuiv5";
    private static final String SERVICE＿ACTION = "woyou.aidlservice.jiuiv5.IWoyouService";

    //aidl接口
    private IWoyouService woyouService;

    @Override
    public boolean init(Context context) {
        this.context = context.getApplicationContext();
        Intent intent = new Intent();
        intent.setPackage(SERVICE＿PACKAGE);
        intent.setAction(SERVICE＿ACTION);
        context.getApplicationContext().startService(intent);
        boolean result = context.getApplicationContext().bindService(intent, connService, Context.BIND_AUTO_CREATE);
        if (result == false) {
            PrintLogger.i(TAG, "商米T1打印机初始化失败");
            return false;
        }
        PrintLogger.i(TAG, "商米T1打印机初始化成功");
        return true;
    }

    @Override
    public boolean release() {
        if (this.context != null && connService != null) {
            this.context.unbindService(connService);
        }
        context = null;
        woyouService = null;
        return true;
    }

    @Override
    public int printText(int align, int size, String content, boolean isFeed) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            int ret = setAlign(align);
            woyouService.sendRAWData(ESCUtil.boldOff(), null);
            woyouService.sendRAWData(ESCUtil.underlineOff(), null);
            woyouService.printTextWithFont(content, null, size, null);
            if (isFeed) {
                woyouService.lineWrap(1, null);
            }
            return ret;
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, ex.getMessage());
        }
    }

    @Override
    public int printImage(int align, Bitmap bm, boolean isFeed) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            int ret = setAlign(align);
            //判断bitmap宽高
            Bitmap actualBm = null;
            if (bm.getWidth() > MAX_IMG_WIDTH_80MM) {
                actualBm = BitmapUtils.scaleBitmap(bm, MAX_IMG_WIDTH_80MM, 0);
                woyouService.printBitmap(actualBm, null);
            } else {
                woyouService.printBitmap(bm, null);
            }
            if (actualBm != null) {
                actualBm.recycle();
            }
            woyouService.lineWrap(2, null);
            return ret;
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    @Override
    public int printQrcode(int align, String content, boolean isFeed) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            int ret = setAlign(align);
            woyouService.printQRCode(content, 4, 3, null);
            woyouService.lineWrap(3, null);
            return ret;
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    @Override
    public int printBarcode(int align, String content, boolean isFeed) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            int ret = setAlign(align);
            if (content != null && content.trim().length() <= 12) {
                //该方法最多只能打印12位以内的二维码
                woyouService.printBarCode(content, 8, 148, 2, 2, null);
            } else if (content != null && content.trim().length() > 12 && content.trim().length() % 2 == 0) {
                //该方法只能打印12位以上位数位偶数的条码
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                buffer.write(new byte[]{0x1D, 0x48, (byte) 2,
                        0x1D, 0x77, (byte) 2, 0x1D, 0x68, (byte) 148, 0x0A});

                byte[] barcode;
                barcode = BytesUtil.getBytesFromDecString(content);
                buffer.write(new byte[]{0x1D, 0x6B, 0x49, (byte) (barcode.length + 2), 0x7B, (byte) (0x43)});
                buffer.write(barcode);
                woyouService.sendRAWData(buffer.toByteArray(), null);
            } else if (content != null) {
                //超过12位且长度位奇数的情况，采用打印一维条码图片的形式
                Bitmap barcodeBm = BitmapUtils.createBarcodeBitmap(content, 8, 460, 148);
                if (barcodeBm != null) {
                    ret = printImage(align, barcodeBm, isFeed);
                    barcodeBm.recycle();
                }
            }
            if (isFeed) {
                woyouService.lineWrap(1, null);
            }
            return ret;
        } catch (Exception e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    @Override
    public int cutPaper() {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            woyouService.cutPaper(null);
            return PrinterStatusEnum.CODE_SUCCESS.status;
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

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

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

    @Override
    public int getPrinterStatus() {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            int state = woyouService.updatePrinterState();
            return changeStatus2Custom(status);
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    @Override
    public int feedPaper() {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            woyouService.lineWrap(1, null);
            return PrinterStatusEnum.CODE_SUCCESS.status;
        } catch (RemoteException e) {
            e.printStackTrace();
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    @Override
    public int setAlign(int align) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            int ret = PrinterStatusEnum.CODE_SUCCESS.getStatus();
            if (this.align != align &&
                    (align == 0 || align == 1 || align == 2)) {
                this.align = align;
                woyouService.setAlignment(align, null);
            }
            return changeStatus2Custom(ret);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 将商米的状态码翻译成PrinterStatusEnum中的标准状态码
     * 注：内部会自动抛出不允许的异常状态
     *
     * @param status 商米返回的状态码
     * @return PrinterStatusEnum中的标准状态码
     */
    private int changeStatus2Custom(int status) {
        switch (status) {
            case 0:
                return PrinterStatusEnum.CODE_SUCCESS.status;
            case 1:
                //正常状态
                return PrinterStatusEnum.CODE_SUCCESS.status;
            case 2:
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印机更新状态");
            case 3:
                throw new PrinterException(PrinterStatusEnum.CODE_NO_PAPER.status, "获取状态异常");
            case 4:
                throw new PrinterException(PrinterStatusEnum.CODE_NO_PAPER.status, PrinterStatusEnum.CODE_NO_PAPER.getDesc());
            case 5:
                //打印头过热
                return PrinterStatusEnum.CODE_PRINT_HEAD_HOT.status;
            case 6:
                //开盖
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "打印机开盖");
            case 7:
                throw new PrinterException(PrinterStatusEnum.CODE_KNIFE_ERROR.status, "切刀异常");
            default:
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "获取状态异常");
        }
    }

    /**
     * 连接服务
     *
     * @param context context
     */
    public void connectPrinterService(Context context) {
        this.context = context.getApplicationContext();
        Intent intent = new Intent();
        intent.setPackage(SERVICE＿PACKAGE);
        intent.setAction(SERVICE＿ACTION);
        context.getApplicationContext().startService(intent);
        context.getApplicationContext().bindService(intent, connService, Context.BIND_AUTO_CREATE);
    }

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

    public boolean isConnect() {
        return woyouService != null;
    }

    private ServiceConnection connService = new ServiceConnection() {

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

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            woyouService = IWoyouService.Stub.asInterface(service);
        }
    };

    @Deprecated
    public void LF() {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            woyouService.lineWrap(1, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    @Deprecated
    public void cutPage() {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            woyouService.cutPaper(null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    @Deprecated
    public void setAlignMode(int mode) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            woyouService.setAlignment(mode, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 设置打印浓度
     */
    private int[] darkness = new int[]{0x0600, 0x0500, 0x0400, 0x0300, 0x0200, 0x0100, 0,
            0xffff, 0xfeff, 0xfdff, 0xfcff, 0xfbff, 0xfaff};

    public void setDarkness(int index) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        int k = darkness[index];
        try {
            woyouService.sendRAWData(ESCUtil.setPrinterDarkness(k), null);
            woyouService.printerSelfChecking(null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 取得打印机系统信息，放在list中
     *
     * @return list
     */
    public List<String> getPrinterInfo() {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }

        List<String> info = new ArrayList<>();
        try {
            info.add(woyouService.getPrinterSerialNo());
            info.add(woyouService.getPrinterModal());
            info.add(woyouService.getPrinterVersion());
            info.add(woyouService.getPrintedLength() + "");
            info.add("");
            //info.add(woyouService.getServiceVersion());
            PackageManager packageManager = context.getPackageManager();
            try {
                PackageInfo packageInfo = packageManager.getPackageInfo(SERVICE＿PACKAGE, 0);
                if (packageInfo != null) {
                    info.add(packageInfo.versionName);
                    info.add(packageInfo.versionCode + "");
                } else {
                    info.add("");
                    info.add("");
                }
            } catch (PackageManager.NameNotFoundException e) {
                throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
            }

        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
        return info;
    }

    /**
     * 初始化打印机
     */
    public void initPrinter() {
        if (woyouService == null) {
            return;
        }

        try {
            woyouService.printerInit(null);
        } catch (RemoteException e) {

        }
    }

    /**
     * 打印二维码
     */
    @Deprecated
    public void printQr(String data, int modulesize, int errorlevel) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            woyouService.setAlignment(1, null);
            woyouService.printQRCode(data, modulesize, errorlevel, null);
            woyouService.lineWrap(3, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 打印条形码(不带强制换行的条码打印)
     */
    public void printBarCodeWithNoLF(String data, int symbology, int height, int width, int textposition) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }


        try {
            woyouService.printBarCode(data, symbology, height, width, textposition, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 打印条形码
     */
    public void printBarCode(String data, int symbology, int height, int width, int textposition) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }


        try {
            woyouService.printBarCode(data, symbology, height, width, textposition, null);
            woyouService.lineWrap(3, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }


    /**
     * 打印一维条形码
     * data 条码内容
     * height 条码高度
     * width 条码宽度
     * textposition 条码内容位置
     */
    public void printLongBarCode(String data, int height, int width, int textposition) throws RemoteException, IOException {


        if (width < 2 || width > 6) {
            width = 2;
        }
        if (textposition < 0 || textposition > 3) {
            textposition = 0;
        }
        if (height < 1 || height > 255) {
            height = 162;
        }
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        buffer.write(new byte[]{0x1D, 0x48, (byte) textposition,
                0x1D, 0x77, (byte) width, 0x1D, 0x68, (byte) height, 0x0A});

        byte[] barcode;
        barcode = BytesUtil.getBytesFromDecString(data);
        buffer.write(new byte[]{0x1D, 0x6B, 0x49, (byte) (barcode.length + 2), 0x7B, (byte) (0x43)});
        buffer.write(barcode);


        woyouService.sendRAWData(buffer.toByteArray(), null);
    }

    /**
     * 打印文字
     */
    @Deprecated
    public void printText(String content, float size, boolean isBold, boolean isUnderLine) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }
        try {
            if (isBold) {
                woyouService.sendRAWData(ESCUtil.boldOn(), null);
            } else {
                woyouService.sendRAWData(ESCUtil.boldOff(), null);
            }
            if (isUnderLine) {
                woyouService.sendRAWData(ESCUtil.underlineWithOneDotWidthOn(), null);
            } else {
                woyouService.sendRAWData(ESCUtil.underlineOff(), null);
            }
            woyouService.printTextWithFont(content, null, size, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /*
     *打印图片
     */
    @Deprecated
    public void printBitmap(Bitmap bitmap) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");

        }

        try {
            woyouService.setAlignment(1, null);
            woyouService.printBitmap(bitmap, null);
            woyouService.lineWrap(2, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    /**
     * 打印图片和文字按照指定排列顺序
     */
    public void printBitmap(Bitmap bitmap, int orientation) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }

        try {
            if (orientation == 0) {
                woyouService.printBitmap(bitmap, null);
                woyouService.printText("横向排列\n", null);
                woyouService.printBitmap(bitmap, null);
                woyouService.printText("横向排列\n", null);
            } else {
                woyouService.printBitmap(bitmap, null);
                woyouService.printText("\n纵向排列\n", null);
                woyouService.printBitmap(bitmap, null);
                woyouService.printText("\n纵向排列\n", null);
            }
            woyouService.lineWrap(3, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }


//    /**
//     * 打印表格
//     */
//    public void printTable(LinkedList<TableItem> list) {
//        if (woyouService == null) {
//            Toast.makeText(context,R.string.toast_2,Toast.LENGTH_LONG).show();
//            return;
//        }
//
//        try {
//            for (TableItem tableItem : list) {
//                Log.i("kaltin", "printTable: "+tableItem.getText()[0]+tableItem.getText()[1]+tableItem.getText()[2]);
//                woyouService.printColumnsText(tableItem.getText(), tableItem.getWidth(), tableItem.getAlign(), null);
//            }
//            woyouService.lineWrap(3, null);
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }
//    }

    @Deprecated
    public String updatePrinterState() throws RemoteException {
        if (woyouService == null) {
            return "打印服务已断开!";
        }
        int state = woyouService.updatePrinterState();
        if (state == 1) {
            return "正常";
        }
        if (state == 2) {
            return "打印机更新状态";
        }
        if (state == 3) {
            return "获取状态异常";
        }
        if (state == 4) {
            return "缺纸";
        }
        if (state == 5) {
            return "过热";
        }
        if (state == 6) {
            return "开盖";
        }
        if (state == 7) {
            return "切刀异常";
        }
        return "获取状态异常";
    }


    /*
     * 空打三行！
     */
    public void print3Line() {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }

        try {
            woyouService.lineWrap(3, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }


    public void sendRawData(byte[] data) {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }

        try {
            woyouService.sendRAWData(data, null);
        } catch (RemoteException e) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, e.getMessage());
        }
    }

    //获取当前的打印模式
    public int getPrintMode() {
        if (woyouService == null) {
            throw new PrinterException(PrinterStatusEnum.CODE_FAILED.status, "服务已断开!");
        }

        int res;
        try {
            res = woyouService.getPrinterMode();
        } catch (RemoteException e) {
            e.printStackTrace();
            res = -1;
        }
        return res;
    }
}
