package com.develop.step

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.activity.viewModels
import androidx.recyclerview.widget.LinearSnapHelper
import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.develop.food.base.adapter.CookTimeAdapter
import com.develop.food.base.data.model.CookSettingType
import com.develop.food.base.router.Screens
import com.develop.food.base.ui.BaseActivity
import com.develop.food.base.utils.TimeUtil
import com.develop.food.base.utils.setGone
import com.develop.food.base.utils.setVisible
import com.develop.food.base.widgets.LinearPositionObserver
import com.develop.step.databinding.ActivityFoodStepBinding
import com.develop.step.viewmodel.CookStepViewModel
import com.develop.step.widgets.NoteEditDialog
import com.develop.step.widgets.RingControlView
import com.kuyuntech.cofarcooking.device.sdk.constant.core.DevStatus
import com.kuyuntech.cofarcooking.device.sdk.eventbus.event.DevStatusEvent
import com.kuyuntech.cofarcooking.device.sdk.util.core.CofarSDK
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

@Route(path = Screens.Cook.COOK_STEP)
class CookStepActivity: BaseActivity<ActivityFoodStepBinding>() {

    /**
     * 使用[CookSettingType.name]把步骤传过来
     */
    @JvmField
    @Autowired(name = "cook_step")
    var requireCookStep: String? = null
    private val viewModel by viewModels<CookStepViewModel>()
    private var firstTimePos = 0
    private var secondTimePos = 0
    private var timeArray = IntArray(3)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ARouter.getInstance().inject(this)
//        EventBus.getDefault().register(this)
        binding.tvTitleStep.setOnClickListener {
            showCookDetailDialog()
        }
        binding.tvStepName.setOnClickListener {
            showCookDetailDialog()
        }
        binding.viewRemark.setOnClickListener {
            NoteEditDialog().showDialog(supportFragmentManager, "NoteEditDialog")
        }
        binding.ivNextStep.setOnClickListener {
            viewModel.nextStep()
        }
        binding.ivPrevStep.setOnClickListener {
            viewModel.prevStep()
        }
        binding.controller.clCookTemp.setOnClickListener {
            viewModel.changeStep(CookSettingType.TEMP_SETTING)
        }
        binding.controller.clCookTime.setOnClickListener {
            viewModel.changeStep(CookSettingType.TIME_SETTING)
        }
        binding.controller.clCookSpeed.setOnClickListener {
            viewModel.changeStep(CookSettingType.SPEED_SETTING)
        }
        binding.controller.clCookDirection.setOnClickListener {
            viewModel.changeStep(CookSettingType.DIRECTION_SETTING)
        }
        binding.viewBack.setOnClickListener {
            finish()
        }
        binding.controller.btnStart.setOnClickListener {
            if (viewModel.stepUiData.doingModify) {
                viewModel.stepUiData.doingModify = false
                refreshRunningUi(false)
                return@setOnClickListener
            }
            if (viewModel.stepUiData.runningStatus == DevStatus.RUNNING.toInt()) {
                CofarSDK.pause()
            } else {
                if (viewModel.stepUiData.runningStatus == DevStatus.STOP.toInt()) {
                    CofarSDK.start("")
                }else {
                    CofarSDK.resume()
                }
            }
        }
        binding.controller.btnReset.setOnClickListener {
            if (viewModel.stepUiData.doingModify) {
                viewModel.stepUiData.doingModify = false
                refreshRunningUi(false)
                return@setOnClickListener
            }
        }
        binding.tvWeightTare.setOnClickListener {
            CofarSDK.startWeight()
        }
        binding.controller.apply {
            tempRingView.setRange(0f, 100f)
            tempRingView.updateProgress(80)
            tempRingView.onRingViewListener = object : RingControlView.OnRingViewListener {
                @SuppressLint("SetTextI18n")
                override fun onProgressChange(progress: Int) {
                    tvTempValue.text = "${progress}°C"
                    tvRingText.text  = "${progress}°C"
                    viewModel.tempStatus.settingTemp = progress
                    viewModel.stepUiData.doingModify = true
                    refreshRunningUi(true)
                }
            }
            speedRingView.setRange(0f, 10f)
            speedRingView.updateProgress(2)
            speedRingView.onRingViewListener = object : RingControlView.OnRingViewListener {
                override fun onProgressChange(progress: Int) {
                    tvSpeedText.text = "$progress"
                    tvSetSpeed.text  = "$progress"
                    viewModel.speedStatus.settingSpeed = progress
                    viewModel.stepUiData.doingModify = true
                    refreshRunningUi(true)
                }
            }
        }
        configureTimeSetting()
        configureDirection()
        initData()
    }

    private fun initData() {
        viewModel.currentSetting.observe(this) {
            if (it == null) {
                return@observe
            }
            when (it) {
                CookSettingType.WEIGHT -> {
                    changeWeightStep()
                }
                CookSettingType.TEMP_SETTING -> {
                    changeTempSettingStep()
                }
                CookSettingType.TIME_SETTING -> {
                    changeTimeSettingStep()
                }
                CookSettingType.SPEED_SETTING -> {
                    changeSpeedSettingStep()
                }
                CookSettingType.DIRECTION_SETTING -> {
                    changeDirectionSettingStep()
                }
            }
        }
        if (requireCookStep != null) {
            viewModel.changeStep(CookSettingType.valueOf(requireCookStep!!))
        }
    }

    /**
     * 这里直接监听turn left / right事件
     */
    private fun configureDirection() {
        binding.controller.tvTurnRight.setOnClickListener {
            binding.controller.ivDirection.rotation = 0f
            binding.controller.tvTurnRight.setTextColor(0xffE60012.toInt())
            binding.controller.tvTurnLeft.setTextColor(0xffE5E5E5.toInt())
            binding.controller.tvSetDirection.text = "TURN\nRIGHT"
            viewModel.directionStatus.settingValue = 1
        }
        binding.controller.tvTurnLeft.setOnClickListener {
            binding.controller.ivDirection.rotation = 180f
            binding.controller.tvTurnRight.setTextColor(0xffE5E5E5.toInt())
            binding.controller.tvTurnLeft.setTextColor(0xffE60012.toInt())
            binding.controller.tvSetDirection.text = "TURN\nLEFT"
            viewModel.directionStatus.settingValue = 0
        }
    }

    @SuppressLint("SetTextI18n")
    private fun refreshRunningUi(onlyUpdateButton: Boolean) {
        val uiData = viewModel.stepUiData
        if (uiData.doingModify) {
            binding.controller.btnStart.setVisible()
            binding.controller.btnReset.setVisible()
            binding.controller.btnStart.setText(R.string.confirm)
            binding.controller.btnReset.setText(R.string.cancel)
        }else {
            if (uiData.runningStatus == DevStatus.STOP.toInt()) {
                binding.controller.btnStart.setVisible()
                binding.controller.btnReset.setVisible()
                binding.controller.btnStart.setText(R.string.start)
                binding.controller.btnReset.text = "RESET"
            }else if (uiData.runningStatus == DevStatus.RUNNING.toInt()) {
                binding.controller.btnStart.setVisible()
                binding.controller.btnReset.setGone()
                binding.controller.btnStart.setText(R.string.pause)
            }else {
                binding.controller.btnStart.setVisible()
                binding.controller.btnReset.setVisible()
                binding.controller.btnStart.setText(R.string.resume)
                binding.controller.btnReset.setText(R.string.stop)
            }
        }
        if (onlyUpdateButton) {
            return
        }
        binding.tvWeightNum.text = uiData.weightNum.toString()
        if (uiData.runningStatus == DevStatus.STOP.toInt()) {
            TimeUtil.getTimes(uiData.targetTime, timeArray)
            binding.controller.tvCookingTempTarget.setGone()
            binding.controller.tvCookingTimeTarget.setGone()
            binding.controller.tvTempValue.text = "${uiData.targetTemp}°C"
            setTimeInternal(timeArray[0], timeArray[1], timeArray[2], true)
        }else {
            TimeUtil.getTimes(uiData.targetTime, timeArray)
            binding.controller.tvCookingTempTarget.setVisible()
            binding.controller.tvCookingTimeTarget.setVisible()
            binding.controller.tvCookingTempTarget.text = "${uiData.targetTemp}°C"
            binding.controller.tvCookingTimeTarget.text = "--${TimeUtil.formatTime(timeArray)}--"
            binding.controller.tvTempValue.text = "${uiData.currentTemp}°C"
            binding.controller.tvRingText.text = ">  ${uiData.currentTemp}°C  <"
            binding.controller.tvRingTextCooking.text = "${uiData.targetTemp}°C"
            if (binding.controller.tvRingText.visibility == View.VISIBLE) {
                binding.controller.tvRingTextCooking.setVisible()
            }
            TimeUtil.getTimes(uiData.currentTime, timeArray)
            setTimeInternal(timeArray[0], timeArray[1], timeArray[2], true)
        }
    }

    private fun configureTimeSetting() {
        binding.controller.let {
            val firstData = mutableListOf<String>()
            val secondData = mutableListOf<String>()
            repeat(60) { idx ->
                if (idx < 10) {
                    firstData.add("0$idx")
                    secondData.add("0$idx")
                }else {
                    firstData.add(idx.toString())
                    secondData.add(idx.toString())
                }
            }
            repeat(9) { idx ->
                if (idx == 0) {
                    return@repeat
                }
                if (idx < 10) {
                    firstData.add("0$idx")
                }else {
                    firstData.add(idx.toString())
                }
            }
            val firstAdapter = CookTimeAdapter(firstData)
            val secondAdapter = CookTimeAdapter(secondData)
            it.tvSetTimeFirst.adapter = firstAdapter
            it.tvSetTimeSecond.adapter = secondAdapter
            it.tvSetTimeFirst.addOnScrollListener(LinearPositionObserver { pos ->
                firstTimePos = pos
                checkChangeTimeScale(pos)
                updateDisplayTime()
            })
            it.tvSetTimeSecond.addOnScrollListener(LinearPositionObserver { pos ->
                secondTimePos = pos
                updateDisplayTime()
            })
            LinearSnapHelper().attachToRecyclerView(it.tvSetTimeFirst)
            LinearSnapHelper().attachToRecyclerView(it.tvSetTimeSecond)
        }
    }

    private fun checkChangeTimeScale(firstPos: Int) {
        val firstUnit: String
        val secondUnit: String
        if (firstPos >= 60) {
            firstUnit = "hour"
            secondUnit = "min"
        }else {
            firstUnit = "min"
            secondUnit = "sec"
        }
        if (firstUnit != binding.controller.tvFirstBottom.text) {
            binding.controller.tvFirstBottom.text = firstUnit
        }
        if (secondUnit != binding.controller.tvSecondBottom.text) {
            binding.controller.tvSecondBottom.text = secondUnit
        }
    }

    private fun updateDisplayTime() {
        if (firstTimePos >= 60) {
            setTimeInternal(
                firstTimePos - 60 + 1,
                secondTimePos,
                0,
                false
            )
        }else {
            setTimeInternal(
                0,
                firstTimePos,
                secondTimePos,
                false
            )
        }
    }

    @SuppressLint("SetTextI18n")
    private fun setTimeInternal(
        hours: Int,
        minute: Int,
        second: Int,
        changeSetting: Boolean
    ) {
        val firstTime: Int
        val secondTime: Int
        if (hours > 0) {
            firstTime = hours
            secondTime = minute
        }else {
            firstTime = minute
            secondTime = second
        }
        binding.controller.let {
            if (changeSetting) {
                if (hours > 0) {
                    it.tvSetTimeFirst.scrollToPosition(59 + firstTime)
                    it.tvSetTimeSecond.scrollToPosition(secondTime)
                }else {
                    it.tvSetTimeFirst.scrollToPosition(firstTime)
                    it.tvSetTimeSecond.scrollToPosition(secondTime)
                }
            }
            val firstStr = if (firstTime < 10) {
                "0$firstTime"
            } else {
                firstTime.toString()
            }
            val secondStr = if (secondTime < 10) {
                "0$secondTime"
            } else {
                secondTime.toString()
            }
            it.tvSetTime.text = "${firstStr}:${secondStr}"
        }
        viewModel.timeStatus.let {
            it.settingHours = hours
            it.settingMinutes = minute
            it.settingSeconds = second
        }
    }

    private fun changeWeightStep() {
        binding.controller.root.visibility = View.GONE
        binding.llWeightView.visibility = View.VISIBLE
    }

    private fun changeTempSettingStep() {
        binding.llWeightView.visibility = View.GONE
        binding.controller.root.visibility = View.VISIBLE
        binding.controller.tempRingView.visibility = View.VISIBLE
        binding.controller.tvRingText.visibility = View.VISIBLE
        binding.controller.speedRingView.visibility = View.GONE
        binding.controller.tvSpeedText.visibility = View.GONE
        binding.controller.tvRingTextCooking.visibility = View.GONE
        binding.controller.clSetTime.visibility = View.GONE
        binding.controller.flDirection.visibility = View.GONE
        if (viewModel.stepUiData.runningStatus != DevStatus.STOP.toInt()) {
            binding.controller.tvRingTextCooking.setVisible()
        }
        setPanelViewProperty(CookSettingType.TEMP_SETTING)
    }

    private fun changeTimeSettingStep() {
        binding.llWeightView.visibility = View.GONE
        binding.controller.root.visibility = View.VISIBLE
        binding.controller.tempRingView.visibility = View.INVISIBLE
        binding.controller.tvRingText.visibility = View.GONE
        binding.controller.speedRingView.visibility = View.GONE
        binding.controller.tvSpeedText.visibility = View.GONE
        binding.controller.tvRingTextCooking.visibility = View.GONE
        binding.controller.clSetTime.visibility = View.VISIBLE
        binding.controller.flDirection.visibility = View.GONE
        if (viewModel.stepUiData.runningStatus != DevStatus.STOP.toInt()) {
            binding.controller.tvRingTextCooking.setVisible()
        }
        setPanelViewProperty(CookSettingType.TIME_SETTING)
    }

    private fun changeSpeedSettingStep() {
        binding.llWeightView.visibility = View.GONE
        binding.controller.root.visibility = View.VISIBLE
        binding.controller.tempRingView.visibility = View.INVISIBLE
        binding.controller.tvRingText.visibility = View.GONE
        binding.controller.speedRingView.visibility = View.VISIBLE
        binding.controller.tvSpeedText.visibility = View.VISIBLE
        binding.controller.tvRingTextCooking.visibility = View.GONE
        binding.controller.clSetTime.visibility = View.GONE
        binding.controller.flDirection.visibility = View.GONE
        setPanelViewProperty(CookSettingType.SPEED_SETTING)
    }

    private fun changeDirectionSettingStep() {
        binding.llWeightView.visibility = View.GONE
        binding.controller.root.visibility = View.VISIBLE
        binding.controller.tempRingView.visibility = View.INVISIBLE
        binding.controller.tvRingText.visibility = View.GONE
        binding.controller.speedRingView.visibility = View.GONE
        binding.controller.tvSpeedText.visibility = View.GONE
        binding.controller.tvRingTextCooking.visibility = View.GONE
        binding.controller.clSetTime.visibility = View.GONE
        binding.controller.flDirection.visibility = View.VISIBLE
        setPanelViewProperty(CookSettingType.DIRECTION_SETTING)
    }

    private fun setPanelViewProperty(selectStep: CookSettingType) {
        binding.controller.apply {
            viewSelectTemp.visibility = View.INVISIBLE
            viewSelectTime.visibility = View.INVISIBLE
            viewSelectSpeed.visibility = View.INVISIBLE
            viewSelectDirection.visibility = View.INVISIBLE
            tvTempValue.isSelected = false
            tvTitleTemp.isSelected = false
            tvSetTime.isSelected = false
            tvTitleTime.isSelected = false
            tvSetSpeed.isSelected = false
            tvTitleSpeed.isSelected = false
            tvSetDirection.isSelected = false
            tvTitleDirection.isSelected = false
            viewBackgroundTemp.isSelected = false
            viewBackgroundTime.isSelected = false
            viewBackgroundSpeed.isSelected = false
            viewBackgroundDirection.isSelected = false
            viewIconTemp.isSelected = false
            viewIconTime.isSelected = false
            viewIconSpeed.isSelected = false
            viewIconDirection.isSelected = false
            when (selectStep) {
                CookSettingType.TEMP_SETTING -> {
                    viewSelectTemp.visibility = View.VISIBLE
                    tvTempValue.isSelected = true
                    tvTitleTemp.isSelected = true
                    viewBackgroundTemp.isSelected = true
                    viewIconTemp.isSelected = true
                }
                CookSettingType.TIME_SETTING -> {
                    viewSelectTime.visibility = View.VISIBLE
                    tvSetTime.isSelected = true
                    tvTitleTime.isSelected = true
                    viewBackgroundTime.isSelected = true
                    viewIconTime.isSelected = true
                }
                CookSettingType.SPEED_SETTING -> {
                    viewSelectSpeed.visibility = View.VISIBLE
                    tvSetSpeed.isSelected = true
                    tvTitleSpeed.isSelected = true
                    viewBackgroundSpeed.isSelected = true
                    viewIconSpeed.isSelected = true
                }
                CookSettingType.DIRECTION_SETTING -> {
                    viewSelectDirection.visibility = View.VISIBLE
                    tvSetDirection.isSelected = true
                    tvTitleDirection.isSelected = true
                    viewBackgroundDirection.isSelected = true
                    viewIconDirection.isSelected = true
                }
                CookSettingType.WEIGHT -> {
                    // do nothing
                }
            }
        }
    }

    private fun showCookDetailDialog() {
        val dialogView = layoutInflater.inflate(
            R.layout.item_cook_details, binding.flCookDetails, true
        )
        val textView = dialogView.findViewById<TextView>(R.id.tv_details)
        textView.append("Step1：Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderjug.")
        textView.append("\n\n")
        textView.append("Step2：Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderStep1:Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderjug.juep1:Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderjug.")
        textView.append("\n\n")
        textView.append("Step3：Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderjug.")
        textView.append("\n\n")
        textView.append("Step4：Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderStep1:Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderjug.juep1:Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderjug.")
        textView.append("\n\n")
        textView.append("Step5：Peel 3 onions(180g)and2 garlic cloves halve the onions andput both in the blenderjug.")
        val closeView = dialogView.findViewById<View>(R.id.iv_close)
        closeView.setOnClickListener {
            binding.flCookDetails.removeAllViews()
        }
    }

    override fun createViewBinding(inflater: LayoutInflater): ActivityFoodStepBinding {
        return ActivityFoodStepBinding.inflate(inflater)
    }

    override fun onDestroy() {
        super.onDestroy()
//        EventBus.getDefault().unregister(this)
    }

    @SuppressLint("SetTextI18n")
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onDevStatusEvent(event: DevStatusEvent) {
        val devInfo = event.devInfo!!
        devInfo.let {
            val format = if (it.targetTime.toLong() > 60 * 60 - 1) {
                "HH:mm"
            } else {
                "mm:ss"
            }
            viewModel.stepUiData.runningStatus = event.devInfo.status
            viewModel.stepUiData.currentTime = devInfo.remainTime.toInt()
            viewModel.stepUiData.currentTemp = devInfo.targetTemp.toInt()
            viewModel.stepUiData.targetTemp = it.temp.toInt()
            viewModel.stepUiData.targetTime = it.targetTime.toInt()
            viewModel.stepUiData.weightNum = it.weight.toInt()
            refreshRunningUi(false)
        }
    }
}