package com.zj365.health.act.binddevice

import android.bluetooth.BluetoothAdapter
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import android.util.Log
import android.view.View
import androidx.core.content.ContextCompat
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.LinearLayoutManager
import com.alibaba.android.arouter.facade.annotation.Route
import com.blankj.utilcode.util.CollectionUtils
import com.lifesense.android.ble.core.application.BindReceiver
import com.lifesense.android.ble.core.application.ConnectionStateReceiver
import com.lifesense.android.ble.core.application.model.enums.BindState
import com.lifesense.android.ble.core.application.model.enums.ConnectionState
import com.lifesense.android.ble.core.valueobject.DeviceInfo
import com.tamsiree.rxkit.RxTimeTool
import com.xty.base.act.BaseVmAct
import com.xty.base.vm.BaseVm
import com.xty.common.LogUtils
import com.xty.common.arouter.ARouterUrl
import com.xty.common.arouter.RouteManager
import com.xty.common.bracelet.checkBlueConnectPermission
import com.xty.common.bracelet.getBluePermission
import com.xty.common.util.CommonToastUtils
import com.zj365.health.R
import com.zj365.health.adapter.binddevice.DeviceListAdapter
import com.zj365.health.databinding.ActBodyFatDeviceSearchBinding
import com.zj365.health.model.LSEDeviceInfoApp
import com.zj365.health.weight.DialogTip
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.concurrent.TimeUnit

@Route(path = ARouterUrl.BODY_FAT_DEVICE_SEARCH)
class BodyFatDeviceSearchAct : BaseVmAct<BaseVm>(), ConnectionStateReceiver {

    val binding by lazy { ActBodyFatDeviceSearchBinding.inflate(layoutInflater) }
    private var receiver: BroadcastReceiver? = null
    val deviceListAdapter: DeviceListAdapter by lazy { DeviceListAdapter() }

    private val fiveSecond by lazy { MutableLiveData<String>() }
    private var fiveSecondJob: Job? = null

    private var disposable: Disposable? = null

    private val dialogBind by lazy {
        DialogTip(this, "连接失败，请开启体脂秤，或站上体脂秤。", "知道了", true) {
            disposable?.dispose()
        }
    }

    //倒计时
    private fun startCountdown(initialCount: Int): Observable<Int> {
        return Observable.interval(1, TimeUnit.SECONDS)
            .map { tick -> initialCount - tick.toInt() }
            .take((initialCount + 1).toLong())
            .subscribeOn(Schedulers.io())
    }

    override fun liveObserver() {
        fiveSecond.observe(this) {
            startSearchDevice()
            time()
        }
    }

