package opo.com.simplescalessdk;
import android.graphics.Bitmap;
import android.util.Log;


import java.io.ByteArrayOutputStream;


//常用指令
public class ESCUtil {

    public static final byte ESC = 0x1B;// Escape
    public static final byte FS =  0x1C;// Text delimiter
    public static final byte GS =  0x1D;// Group separator
    public static final byte DLE = 0x10;// data link escape
    public static final byte EOT = 0x04;// End of transmission
    public static final byte ENQ = 0x05;// Enquiry character
    public static final byte SP =  0x20;// Spaces
    public static final byte HT =  0x09;// Horizontal list
    public static final byte LF =  0x0A;// Print and wrap (horizontal orientation)
    public static final byte CR =  0x0D;// Home key
    public static final byte FF =  0x0C;// Carriage control (print and return to the standard mode (in page mode))
    public static final byte CAN = 0x18;// Canceled (cancel print data in page mode)

    /**
     * 打印单个二维码 sunmi自定义指令
     * @param code:         二维码数据
     * @param modulesize:   二维码块大小(单位:点, 取值 1 至 16 )
     * @param errorlevel:   二维码纠错等级(0 至 3)
     *                0 -- 纠错级别L ( 7%)
     *                1 -- 纠错级别M (15%)
     *                2 -- 纠错级别Q (25%)
     *                3 -- 纠错级别H (30%)
     */
    public static byte[] getPrintQRCode(String code, int modulesize, int errorlevel){
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        try{
            buffer.write(setQRCodeSize(modulesize));
            buffer.write(setQRCodeErrorLevel(errorlevel));
            buffer.write(getQCodeBytes(code));
            buffer.write(getBytesForPrintQRCode(true));
        }catch(Exception e){
            e.printStackTrace();
        }
        return buffer.toByteArray();
    }

    /**
     * 打印一维 enc128 条形码
     *
     * Code 字符编码集  (A,B,C）
     *
     * data 字符
     *
     * width 1 ~ 6
     *
     * textposition:    0 不打印
     *                  1 条码上方
     *                  2 条码下方
     *                  3 条码上、下方
     */
    public static byte[] getPrint128Code(String Code, String data, int height, int width, int textposition){

        if(width < 1 || width > 6){
            width = 1;
        }
        if(textposition <0 || textposition > 3){
            textposition = 0;
        }
        if(height < 1 || height>255){
            height = 162;
        }
        if (Code != "A" && Code != "B" && Code != "C" ){
            Code = "A";
        }

        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        try{
            buffer.write(new byte[]{0x1D,0x77,(byte)width,0x1D,0x68,(byte)height,0x1D,0x48,(byte)textposition});
            byte[] barcode;
            if (Code == "C"){
                if ( data.length() % 2 != 0) {
                    barcode = byteMerger(hexStr2Bytes(data),new byte[]{0x7b,0x42 ,(byte)data.toCharArray()[data.length() - 1]});
                }else{
                    barcode =  hexStr2Bytes(data);
                }
            }else
            {
                 barcode = data.getBytes("GB18030");
            }
            buffer.write(new byte[]{0x1D,0x6B,(byte)0x49,(byte)(barcode.length + 2),0x7b ,(byte)Code.toCharArray()[0]});
            buffer.write(barcode);
        }catch(Exception e){
            e.printStackTrace();
        }
        return buffer.toByteArray();
    }


    //光栅位图打印
    public static byte[] printBitmap(Bitmap bitmap){
        byte[] bytes1  = new byte[4];
        bytes1[0] = GS;
        bytes1[1] = 0x76;
        bytes1[2] = 0x30;
        bytes1[3] = 0x00;

        byte[] bytes2 = getBytesFromBitMap(bitmap);
        return byteMerger(bytes1, bytes2);
    }

    //光栅位图打印 设置mode
    public static byte[] printBitmap(Bitmap bitmap, int mode){
        byte[] bytes1  = new byte[4];
        bytes1[0] = GS;
        bytes1[1] = 0x76;
        bytes1[2] = 0x30;
        bytes1[3] = (byte) mode;

        byte[] bytes2 = getBytesFromBitMap(bitmap);
        return byteMerger(bytes1, bytes2);
    }

    //光栅位图打印
    public static byte[] printBitmap(byte[] bytes){
        byte[] bytes1  = new byte[4];
        bytes1[0] = GS;
        bytes1[1] = 0x76;
        bytes1[2] = 0x30;
        bytes1[3] = 0x00;

        return byteMerger(bytes1, bytes);
    }

    /**
     * 跳指定行数
     */
    public static byte[] nextLine(int lineNum) {
        byte[] result = new byte[lineNum];
        for (int i = 0; i < lineNum; i++) {
            result[i] = LF;
        }

        return result;
    }

    // ------------------------bold-----------------------------
    /**
     * 字体加粗
     */
    public static byte[] boldOn() {
        byte[] result = new byte[3];
        result[0] = ESC;
        result[1] = 0x45;
        result[2] = 0x01;
        return result;
    }

    /**
     * 取消字体加粗
     */
    public static byte[] boldOff() {
        byte[] result = new byte[3];
        result[0] = ESC;
        result[1] = 0x45;
        result[2] = 0;
        return result;
    }


    // ------------------------Align-----------------------------
    /**
     * 居左
     */
    public static byte[] alignLeft() {
        byte[] result = new byte[3];
        result[0] = ESC;
        result[1] = 97;
        result[2] = 0;
        return result;
    }

    /**
     * 居中对齐
     */
    public static byte[] alignCenter() {
        byte[] result = new byte[3];
        result[0] = ESC;
        result[1] = 97;
        result[2] = 1;
        return result;
    }

