import {NativeModules} from 'react-native';
import axios from 'axios';
import moment from 'moment';
import {Buffer} from 'buffer';

const {Printer: _Printer} = NativeModules;

let Printer = null;
if (_Printer) {
  const Command = {
    INIT_PRINTER: 0,
    WAKE_PRINTER: 1,
    PRINT_AND_RETURN_STANDARD: 2,
    PRINT_AND_NEWLINE: 3,
    PRINT_AND_ENTER: 4,
    MOVE_NEXT_TAB_POSITION: 5,
    DEF_LINE_SPACING: 6,
    PRINT_AND_WAKE_PAPER_BY_LNCH: 0,
    PRINT_AND_WAKE_PAPER_BY_LINE: 1,
    CLOCKWISE_ROTATE_90: 4,
    ALIGN: 13,
    ALIGN_LEFT: 0,
    ALIGN_CENTER: 1,
    ALIGN_RIGHT: 2,
    LINE_HEIGHT: 10,
    CHARACTER_RIGHT_MARGIN: 11,
    UNDERLINE: 15,
    UNDERLINE_OFF: 16,
    UNDERLINE_ONE_DOTE: 17,
    UNDERLINE_TWO_DOTE: 18,
    FONT_MODE: 16,
    FONT_SIZE: 17,
  };
  const BarcodeType = {
    UPC_A: 0,
    UPC_E: 1,
    JAN13: 2,
    JAN8: 3,
    CODE39: 4,
    ITF: 5,
    CODABAR: 6,
    JAN128: 7,
    CODE93: 72,
    CODE128: 73,
    PDF417: 100,
    DATAMATRIX: 101,
    QRCODE: 102,
  };
  Printer = {
    // 初始化打印参数
    initPrinter: _Printer.initPrinter,
    /**
     * 方法描述：设置打印机打印字体，包括设置加粗，倍高，倍宽，下划线，标准ASCII字体A (12 × 24)，压缩ASCII字体B (9 × 17)
     * int type 0表示12*24字体大小，1表示9*16字体大小，此设置临时有效，打印机不保存此设置，即打印机重启后无效。如需打印9*16大小字体，需要每次传入1手动设置
     * int width 倍宽，范围0~7
     * int height 倍高，范围0~7
     * int bold 0 不加粗，1加粗
     * int underline 0无下划线，1下划线
     */
    setFont: _Printer.setFont,
    /**
     * 方法描述：设置打印机，包括打印并走纸n点行；打印并走纸n字符行；设置字符对齐方式，左对齐，居中，右对
     * 参数：command, value
       Command.PRINT_AND_WAKE_PAPER_BY_LNCH
       打印并走纸value点行
       Command.PRINT_AND_WAKE_PAPER_BY_LINE
       打印并走纸value字符行
       Command.ALIGN  设置打印内容位置，Value值可指定设置的具体位置，可以为
       Command.ALIGN_LEFT;
       Command.ALIGN_CENTER;
       Command.ALIGN_RIGHT
       例1：设置打印文本居中
       Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER);
       Printer.printText("hello world!\n");
       例2：设置打印一维码居中
       Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER);
       Printer.printBarCode(BarcodeType.CODE128, 2, 150, 2,"123456");
       例3：设置打印二维码居中
       Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER);
       Printer.printBarCode(BarcodeType.QRCODE, 2, 3, 6,"123456");
       注：以上居中对于打印图片printImage方法无效
     */
    setPrinter: _Printer.setPrinter,
    // 获取当前打印机状态
    getCurrentStatus: _Printer.getCurrentStatus,
    // 打印自检页面
    printSelfCheckingPage: _Printer.printSelfCheckingPage,
    // 打印文本，String text 文本内容
    printText: _Printer.printText,
    /**
     * 打印表格
     * @param column 表头
     * @param split 分隔符
     * @param width 列宽，传入数组按照数组比例分配宽度，传入数字(384,576,724)，自动匹配热敏纸尺寸，仅限四列内容
     * @param row 内容
     */
    printTable: (column, split, width, row) => {
      if (typeof width === 'number') {
        if (width === 384) width = [14, 6, 6, 6];
        if (width === 576) width = [18, 10, 10, 12];
        if (width === 724) width = [22, 14, 14, 18];
      }
      if (!Array.isArray(width)) return; // 列宽不为数组，终止执行
      _Printer.printTable(column, split, width, row);
    },
    /**
     * 打印条码和二维码
     * int type, int param1, int param2, int param3, String content
     * type为条码类型，类型常量以PrinterConstants.BarcodeType.开头： 一维条码： UPC_A， UPC_E， JAN13， JAN8， CODE39， ITF， CODABAR， CODE93， CODE128。
       二维条码： PDF417，DATAMATRIX，QRCODE。
       width，height，anno为具体条码参数：
       条码类型type为一维条码时，三个参数表示：
       param1：条码横向宽度 ，2<=n<=6，默认为2
       param2：条码高度 1<=n<=255，默认162
       param3：条码注释位置，0不打印，1上方，2下方，3上下方均有 。条码类型type为二维条码时，三个参数表示不同的意思：
     * type为二维码类型：QRCODE
       param1：表示图形版本号，1<=n<=30(0:自动选择)。
       param2：表示纠错等级，n = 76,77,81,72(L:7%,M:15%,Q:25%,H:30%)。
       param3：表示纵向放大倍数。
     * content为条码数据。
     */
    printBarCode: _Printer.printBarCode,
    // 打印图片，imgUrl，图片URL
    printImage: async imgUrl => {
      const res = await axios.get(imgUrl, {responseType: 'arraybuffer'});
      const base64Image = new Buffer(res.data, 'binary').toString('base64');
      return await _Printer.printImage(base64Image, 'NONE', 50, 128);
    },
    /**
     * 方法描述：发送十六进制指令至打印机，例如：若此SDK没有提供需要的功能，可参照指令手册调用此方法直接发送指令给打印机。
       如：在指令手册上查得设置打印位置居中的指令为：0x1B,0x61,0x01，代码可如下编写以实现设置打印位置居中效果：
       Printer.sendBytesData([27, 97, 1]);
       开启斜体文字指令为：0x1C,0x21,0x80，Printer.sendBytesData([28, 33, 128]);
       关闭斜体文字指令为：0x1C,0x21,0x00，Printer.sendBytesData([28, 33, 0]);
     */
    sendBytesData: _Printer.sendBytesData,
    halfCut: _Printer.halfCut, // 全切
    allCut: _Printer.allCut, // 半切
    usbConnect: _Printer.usbConnect, // 连接打印机
    disconnect: _Printer.disconnect, // 断开打印机连接
    isConnected: _Printer.isConnected, // 是否连接成功
    testPrint: async () => {
      await Printer.initPrinter(); // 初始化配置
      await Printer.setFont(0, 0, 0, 0, 1); // 设置下划线
      await Printer.sendBytesData([28, 33, 128]);
      await Printer.printText('打印机测试：');
      await Printer.sendBytesData([28, 33, 0]);
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setFont(0, 0, 0, 1, 0); // 设置加粗
      const row = ['可乐,2,3.5,7.0', '怡宝,4,2.0,8.0'];
      await Printer.printTable('商品,数量,单价,金额', ',', 384, row);
      await Printer.printImage(
        'https://zmgo.oss-cn-shenzhen.aliyuncs.com/app/app-logo.jpg?x-oss-process=image/resize,w_300',
      );
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER);
      await Printer.printBarCode(BarcodeType.QRCODE, 2, 3, 6, '123456');
      await Printer.halfCut(); // 半切
      // await Printer.allCut(); // 全切
    },
    printSendOrder: async () => {
      await Printer.initPrinter(); // 初始化配置

      await Printer.printText('---------------------');
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER); // 设置居中对齐
      await Printer.setFont(0, 1, 1, 1, 0); // 字体加粗加大
      await Printer.printText('-#**美团外卖-');
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER); // 设置居中对齐
      await Printer.setFont(0, 0, 0, 0, 0); // 默认字体
      await Printer.printText('测试门店12345678');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_LEFT); // 还原左对齐
      await Printer.setFont(0, 0, 0, 0, 0); // 默认字体
      await Printer.printText('预计');
      await Printer.setFont(0, 1, 1, 0, 0); // 大字体
      await Printer.printText('今日 25：61');
      await Printer.setFont(0, 0, 0, 0, 0); // 恢复默认字体
      await Printer.printText('送达');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('---------------------');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('下单时间：yyyy-mm-dd HH:mm:ss');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('---------------------');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setFont(0, 1, 1, 0, 0); // 大字体
      await Printer.printText('备注：不要备注不要备注');

      await Printer.setFont(0, 0, 0, 0, 0); // 恢复默认字体

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('*********************');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('-------1号口袋-------');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      const row = ['可乐,2,3.5,7.0', '怡宝,4,2.0,8.0'];
      await Printer.printTable('商品,数量,单价,金额', ',', 384, row);

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('*********************');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('---------其他--------');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      const rowTemp = ['打包费,2', '配送费,2'];
      await Printer.printTable(' , ', ',', 384, rowTemp);

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('*********************');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 2); // 换行
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_RIGHT); // 右对齐
      await Printer.printText('原价：88.88元');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('（用户在线支付）');
      await Printer.setFont(0, 1, 1, 0, 0); // 大字体
      await Printer.printText('88.00元');
      await Printer.setFont(0, 0, 0, 0, 0); // 恢复默认字体

      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_LEFT); // 恢复左对齐
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('---------------------');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setFont(0, 1, 1, 0, 0); // 大字体
      await Printer.printText('XXX');
      await Printer.setFont(0, 0, 0, 0, 0); // 恢复默认字体

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('XXX');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setFont(0, 1, 1, 0, 0); // 大字体
      await Printer.printText('顾客号码：手机尾号8888');
      await Printer.setFont(0, 0, 0, 0, 0); // 恢复默认字体

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('xxxxxxxxxxxxxx');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText('xxxxxxxxxxxxxx');

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setFont(0, 1, 1, 0, 0); // 大字体
      await Printer.printText('顾客地址：xxxxxxxxxxxxxxxx');
      await Printer.setFont(0, 0, 0, 0, 0); // 恢复默认字体

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER); // 设置居中对齐
      await Printer.setFont(0, 1, 1, 1, 0); // 字体加粗加大
      await Printer.printText('-#**美团外卖-');

      await Printer.setFont(0, 0, 0, 0, 0); // 恢复默认字体
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_LEFT); // 恢复左对齐

      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.sendBytesData([28, 33, 0]);
      await Printer.allCut(); // 半切
    },
    printNote: async (row, params) => {
      let now = new Date();
      await Printer.initPrinter(); // 初始化配置
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER); //居中
      await Printer.setFont(0, 1, 1, 1, 0); // 标题加粗大字号
      await Printer.printText(params.storeName); //门店命
      await Printer.setFont(0, 0, 0, 0, 0); // 默认字体
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 0); // 换行
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_LEFT); //左对齐
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.printText(
        `单据日期:${moment(now).format('YYYY-MM-DD')}\n打印时间:${moment(
          now,
        ).format('YYYY-MM-DD hh:mm:ss')}`,
      ); //门店
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.setFont(0, 0, 0, 1, 0); // 设置加粗
      await Printer.printTable('商品,数量,单价,金额', ',', 384, row);
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      (await params.phone) && Printer.printText(`商家电话:${params.phone}`); //门店
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 0); // 换行
      await Printer.setFont(0, 0, 0, 1, 0); // 默认字体
      await Printer.setPrinter(Command.ALIGN, Command.ALIGN_CENTER);
      await Printer.printText(
        `================================\n${params.bottomText}`,
      ); //门店
      // await Printer.printBarCode(BarcodeType.QRCODE, 2, 3, 6, '123456');
      await Printer.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 1); // 换行
      await Printer.sendBytesData([28, 33, 0]);
      await Printer.halfCut(); // 半切
    },
  };
  // (async () => {
  //   // 修复没有打印机模块导致闪退问题
  //   try {
  //     const isConnected = await Printer.isConnected();
  //     if (!isConnected) await Printer.usbConnect();
  //   } catch (e) {
  //     // do nothing
  //   }
  // })();
}

export default Printer;
