package zs.qimai.com.printer2.manager

import android.hardware.usb.*
import android.util.Log
import zs.qimai.com.printer2.callback.UsbPrintConnCallBack
import zs.qimai.com.printer2.printStatus.PrintStatusCallBack
import zs.qimai.com.printer2.printStatus.PrinterStatusUtils
import zs.qimai.com.printer2.utils.PrintManagerUtils.Companion.USB_CONN_FAILED
import zs.qimai.com.printer2.utils.PrintManagerUtils.Companion.USB_DEVICE_INFO_NOT_FOUND
import java.util.*

class UsbDeviceManager(override var mType: Int = USB) : DeviceManager() {
    private val TAG = "UsbDeviceManager"
    var usbDevice: UsbDevice? = null
    var usbManager: UsbManager? = null
    private var mmConnection: UsbDeviceConnection? = null
    private var mmIntf: UsbInterface? = null
    private var mmEndIn: UsbEndpoint? = null
    private var mmEndOut: UsbEndpoint? = null
    var mUsbPrintConnCallBack: UsbPrintConnCallBack? = null
    override fun openPort() {
        Log.d(TAG, "openPort: ")
        usbDevice?.let {
            if (it.interfaceCount != 0) {
                mmIntf = it.getInterface(0)
                if (mmIntf != null) {
                    this.mmConnection = this.usbManager?.openDevice(this.usbDevice)
                    this.deviceId =
                        "${this.usbDevice?.serialNumber ?: ""}${this.usbDevice?.productId ?: 0}" +
                                "${this.usbDevice?.manufacturerName ?: ""}${this.usbDevice?.productName ?: ""}"
                    if (this.mmConnection != null && this.mmConnection?.claimInterface(
                            mmIntf!!,
                            true
                        ) == true
                    ) {
                        for (i in 0 until mmIntf!!.endpointCount) {
                            val ep = mmIntf!!.getEndpoint(i)
                            if (ep.type == 2) {
                                if (ep.direction == 0) {
                                    this.mmEndOut = ep
                                } else {
                                    this.mmEndIn = ep
                                }
                            }
                        }
                    }
                }
            }
            if (this.mmEndOut != null) {
                //检查打印机状态
                PrinterStatusUtils(this).apply {
                    mPrintStatusCallBack = object : PrintStatusCallBack {
                        override fun searchResult(status: Int?) {
                            mPrintMode = status ?: ESC
                            mStatus = true
                            name = it.productName
                            if (name.isNullOrEmpty()) {
                                name = if (mPrintMode == ESC) "小票打印机" else "杯贴打印机"
                            }
                            DeviceManagerUtils.getInstance().addDevice(this@UsbDeviceManager)
                            mUsbPrintConnCallBack?.onConnSucess(this@UsbDeviceManager)
                        }
                    }
                }.queryStatus()

            } else {
                mUsbPrintConnCallBack?.onConnFailed(USB_CONN_FAILED, "连接失败")

            }
        } ?: mUsbPrintConnCallBack?.onConnFailed(USB_DEVICE_INFO_NOT_FOUND, "获取不到USB设备信息")

    }

    override fun closePort() {
        mStatus = false
        mUsbPrintConnCallBack = null
        DeviceManagerUtils.getInstance().removeDevice(this@UsbDeviceManager)
        if (this.mmIntf != null && this.mmConnection != null) {
            this.mmConnection!!.releaseInterface(this.mmIntf)
            this.mmConnection!!.close()
            this.mmConnection = null
        }
    }

    override fun readData(bytes: ByteArray): Int {
        this.mmEndIn?.let {
            return if (this.mmConnection != null) this.mmConnection!!.bulkTransfer(
                this.mmEndIn,
                bytes,
                bytes.size,
                200
            ) else 0
        }
        return 0
    }

    override fun writeData(data: ByteArray) {
        //如果数据长度超过16384则超过的不能显示


        try {
            var result = 0
            val sendData: Vector<Byte> = Vector<Byte>()
            for (i in data.indices) {
                if (sendData.size >= 1024) {
                    Log.e(
                      TAG,
                        "i = " + i + "\tsendData size -> " + sendData.size + "\tdata size -> " + data.size
                    )
                    result += mmConnection!!.bulkTransfer(
                        mmEndOut,
                        this.convertVectorByteToBytes(sendData),
                        sendData.size,
                        1000
                    )
                    sendData.clear()
                    Log.e(TAG, "sendData.clear() size -> " + sendData.size)
                }
                sendData.add(data[i])
            }
            if (sendData.size > 0) {
                Log.e(TAG, "sendData size -> " + sendData.size)
                result += mmConnection!!.bulkTransfer(
                    mmEndOut,
                    this.convertVectorByteToBytes(sendData),
                    sendData.size,
                    1000
                )
            }
            if (result == data.size) {
                Log.d(TAG, "send success")
            }
        } catch (var7: Exception) {
            Log.d(TAG, "Exception occured while sending data immediately: " + var7.message)
        }
    }

    /*   override fun equals(other: Any?): Boolean {
           if (other != null && other is UsbDeviceManager) {
               if ((other.address == this.address) && other.usbDevice == this.usbDevice) {
                   return true
               }
           }
           return false
       }

       override fun hashCode(): Int {

           return address?.hashCode() ?: 0 + usbDevice.hashCode()
       }*/

    override fun toString(): String {
        return "UsbDeviceManager(mType=$mType, TAG='$TAG', usbDevice=$usbDevice, usbManager=$usbManager, mmConnection=$mmConnection, mmIntf=$mmIntf, mmEndIn=$mmEndIn, mmEndOut=$mmEndOut, mUsbPrintConnCallBack=$mUsbPrintConnCallBack)"
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is UsbDeviceManager) return false

        if (deviceId != other.deviceId) return false

        return true
    }

    override fun hashCode(): Int {
        return deviceId.hashCode()
    }
    protected fun convertVectorByteToBytes(data: Vector<Byte>): ByteArray? {
        val sendData = ByteArray(data.size)
        if (data.size > 0) {
            for (i in data.indices) {
                sendData[i] = data[i] as Byte
            }
        }
        return sendData
    }
}