package com.vsu.fcounter.printer;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.WritableMap;
import com.printer.sdk.Barcode;
import com.printer.sdk.PrinterConstants;
import com.printer.sdk.PrinterInstance;
import com.printer.sdk.Table;
import com.printer.sdk.usb.USBPort;
import com.printer.sdk.utils.XLog;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

class PrinterModule extends ReactContextBaseJavaModule {

    private ReactContext reactContext;
    private PrinterInstance printer;
    private List<UsbDevice> deviceList;
    private static UsbDevice mUSBDevice;
    public static boolean isConnected = false;// 蓝牙连接状态
    protected static final String TAG = "PrinterModule";
    public static String devicesName = "未知设备";
    private static String devicesAddress;
    private static BluetoothDevice mDevice;
    private static final String ACTION_USB_PERMISSION = "com.android.usb.USB_PERMISSION";
    private int interfaceType = 0;
    private static boolean hasRegDisconnectReceiver = false;
    private Handler mHandler;

    @Override
    public String getName() {
        return "Printer";
    }

    PrinterModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
        mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                int interfaceType = 0;
                switch (msg.what) {
                    case PrinterConstants.Connect.SUCCESS:
                        isConnected = true;
                        GlobalContants.ISCONNECTED = isConnected;
                        GlobalContants.DEVICENAME = devicesName;
                        if (interfaceType == 0) {
                            PrefUtils.setString(reactContext, GlobalContants.DEVICEADDRESS, devicesAddress);
                            IntentFilter bluDisconnectFilter = new IntentFilter();
                            bluDisconnectFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
                            reactContext.registerReceiver(myReceiver, bluDisconnectFilter);
                        }
                        break;
                    case PrinterConstants.Connect.FAILED:
                        isConnected = false;

                        Toast.makeText(reactContext, "连接失败", Toast.LENGTH_SHORT).show();
                        XLog.i(TAG, "ZL at SettingActivity Handler() 连接失败!");
                        break;
                    case PrinterConstants.Connect.CLOSED:
                        isConnected = false;
                        GlobalContants.ISCONNECTED = isConnected;
                        GlobalContants.DEVICENAME = devicesName;
                        Toast.makeText(reactContext, "连接关闭", Toast.LENGTH_SHORT).show();
                        XLog.i(TAG, "ZL at SettingActivity Handler() 连接关闭!");
                        break;
                    case PrinterConstants.Connect.NODEVICE:
                        isConnected = false;
                        Toast.makeText(reactContext, "没有可连接的设备", Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        break;
                }

            }

        };
    }

    @ReactMethod
    void initPrinter(Promise promise) {
        new Thread(() -> {
            printer.initPrinter();
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void setFont(int type, int width, int height, int bold, int underline, Promise promise) {
        new Thread(() -> {
            printer.setFont(type, width, height, bold, underline);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void setPrinter(int command, int value, Promise promise) {
        new Thread(() -> {
            printer.setPrinter(command, value);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void getCurrentStatus(Promise promise) {
        new Thread(() -> {
            String strStatus = "";
            int i = printer.getCurrentStatus();
            if (i == 0) {
                strStatus = "打印机状态正常";
            } else if (i == -1) {
                strStatus = "接收数据失败";
            } else if (i == -2) {
                strStatus = "打印机缺纸";
            } else if (i == -3) {
                strStatus = "打印机纸将尽";
            } else if (i == -4) {
                strStatus = "打印机开盖";
            } else if (i == -5) {
                strStatus = "发送数据失败";
            }
            WritableMap res = Arguments.createMap();
            res.putInt("code", i);
            res.putString("msg", strStatus);
            promise.resolve(res);
        }).start();
    }

    @ReactMethod
    void printSelfCheckingPage(Promise promise) {
        new Thread(() -> {
            printer.printSelfCheckingPage();
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void printText(String text, Promise promise) {
        new Thread(() -> {
            printer.printText(text);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void printTable(String column, String split, ReadableArray width, ReadableArray row, Promise promise) {
        new Thread(() -> {
            int[] columnWidth = new int[width.size()];
            for (int i = 0; i < width.size(); i++)
                columnWidth[i] = width.getInt(i);
            Table table = new Table(column, split, columnWidth);
            for (int i = 0; i < row.size(); i++)
                table.addRow(row.getString(i));
            printer.printTable(table);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void printBarCode(int type, int param1, int param2, int param3, String content, Promise promise) {
        new Thread(() -> {
            Barcode barcode = new Barcode((byte) type, param1, param2, param3, content);
            printer.printBarCode(barcode);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void printImage(String base64Image, String align, int left, int level, Promise promise) {
        new Thread(() -> {
            byte[] decodedString = Base64.decode(base64Image, Base64.DEFAULT);
            Bitmap bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
            PrinterConstants.PAlign alignType = PrinterConstants.PAlign.valueOf(align);
            printer.printImage(bitmap, alignType, left, level);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void sendBytesData(ReadableArray data, Promise promise) {
        new Thread(() -> {
            byte[] bytes = new byte[data.size()];
            for (int i = 0; i < data.size(); i++)
                bytes[i] = (byte) data.getInt(i);
            printer.sendBytesData(bytes);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void allCut(Promise promise) {
        new Thread(() -> {
            printer.cutPaper(65, 50);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void halfCut(Promise promise) {
        new Thread(() -> {
            printer.cutPaper(66, 50);
            promise.resolve(true);
        }).start();
    }

    @ReactMethod
    void usbConnect(Promise promise) {
        new Thread(() -> {
//            try {
//                UsbManager manager = (UsbManager) reactContext.getSystemService(Context.USB_SERVICE);
//                usbAutoConn(manager);
//                promise.resolve(true);
//            } catch (Exception e) {
//                promise.resolve(false);
//            }
            try {
                initBluetoothPrinter(); // 调用初始化蓝牙连接的方法
                if (isConnected) { // 检查连接状态
                    promise.resolve(true);
                } else {
                    promise.reject("Bluetooth connection failed");
                }
            } catch (Exception e) {
                Log.e(TAG, "蓝牙连接失败", e);
                promise.reject(e);
            }
        }).start();
    }

    @ReactMethod
    void disconnect(Promise promise) {
        new Thread(() -> {
            if (printer != null) {
                printer.closeConnection();
                printer = null;
                if (interfaceType == 0 && hasRegDisconnectReceiver) {
                    reactContext.unregisterReceiver(myReceiver);
                    hasRegDisconnectReceiver = false;
                }
                promise.resolve(true);
            }
            promise.resolve(false);
        }).start();
    }

    @ReactMethod
    void isConnected(Promise promise) {
        promise.resolve(isConnected);
    }

    public BroadcastReceiver myReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {

                if (device != null && printer != null && isConnected && device.equals(mDevice)) {
                    printer.closeConnection();
                    mHandler.obtainMessage(PrinterConstants.Connect.CLOSED).sendToTarget();
                }
            }

        }
    };

    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        @SuppressLint("NewApi")
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.w(TAG, "receiver action: " + action);

            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    reactContext.unregisterReceiver(mUsbReceiver);
                    UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
                            && mUSBDevice.equals(device)) {
                        printer.openConnection();
                    } else {
                        mHandler.obtainMessage(PrinterConstants.Connect.FAILED).sendToTarget();
                        Log.e(TAG, "permission denied for device " + device);
                    }
                }
            }
        }
    };


    /*
     * @Override public void onConfigurationChanged(Configuration newConfig) {
     * super.onConfigurationChanged(newConfig); if
     * (this.getResources().getConfiguration().orientation ==
     * Configuration.ORIENTATION_LANDSCAPE) { // land } else if
     * (this.getResources().getConfiguration().orientation ==
     * Configuration.ORIENTATION_PORTRAIT) { // port } }
     */

    @SuppressLint({"InlinedApi", "NewApi"})
    public void usbAutoConn(UsbManager manager) {

        doDiscovery(manager);
        if (deviceList.isEmpty()) {
            Toast.makeText(reactContext, "打印机未连接!", Toast.LENGTH_SHORT).show();
            return;
        }
        mUSBDevice = deviceList.get(0);
        if (mUSBDevice == null) {
            mHandler.obtainMessage(PrinterConstants.Connect.FAILED).sendToTarget();
            return;
        }
        printer = PrinterInstance.getPrinterInstance(reactContext, mUSBDevice, mHandler);
        devicesName = mUSBDevice.getDeviceName();
        devicesAddress = "vid: " + mUSBDevice.getVendorId() + "  pid: " + mUSBDevice.getProductId();
        UsbManager mUsbManager = (UsbManager) reactContext.getSystemService(Context.USB_SERVICE);
        if (mUsbManager.hasPermission(mUSBDevice)) {
            printer.openConnection();
        } else {
            // 没有权限询问用户是否授予权限
            PendingIntent pendingIntent = PendingIntent.getBroadcast(reactContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
            IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
            filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
            filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
            reactContext.registerReceiver(mUsbReceiver, filter);
            mUsbManager.requestPermission(mUSBDevice, pendingIntent); // 该代码执行后，系统弹出一个对话框
        }

    }

    @SuppressLint("NewApi")
    private void doDiscovery(UsbManager manager) {
        HashMap<String, UsbDevice> devices = manager.getDeviceList();
        deviceList = new ArrayList<UsbDevice>();
        for (UsbDevice device : devices.values()) {
            if (USBPort.isUsbPrinter(device)) {
                deviceList.add(device);
            }
        }

    }


    /**
     * 蓝牙设备连接
     */
    private void initBluetoothPrinter() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
            Log.e(TAG, "蓝牙未启用或不可用");
            return;
        }

        Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
        if (pairedDevices != null && pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                if (device.getName().equals("BLU58")) { // 匹配名称为BLU58的设备
                    mDevice = device;
                    break;
                }
            }
        }

        if (mDevice != null) {
            // 假设SDK提供了一个静态方法来获取实例
            printer = PrinterInstance.getPrinterInstance(mDevice, mHandler);
            printer.openConnection();
            isConnected = true;
        } else {
            Log.e(TAG, "未找到匹配的蓝牙设备");
            isConnected = false;

        }
    }
}