package com.dlc.chemical.serial.port.scan

import android.content.Context
import android.os.Handler
import android.os.Looper
import android_serialport_api.SerialPort
import com.dlc.chemical.serial.HexDump
import com.dlc.chemical.serial.listener.OnSerialListener
import com.dlc.chemical.sp.PortDevicesSp
import com.rc.core.log.RcLog
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.security.InvalidParameterException

/**
 * info
 *
 * @author ReiChin_
 */
class PortScanManager(private val listener: OnSerialListener? = null) {

    companion object {
        const val BAUD_RATE = 9600
        const val PATH = "/dev/ttyS4"

        private const val MESSAGE_DELAY: Long = 200 // 延迟200ms，判断扫码是否完成。
    }

    private var mSerialPort: SerialPort? = null
    private var mOutputStream: OutputStream? = null
    private var mInputStream: InputStream? = null

    private var mReadThread: ReadThread? = null

    fun connect(context: Context) {
        try {
            val device = PortDevicesSp.loadConfig(context)
            mSerialPort = SerialPort(File(device.path), device.baudRate, 0)
            mInputStream = mSerialPort?.inputStream
            mOutputStream = mSerialPort?.outputStream
            listener?.onConnected(true, "path:${device.path}, baudRate:${device.baudRate} connected.")
            mReadThread = ReadThread(mInputStream) { buffer, size ->
                onDataReceived(buffer, size)
            }
            mReadThread?.start()
        } catch (e: SecurityException) {
            listener?.onConnected(
                false,
                "You do not have read/write permission to the serial port."
            )
        } catch (e: IOException) {
            listener?.onConnected(false, "The serial port can not be opened for an unknown reason.")
        } catch (e: InvalidParameterException) {
            listener?.onConnected(false, "Please configure your serial port first.")
        } catch (e: Exception) {
            listener?.onConnected(false, "connect port fail, 未知异常.")
        }
    }

    private var mKeyContent = StringBuilder()

    private fun onDataReceived(buffer: ByteArray, size: Int) {
        RcLog.info("PortScanManager#onDataReceived() QRCode/IC buffer=${HexDump.toHexString(buffer, length = size)}, size=${size}")
        val hex = if (buffer.size > 4
            && 0x02 == buffer[0].toInt() // 正文开始
            && 0x0D == buffer[size - 3].toInt() // 回车
            && 0x0A == buffer[size - 2].toInt() // 换行
            && 0x03 == buffer[size - 1].toInt()) {  // 正文结束
            HexDump.toHexString(buffer, offset = 1, length = size - 4)
        } else {
            HexDump.toHexString(buffer, length = size)
        }

        when(hex) {
            // 正文开始
            "02" -> mKeyContent.clear()
            "0D", "0A", "03"-> {
                // 0D-回车 0A-换行 03-正文结束
//                mHandler.removeCallbacks(mScanningFishedRunnable)
//                mHandler.postDelayed(mScanningFishedRunnable, MESSAGE_DELAY)
            }
            else -> {
                trimInvalidData(hex)?.let {
                    RcLog.info("PortScanManager#onDataReceived() QRCode/IC buffer=${HexDump.hexToAscii(it)}")

                    mKeyContent.append(HexDump.hexToAscii(it)) }
//                mKeyContent.append(HexDump.hexToAscii(hex))
            }
        }

        mHandler.removeCallbacks(mScanningFishedRunnable)
        mHandler.postDelayed(mScanningFishedRunnable, MESSAGE_DELAY)
    }

    private fun trimInvalidData(hexData: String?): String? {
        if (null == hexData || hexData.length < 2) return null
        if (hexData.length % 2 == 1) return null

        if (hexData.length == 2) {
            val decimal = HexDump.hexToDecimal(hexData)
            return if (isValidData(decimal)) hexData else null
        }

        val buffer = StringBuffer()
        for (index in hexData.indices step 2) {
            val temp = hexData.substring(index, index + 2)
            if (isValidData(HexDump.hexToDecimal(temp))) {
                buffer.append(temp)
            }
        }
        return buffer.toString()
    }

    private fun isValidData(decimal: Long): Boolean {
        // 数字
        if (decimal in 0x30..0x39) return true
        // 大写字母
        if (decimal in 0x41..0x5A) return true
        // 小写字母
        if (decimal in 0x61..0x61) return true
        return false
    }

    private val mHandler by lazy { Handler(Looper.getMainLooper()) }
    private val mScanningFishedRunnable = Runnable {
        if (mKeyContent.isNotEmpty()) listener?.onReceive(mKeyContent.toString())
        mKeyContent.clear()
    }

    fun disconnect() {
        mReadThread?.interrupt()
        mReadThread = null
        mSerialPort?.close()
        mSerialPort = null
    }

    private class ReadThread(
        private val inputStream: InputStream?,
        private val callback: ((buffer: ByteArray, size: Int) -> Unit)? = null
    ) : Thread() {
        override fun run() {
            while (!isInterrupted) {
                var size: Int
                try {
                    val buffer = ByteArray(64)
                    if (inputStream == null) return
                    size = inputStream.read(buffer)
                    if (size > 0) {
                        callback?.invoke(buffer, size)
                    }
                } catch (e: IOException) {
                    e.printStackTrace()
                    return
                }
            }
        }
    }

}