package com.cx_1500n_plugin

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.os.SystemClock
import android.os.Vibrator
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import com.hc.pda.HcPowerCtrl
import com.hc.so.SerialPortManager
import com.hc.so.listener.OnSerialPortDataListener
import com.nlscan.nlsdk.NLDeviceStream
import com.xlzn.hcpda.R
import com.xlzn.hcpda.uhf.UHFReader
import com.xlzn.hcpda.uhf.entity.UHFReaderResult
import com.xlzn.hcpda.uhf.entity.UHFTagEntity
import com.xlzn.hcpda.uhf.enums.InventoryModeForPower
import com.xlzn.hcpda.uhf.interfaces.OnInventoryDataListener
import com.xlzn.hcpda.uhf.module.UHFReaderSLR
import com.xlzn.hcpda.utils.DataConverter.bytesToHex
import com.xlzn.hcpda.utils.LoggerUtils
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.EventChannel.EventSink
import io.flutter.plugin.common.EventChannel.StreamHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import org.json.JSONObject
import java.io.ByteArrayOutputStream
import java.io.File
import java.nio.charset.StandardCharsets


/** Cx1500nPlugin */
class Cx1500nPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
    NLDeviceStream.NLUartListener {
    private var activity: Activity? = null
    val TAG = "Cx1500nPlugin"

    private lateinit var channel: MethodChannel
    private lateinit var eventChannel: EventChannel
    private var eventSink: EventSink? = null
    var sp_path: String = "pda"

    //    private val ds: NLDeviceStream = NLDevice(NLDeviceStream.DevClass.DEV_UART)
    val path: String = "/dev/ttyS1"
    val baudrate: Int = 9600

    var ctrl: HcPowerCtrl? = HcPowerCtrl()
    var serialPortManager: SerialPortManager? = null
    private val barcodeBuff = ByteArray(2 * 1024)

    var vibrator: Vibrator? = null
    var tagEntityList: MutableList<UHFTagEntity> = ArrayList<UHFTagEntity>()

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cx_1500n_plugin")
        eventChannel = EventChannel(
            flutterPluginBinding.binaryMessenger,
            "cx_1500n_plugin/connection"
        )
        eventChannel.setStreamHandler(
            object : StreamHandler {
                override fun onListen(arguments: Any?, events: EventSink?) {
                    Log.e(TAG,"events onlistn called")
                    eventSink = events
                }

                override fun onCancel(arguments: Any?) {
                    Log.e(TAG,"events oncancel called")
                    eventSink = null
                }
            }
        )
        channel.setMethodCallHandler(this)

        Utils.loadSoundPool(flutterPluginBinding.applicationContext)
    }


    override fun onMethodCall(call: MethodCall, result: io.flutter.plugin.common.MethodChannel.Result) {
        if (call.method == "getPlatformVersion") {
            result.success("Android ${Build.VERSION.RELEASE}")
        } else if (call.method == "connect") {
            connect(call, result)
        } else if (call.method == "disconnect") {
            disconnect(call, result)
        } else if (call.method == "startInventory") {
            startInventory(result)
        } else if (call.method == "stopInventory") {
            stopInventory(result)
        } else if (call.method == "setPower") {
            val power: Int = call.argument<Int>("power")!!
            setPower(power, result)
        } else if (call.method == "read") {
            read(call, result)
        } else if (call.method == "startScan") {
            startScan()
            result.success(null)
        } else if (call.method == "stopScan") {
            closeScan()
            result.success(null)
        } else {
            result.notImplemented()
        }
    }

    private fun disconnect(call: MethodCall, result: Result) {
        UHFReader.getInstance().disConnect()
        // 创建一个Intent对象
        val intent = Intent()
        // 设置广播的Action
        intent.setAction("android.intent.action.SCREEN_ON_UHF")
        // 发送广播
        activity!!.sendBroadcast(intent)
        result.success("")
    }

    private fun connect(call: MethodCall, result: Result) {
        val intent = Intent()
        intent.setAction("android.intent.action.SCREEN_OFF_UHF")
        activity?.sendBroadcast(intent)
        SystemClock.sleep(100)

        GlobalScope.launch {
            try {
                val uhfConnectResult = UHFReader.getInstance().connect(activity!!)
                if (uhfConnectResult.resultCode == UHFReaderResult.ResultCode.CODE_SUCCESS) {
                    if (UHFReaderSLR.is5300) {
                        Log.e(TAG, "onPostExecute: 省电模式")
                        UHFReader.getInstance()
                            .setInventoryModeForPower(InventoryModeForPower.POWER_SAVING_MODE)
                    }
                    //                UHFReader.getInstance().setInventoryModeForPower(InventoryModeForPower.POWER_SAVING_MODE);
                    UHFReader.getInstance().setDynamicTarget(0)

                    val anInt: Int =
                        HcPreferences.getInstance()
                            .getInt(activity!!.applicationContext, "pda", "power")
                    Log.e("TAG", "onPostExecute: " + anInt)
                    val booleanUHFReaderResult: UHFReaderResult<Boolean?> =
                        UHFReader.getInstance().setPower(anInt)
                    Log.e(TAG, "功率设置:.... " + booleanUHFReaderResult.getResultCode())

                    withContext(Dispatchers.Main) {
                        result.success("")
                        openScan115200()
                    }
                } else {
                    withContext(Dispatchers.Main) {
                        result.error("101", "connection Failed", null)
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
                withContext(Dispatchers.Main) {
                    result.error("102", e.message, null)
                }
            }
        }
    }

    var epcList: MutableList<String?> = ArrayList<String?>()
    var isTidModel: Boolean = false
    var count = 0

    var handler: Handler = object : Handler(Looper.myLooper()!!) {
        @RequiresApi(api = Build.VERSION_CODES.N)
        @SuppressLint("SetTextI18n")
        override fun handleMessage(msg: Message) {
            if (stop) {
                return
            }
            if (msg.what == 1) {
                val uhfTagEntity = msg.obj as UHFTagEntity
                count++
                var addFlag = false
                for (entity in tagEntityList) {
                    if (entity.getEcpHex() == uhfTagEntity.getEcpHex()) {
                        entity.count = (entity.count + uhfTagEntity.count)
                        entity.rssi = uhfTagEntity.rssi
                        addFlag = true
                        break
                    }
                }

                if (!addFlag) {
                    tagEntityList.add(uhfTagEntity)
                }

                eventSink?.success(
                    prepareEvent(
                        Events.EVENT_INVENTORY,
                        Json.encodeToString(
                            ListSerializer(UHFTagEntity.serializer()),
                            tagEntityList
                        )
                    )
                )
//                tvCount.setText(count.toString() + "")
//                tvNumber.setText(mainActivity.tagEntityList.size() + "")
//
//                if (myAdapter != null) {
//                    myAdapter.notifyDataSetChanged()
//                }
            }

        }


    }

    private fun prepareEvent(event: String, data: String): Any {
        return JSONObject().apply {
            put("en", event)
            put("data", data)
        }.toString()
    }

    private fun setPower(power: Int, mResult: Result) {
        var mPower: Int = power
        if (mPower == 6) {
            mPower = 0
        }
        LoggerUtils.d("CHLOG", power.toString() + "")
        Log.e("TAG", "setPower: " + mPower)
        //        UHFReaderResult<Boolean> result = UHFReader.getInstance().setPower(1);
        val result = UHFReader.getInstance().setPower(mPower)
        //        UHFReaderResult<Boolean> result = UHFReader.getInstance().setPower(power);
        if (result.getResultCode() == UHFReaderResult.ResultCode.CODE_SUCCESS) {
            HcPreferences.getInstance()
                .set(activity, sp_path, "power", mPower)
            //            HcPreferences.getInstance().set(activity, sp_path, "power", power);
            Toast.makeText(activity, R.string.success, Toast.LENGTH_SHORT).show()
            mResult.success("")
        } else {
            Toast.makeText(activity, R.string.fail, Toast.LENGTH_SHORT).show()
            mResult.error("100", "Failed to set with code ${result.resultCode}", null)
        }
    }

    var stop: Boolean = false
    private fun startInventory(methodResult: Result) {
        stop = false
        UHFReader.getInstance().setOnInventoryDataListener(object : OnInventoryDataListener {
            override fun onInventoryData(tagEntityList: MutableList<UHFTagEntity?>?) {
                if (tagEntityList != null && tagEntityList.size > 0) {
                    for (k in tagEntityList.indices) {
                        if (!stop) {
                            if (!TextUtils.isEmpty(tagEntityList.get(k)!!.getEcpHex())) {
                                val message = Message()
                                message.what = 1
                                message.obj = tagEntityList.get(k)
                                handler.sendMessage(message)
                                Utils.play()
                            }
                        }
                    }
                }
            }
        })
//        //创建适配器
//        myAdapter = com.xlzn.hcpda.uhf.ui.main.InventoryFragment.MyAdapter(
//            mainActivity.tagEntityList,
//            isAscii,
//            isUpc
//        )
//        //设置适配器
//        recyclerview.setAdapter(myAdapter)


        Log.e("ttt", " 开始盘点启动 ")
        val readerResult = UHFReader.getInstance().startInventory()

        Log.e("ttt", " 开始盘点 readerResult.getData(): " + readerResult.getData())
        Log.e("ttt", " 开始盘点 readerResult.getResultCode(): " + readerResult.getResultCode())


        if (readerResult.getResultCode() == UHFReaderResult.ResultCode.CODE_SUCCESS) {
            methodResult.success(null)

//            var trim = "" //et_stopTime.getText().toString().trim { it <= ' ' }
//            if (trim == "") {
//                trim = "80000000"
//            }
//            val finalTrim = trim
//            inventoryTime = finalTrim.toInt()
//            inventoryTime = inventoryTime * 1000
//            if (needStop) {
//                handler.postDelayed(object : Runnable {
//                    override fun run() {
//                        UHFReader.getInstance().stopInventory()
//                        handler.sendEmptyMessage(3)
//                        timeKeeping = 0
//                        handler.removeCallbacks(runnable)
//                    }
//                }, inventoryTime.toLong())
//                runnable = object : Runnable {
//                    @SuppressLint("SetTextI18n")
//                    override fun run() {
//                        // 更新数据（例如：更新计数器）
//                        timeKeeping = timeKeeping + 1
//                        tvTime.setText(timeKeeping.toString() + "")
//                        // 每隔1秒再次执行该Runnable
//                        handler.postDelayed(this, 1000)
//                    }
//                }
//
//                handler.post(runnable)
//            } else {
//            runnable = object : Runnable {
//                @SuppressLint("SetTextI18n")
//                override fun run() {
//                    // 更新数据（例如：更新计数器）
////                        timeKeeping = timeKeeping + 1
////                        tvTime.setText(timeKeeping.toString() + "")
//                    // 每隔1秒再次执行该Runnable
//                    handler.postDelayed(this, 1000)
//                }
//            }
//
//            handler.post(runnable!!)
//            }
//            btStartStop.setText(R.string.stop)
//            btnSingle.setEnabled(false)
        } else {
            Toast.makeText(activity, R.string.fail, Toast.LENGTH_SHORT).show()
        }

    }

    var runnable: Runnable? = null

    fun stopInventory(methodResult: Result) {
        stop = true
        Utils.stop()

        val booleanUHFReaderResult = UHFReader.getInstance().stopInventory()

        Log.e(
            "ttt",
            " 停止盘点 booleanUHFReaderResult.getData(): " + booleanUHFReaderResult.getData()
        )
        Log.e(
            "ttt",
            " 停止盘点 booleanUHFReaderResult.getResultCode(): " + booleanUHFReaderResult.getResultCode()
        )

        if (booleanUHFReaderResult.resultCode == UHFReaderResult.ResultCode.CODE_SUCCESS) {
            methodResult.success("Success :: ${booleanUHFReaderResult.data}")
        } else {
            methodResult.error(
                "105",
                "stop inventory failed :: ${booleanUHFReaderResult.message}",
                null
            )
        }
    }


    /*------READ SINGLE EPC--------*/
    fun read(call: MethodCall, result: Result) {
        val password: String = call.argument<String?>("password") ?: "00000000"
        var address: Int = call.argument<Int?>("address") ?: 2
        var wordCount: Int = call.argument<Int?>("wordCount") ?: 6
        val membank: Int = call.argument<Int?>("membank") ?: 0
        val readByByte: Boolean = call.argument<Boolean?>("read_by_byte") == true
        val readAscii: Boolean = call.argument<Boolean?>("readAscii") == true
        if (password.length != 8) {
            Toast.makeText(
                activity,
                "The password must contain 4 bytes of hexadecimal data!",
                Toast.LENGTH_SHORT
            ).show()
            return
        }

        if (membank == 0) {
            address = 0
            wordCount = 4
        } else if (membank == 1) {
            address = 2
            wordCount = 6
        } else {
            address = 0
            wordCount = 6
        }


//        var addrWord = address
//        var numWord = wordCount

        val readerResult = UHFReader.getInstance().read(password, membank, address, wordCount, null)

        if (readerResult.resultCode == 0) {
            Log.e(TAG, "readTag: data = " + readerResult.getData())
            result.success(prepareEvent(Events.EVENT_READ, readerResult.getData()))
        } else {
            Log.e(TAG, "readTag: err")
            Toast.makeText(activity, R.string.fail, Toast.LENGTH_SHORT).show()
            result.error(
                readerResult.resultCode.toString(),
                "Failed :: ${readerResult.message}",
                null
            )
        }

//        if (readByByte) {
//            if (addrWord % 2 == 1)  //奇数
//            {
//                numWord = 1 + (numWord / 2)
//            } else { //地址是偶数
//                //
//                numWord = (numWord + 1) / 2
//            }
//            addrWord = addrWord / 2
//        }
//
//        var readerResult: UHFReaderResult<String>? = null
////        if (cbSelectRead.isChecked()) {
////            //查找指定标签
////            readerResult =
////                UHFReader.getInstance().read(password, membank, addrWord, numWord, selectEntity)
////        } else {
//        readerResult = UHFReader.getInstance().read(password, membank, addrWord, numWord, null)
////        }
//        if (readerResult.getResultCode() != UHFReaderResult.ResultCode.CODE_SUCCESS) {
////            etDataRead.setText("")
//            Toast.makeText(activity, R.string.fail, Toast.LENGTH_SHORT).show()
//            result.error(readerResult.resultCode.toString(), "Failed", null)
//            return
//        }
//
//        Toast.makeText(activity, R.string.success, Toast.LENGTH_SHORT).show()
//        var finleData = ""
//        if (readByByte) {
//            //111122223333444455556666
//            Log.e("TAG", "readerResult.getData(): " + readerResult.getData())
//            Log.e("TAG", "(address%2)*2: " + (address % 2) * 2)
//            Log.e("TAG", "wordCount*2): " + wordCount * 2)
//            val endIndex = (address % 2) * 2 + wordCount * 2
//            finleData = readerResult.getData().substring((address % 2) * 2, endIndex)
////            etDataRead.setText(finleData)
//        } else {
//            finleData = readerResult.getData()
////            etDataRead.setText(readerResult.getData())
//        }
//
//        if (readAscii) {
//            finleData = decode(finleData)
//        }
//        result.success(prepareEvent(Events.EVENT_READ, finleData))
    }

    private val hexString: String = "0123456789ABCDEFabcdef"

    /*
     * 将16进制数字解码成字符串,适用于所有字符（包括中文）
     */
    fun decode(bytes: String): String {
        val baos = ByteArrayOutputStream(
            bytes.length / 2
        )
        // 将每2位16进制整数组装成一个字节 5731363939303030323334
        var i = 0
        while (i < bytes.length) {
            baos.write(
                (hexString.indexOf(bytes.get(i)) shl 4 or hexString
                    .indexOf(bytes.get(i + 1)))
            )
            i += 2
        }
        return String(baos.toByteArray())
    }

    private fun startScan() {
//        if (ctrl == null || !ds.isOpen) {

        serialPortManager = SerialPortManager()
        if (!serialPortManager!!.openSerialPort(File("/dev/ttyS1"), 9600)) {
            Log.e("TAG", "onResume:open ")
        } else {
            Log.e("TAG", "onResume:open fail ")
        }
        serialPortManager?.setOnSerialPortDataListener(object : OnSerialPortDataListener {
            public override fun onDataReceived(bytes: ByteArray) {
                Log.e("TAG", "onDataReceived: " + bytesToHex(bytes))
                Log.e("TAG", "onDataReceived: " + String(bytes, StandardCharsets.UTF_8))
                val barcode = String(bytes, 0, bytes.size)
                count = count + 1
                activity?.runOnUiThread {
                    Utils.playSoundOnce()
                    eventSink!!.success(
                            prepareEvent(
                                    Events.EVENT_BARCODE,
                                    barcode
                            )
                    )
                }
//                mSoundPool.play(soundId, 1, 1, 0, 0, 1.0.toFloat())
//                barcodeList.add(barcode)
//                runOnUiThread(object : Runnable {
//                    override fun run() {
//                        textView.append(barcode)
//                        tv_count.setText("扫描次数 " + count)
//                        scrollToBottom(scrollView, textView)
//                    }
//                })
            }

            public override fun onDataSent(bytes: ByteArray) {
                Log.e("TAG", "send: " + String(bytes))
            }
        })

        if (ctrl != null) {
            ctrl!!.scanTrig(0)
            try {
                Thread.sleep(100)
            } catch (e: InterruptedException) {
                e.printStackTrace()
            }
        } else {
            ctrl = HcPowerCtrl()
            ctrl!!.scanTrig(0)
            try {
                Thread.sleep(100)
            } catch (e: InterruptedException) {
                e.printStackTrace()
            }
        }
        ctrl!!.scanTrig(1)
    }

    private fun closeScan() {
        ctrl!!.scanPower(0)
        serialPortManager?.closeSerialPort();
    }

    private fun openScan115200() {
        ctrl = HcPowerCtrl()
        ctrl!!.scanTrig(1)
        ctrl!!.scanPower(1)
        ctrl!!.scanWakeup(1)
        ctrl!!.scanPwrdwn(1)
        ctrl!!.scanTrig(0)
        try {
            Thread.sleep(200)
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
        ctrl!!.scanTrig(1)
        ctrl!!.scanPower(1)
        ctrl!!.scanWakeup(1)
        ctrl!!.scanPwrdwn(1)
        ctrl!!.scanTrig(0)
    }


    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
        eventChannel.setStreamHandler(null)
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.activity
    }

    override fun onDetachedFromActivityForConfigChanges() {

    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        activity = binding.activity
    }

    override fun onDetachedFromActivity() {

    }

    override fun actionRecv(RecvBuff: ByteArray?, len: Int) {
//        if (RecvBuff != null) {
//            System.arraycopy(RecvBuff, 0, barcodeBuff, 0, len)
//            val barcode: String = kotlin.text.String(barcodeBuff, 0, len)
//            Log.e(TAG, "actionRecv: " + barcode)
//            Utils.playSoundOnce()
//
//
//            eventSink?.success(
//                prepareEvent(
//                    Events.EVENT_BARCODE,
//                    barcode
//                )
//            )
//        } else {
//            Log.e(TAG, "actionRecv: 返回数据null")
//        }
    }
}