    /**
     * 居右
     */
    public static byte[] alignRight() {
        byte[] result = new byte[3];
        result[0] = ESC;
        result[1] = 97;
        result[2] = 2;
        return result;
    }

    //开钱箱
    public static byte[] openCashdrawer(){
        byte[] data = new byte[]{0x1b,0x70,0x00,60, (byte) 255};
        return data;
    }

    ////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////          private                /////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////
    private static byte[] setQRCodeSize(int modulesize){
        //二维码块大小设置指令
        byte[] dtmp = new byte[8];
        dtmp[0] = GS;
        dtmp[1] = 0x28;
        dtmp[2] = 0x6B;
        dtmp[3] = 0x03;
        dtmp[4] = 0x00;
        dtmp[5] = 0x31;
        dtmp[6] = 0x43;
        dtmp[7] = (byte)modulesize;
        return dtmp;
    }

    private static byte[] setQRCodeErrorLevel(int errorlevel){
        //二维码纠错等级设置指令
        byte[] dtmp = new byte[8];
        dtmp[0] = GS;
        dtmp[1] = 0x28;
        dtmp[2] = 0x6B;
        dtmp[3] = 0x03;
        dtmp[4] = 0x00;
        dtmp[5] = 0x31;
        dtmp[6] = 0x45;
        dtmp[7] = (byte)(48+errorlevel);
        return dtmp;
    }


    private static byte[] getBytesForPrintQRCode(boolean single){
        //打印已存入数据的二维码
        byte[] dtmp;
        if(single){     //同一行只打印一个QRCode， 后面加换行
            dtmp = new byte[9];
            dtmp[8] = 0x0A;
        }else{
            dtmp = new byte[8];
        }
        dtmp[0] = 0x1D;
        dtmp[1] = 0x28;
        dtmp[2] = 0x6B;
        dtmp[3] = 0x03;
        dtmp[4] = 0x00;
        dtmp[5] = 0x31;
        dtmp[6] = 0x51;
        dtmp[7] = 0x30;
        return dtmp;
    }

    private static byte[] getQCodeBytes(String code) {
        //二维码存入指令
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        try {
            byte[] d = code.getBytes("GB18030");
            int len = d.length + 3;
            if (len > 7092) len = 7092;
            buffer.write((byte) 0x1D);
            buffer.write((byte) 0x28);
            buffer.write((byte) 0x6B);
            buffer.write((byte) len);
            buffer.write((byte) (len >> 8));
            buffer.write((byte) 0x31);
            buffer.write((byte) 0x50);
            buffer.write((byte) 0x30);
            for (int i = 0; i < d.length && i < len; i++) {
                buffer.write(d[i]);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return buffer.toByteArray();
    }

    /**
     * 将bitmap图转换为头四位有宽高的光栅位图
     */
    private static byte RGB2Gray(int r, int g, int b) {
        return (true ? ((int) (0.29900 * r + 0.58700 * g + 0.11400 * b) > 200)
                : ((int) (0.29900 * r + 0.58700 * g + 0.11400 * b) < 200)) ? (byte) 0 : (byte) 1;
    }
    private static byte[] getBytesFromBitMap(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int bw = (width - 1) / 8 + 1;

        byte[] rv = new byte[height * bw + 4];
        rv[0] = (byte) bw;//xL
        rv[1] = (byte) (bw >> 8);//xH
        rv[2] = (byte) height;
        rv[3] = (byte) (height >> 8);

        int[] pixels = new int[width * height];
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int clr = pixels[width * i + j];
                int red = (clr & 0x00ff0000) >> 16;
                int green = (clr & 0x0000ff00) >> 8;
                int blue = clr & 0x000000ff;
                byte gray = (RGB2Gray(red, green, blue));
                rv[(bw * 8 * i + j) / 8 + 4] = (byte) (rv[(bw * 8 * i + j) / 8 + 4] | (gray << (7 - ((bw * 8 * i + j) % 8))));
            }
        }

        return rv;
    }

    private static byte[] byteMerger(byte[] byte_1, byte[] byte_2) {
        byte[] byte_3 = new byte[byte_1.length + byte_2.length];
        System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
        System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
        return byte_3;
    }

    private static byte[] hexStr2Bytes(String src)
    {
        int m=0,n=0;
        int l= src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++)
        {
            m=i*2+1;
            n=m+1;
            ret[i] = (byte)( Integer.parseInt(src.substring(i*2, m) + src.substring(m,n)) );
        }
        return ret;
    }

    /**
     * 设置字体大小
     */

    public static byte[] setTextSize(int size) {
        byte[] bytes = CMD_FontSize(size).getBytes();
        return bytes;
    }

    // 字体的大小
    // 0:正常大小 1:两倍高 2:两倍宽 3:两倍大小 4:三倍高 5:三倍宽 6:三倍大小
    // 7:四倍高 8:四倍宽 9:四倍大小 10:五倍高 11:五倍宽 12:五倍大小
    private static String CMD_FontSize(int nfontsize) {
        String _cmdstr = "";
        // 设置字体大小
        switch (nfontsize) {
            case -1:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 0).toString();// 29 33
                break;

            case 0:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 0).toString();// 29 33
                break;

            case 1:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 1).toString();
                break;

            case 2:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 16).toString();
                break;

            case 3:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 17).toString();
                break;

            case 4:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 2).toString();
                break;

            case 5:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 32).toString();
                break;

            case 6:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 34).toString();
                break;

            case 7:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 3).toString();
                break;

            case 8:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 48).toString();
                break;

            case 9:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 51).toString();
                break;

            case 10:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 4).toString();
                break;

            case 11:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 64).toString();
                break;

            case 12:
                _cmdstr = new StringBuffer().append((char) 29).append((char) 33)
                        .append((char) 68).toString();
                break;

        }
        return _cmdstr;
    }

}