    override fun setLayout(): View = binding.root
    override fun initView() {
        super.initView()
        statusBar(binding.titleBar.mView)
        binding.titleBar.mIvBack.setOnClickListener { finish() }
        binding.titleBar.mTvTitle.visibility = View.GONE
        binding.titleBar.mTvTitle.text = "搜索设备"

        if (!checkBlueConnectPermission(this)) {
            getBluePermission(this) {
            }
            return
        }

        val builder = SpannableStringBuilder(binding.tvHint.text)
        val redSpan = ForegroundColorSpan(ContextCompat.getColor(this, R.color.col_2621))
        builder.setSpan(redSpan, 0, 5, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
        binding.tvHint.text = builder

        binding.deviceList.apply {
            layoutManager = LinearLayoutManager(this@BodyFatDeviceSearchAct)
            adapter = deviceListAdapter
        }

        deviceListAdapter.addChildClickViewIds(R.id.tvBindButton)
        deviceListAdapter.setOnItemChildClickListener { adapter, view, position ->
            val device = adapter.data[position] as LSEDeviceInfoApp

            bindDevice(device.getLSEDeviceInfo())
        }
        startSearchDevice()
        registerBluetoothStateReceivers()
        if (BlueUtil.getBlueManage().isInitialized) {
            BlueUtil.getBlueManage().registerConnectionStatusReceiver(this)
        }

        time()
    }

    fun time() {
        fiveSecondJob = mainScope.launch(Dispatchers.IO) {
            delay(30000)
            LogUtils.d("休眠结束：${RxTimeTool.curTimeString}")
            fiveSecond.postValue("")
        }
    }

    private fun registerBluetoothStateReceivers() {
        val filter = IntentFilter()
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
        receiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                val action = intent.action
                if (TextUtils.isEmpty(action)) {
                    return
                }
                if (BluetoothAdapter.ACTION_STATE_CHANGED == action) {
                    val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
                    if (!checkBlueConnectPermission(this@BodyFatDeviceSearchAct)) {
                        return
                    }
                    when (state) {
                        BluetoothAdapter.STATE_ON -> startSearchDevice()
                        BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_TURNING_OFF -> {}
                        BluetoothAdapter.STATE_OFF -> {
//                            showEnableBlueToothDialog()
                        }
                    }
                }
            }
        }
        registerReceiver(receiver, filter)
    }

    fun startSearchDevice() {
        if (!checkBlueConnectPermission(this@BodyFatDeviceSearchAct)) {
            return
        }

        if (!BlueUtil.getBlueManage().isInitialized) {
            return
        }
        BlueUtil.getBlueManage().search(5000,
            Consumer { deviceInfo ->
                if (deviceInfo == null) {
                    return@Consumer
                }
                binding.searchLayout.searchLayout.visibility = View.GONE
                binding.titleBar.mTvTitle.visibility = View.VISIBLE
                val info = LSEDeviceInfoApp()
                info.setMacAddress(deviceInfo.mac)
//                lastFindTime = System.currentTimeMillis()
                info.setDeviceName(deviceInfo.deviceName)
                info.setRssi(deviceInfo.rssi)
                info.setLSEDeviceInfo(deviceInfo)
                if (canBeInsertIntoDeviceList(info)) {  //如果没有加入则加入到列表
                    deviceListAdapter.addData(info)
                }
            })
    }

    private fun canBeInsertIntoDeviceList(info: LSEDeviceInfoApp): Boolean {
        var ret = true
        //判断是不是已经加入了list
        for (i in deviceListAdapter.data.indices) {
            if (deviceListAdapter.data[i].getMacAddress()?.toLowerCase()
                    .equals(info.getMacAddress()?.toLowerCase())
            ) {
                ret = false
                break
            }
        }
        return ret
    }

    private fun bindDevice(lseDeviceInfo: DeviceInfo?) {

        mViewModel.loading?.show()
        startCount()

        lseDeviceInfo?.let {
            BlueUtil.getBlueManage().bind(lseDeviceInfo, object : BindReceiver {
                override fun onReceiveRandomNumberRequest() {
//                viewModel.showInputCode(lseDeviceInfoApp)
                }

                override fun onReceiveBindState(bindState: BindState) {
                    mViewModel.loading?.dismiss()
                    disposable?.dispose()
                    if (bindState == BindState.BIND_SUCCESS) {
//                    viewModel.bindSuccess(lseDeviceInfoApp)
                        CommonToastUtils.showSucceedToast("设备连接成功")
                        BlueUtil.getBlueManage().stopSearch()
                        //跳转到填写基础信息界面
                        bundle.clear()
                        bundle.putSerializable("deviceInfo", lseDeviceInfo)
                        RouteManager.goAct(ARouterUrl.BODY_FAT_USER_INFO, bundle)
                        finish()

                    } else if (bindState == BindState.RANDOM_NUMBER_MISS_MATCH) {
//                    viewModel.showInputCode(lseDeviceInfoApp)
                    } else {
                        dialogBind.show()
                        Log.w("bindState", bindState.name)
//                    viewModel.bindFail(lseDeviceInfoApp)
                        BlueUtil.getBlueManage().unBind(it.mac)
                    }
                }

                override fun onReceiveDeviceIdRequest() {
                    BlueUtil.getBlueManage()
                        .inputDeviceId(it.mac, it.mac.replace(":", ""))
                }
            })
        }
    }

    fun startCount() {
        disposable = startCountdown(10)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                { countdown -> println("倒计时: $countdown") },
                { throwable ->
                    disposable?.dispose()
                    throwable.printStackTrace()
                },
                {
                    mViewModel.loading?.dismiss()
                    dialogBind.show()
                    disposable?.dispose()
                    println("倒计时完成")
                }
            )
    }

    override fun onDestroy() {
        super.onDestroy()
        if (BlueUtil.getBlueManage().isInitialized) {
            BlueUtil.getBlueManage().stopSearch()
            BlueUtil.getBlueManage().unRegisterConnectionStatusReceiver(this)
        }

        if (receiver != null) {
            unregisterReceiver(receiver)
        }
        fiveSecondJob?.cancel()
        disposable?.dispose()

    }

    private fun updateDate(devices: MutableList<LSEDeviceInfoApp>) {
        val newData = mutableListOf<LSEDeviceInfoApp>()
        if (CollectionUtils.isNotEmpty(devices)) {
            devices.forEach {
                try {
                    val state = BlueUtil.getBlueManage()
                        .getDeviceConnectState(it.getMacAddress())
                    it.setConnectionState(state)
                    newData.add(it)
                } catch (e: Exception) {
                }
            }
        }
        deviceListAdapter.data.clear()
        deviceListAdapter.addData(newData)
    }

    override fun onConnectionStateChange(p0: String?, p1: ConnectionState?) {
        Log.e("tpppp", "aaaa:" + p1?.name)
        updateDate(deviceListAdapter.data)
    }
}