package com.rdiot.yx485.ui.ctrl

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.drake.net.scope.AndroidScope
import com.drake.net.utils.scopeNetLife
import com.github.gzuliyujiang.wheelpicker.widget.NumberWheelLayout
import com.jaygoo.widget.OnRangeChangedListener
import com.jaygoo.widget.RangeSeekBar
import com.king.view.arcseekbar.ArcSeekBar
import com.king.zxing.util.LogUtils
import com.lindroy.iosdialog.IAlertDialog
import com.rdiot.yx485.R
import com.rdiot.yx485.base.BaseFragment
import com.rdiot.yx485.base.LocalData
import com.rdiot.yx485.base.RoomCtrlViewModelFactory
import com.rdiot.yx485.bean.RoomData
import com.rdiot.yx485.databinding.FraRoomCtrlBinding
import com.rdiot.yx485.net.*
import com.rdiot.yx485.ui.ctrl.model.RoomCtrlViewModel
import com.rdiot.yx485.ui.web.WebActivity
import com.rdiot.yx485.util.*
import com.rdiot.yx485.view.CustomPopupWindow
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay

/**
 * 主控房间控制
 * @author mR2hao
 * @date 2022/11/18
 */
class RoomCtrlFragment : BaseFragment<FraRoomCtrlBinding>(), ClickLimitListener,
    ClickAlphaListener {

    override fun getLayoutId() = R.layout.fra_room_ctrl
    private val viewModel: RoomCtrlViewModel by activityViewModels { RoomCtrlViewModelFactory() }

    private var pollJob: Job? = null
    private var tempScope: AndroidScope? = null

    /** 延迟[OBSERVE_COUNT]次监听结果回复自动换页 */
    private var resumeScrollingCount = -1
    private var mRightTopPlusPop: CustomPopupWindow? = null


    companion object {

        /** 轮询间隔 */
        private const val POLL_REFRESH_TIME = 3

        /** 设置温度偏移量 */
        private const val TEMP_OFFSET = 16

        /** 监听次数 */
        private const val OBSERVE_COUNT = 2

        private const val MAX_TEMP = 30
        private const val MIN_TEMP = 16
    }

    private var level: Int = 0

    @SuppressLint("ClickableViewAccessibility")
    override fun initView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ) {
        binding.hsv.setOnTouchListener { _, motionEvent ->
            when (motionEvent.action) {
                MotionEvent.ACTION_UP,
                MotionEvent.ACTION_DOWN,
                MotionEvent.ACTION_MOVE -> {
                    resumeScrollingCount = 0
                }
            }
            false
        }

        binding.nb.setLeftClickListener { act.finish() }
        binding.nb.setRightClickListener { showDialog() }

        initCtrlViews()

        viewModel.roomData.observe(this) {
            binding.roomData = it
            binding.nb.setTitle(it.name)
            binding.arcSeekBar.progress = it.setTemp - TEMP_OFFSET
            binding.rangeSeekBar.setProgress(it.fanSpeed.toFloat() - 1)
            if (resumeScrollingCount >= OBSERVE_COUNT || resumeScrollingCount == -1) {
                binding.hsv.post { binding.hsv.fullScroll(if (it.mode >= ModeType.SONG_FENG.typeCode) View.FOCUS_RIGHT else View.FOCUS_LEFT) }
            }
            resumeScrollingCount++
        }

        startPoll()
    }

    private fun initCtrlViews() {
        binding.llSwitch.setClickLimitListener(this)
        binding.ivAdd.setClickAlpha(this)
        binding.ivLess.setClickAlpha(this)
        binding.tvCo2.setClickLimitListener(this)
        binding.tvPm25.setClickLimitListener(this)
        binding.tvHomeHumidity2.setClickLimitListener(this)
        binding.tvHomeTemp2.setClickLimitListener(this)
        binding.llZhiRe.setClickLimitListener(this)
        binding.llZhiLeng.setClickLimitListener(this)
        binding.llChuShi.setClickLimitListener(this)
        binding.llSongFeng.setClickLimitListener(this)
        binding.llXinFeng.setClickLimitListener(this)
        binding.llShuiMian.setClickLimitListener(this)
        binding.llJiaShi.setClickLimitListener(this)
        binding.llTimer.setClickLimitListener(this)


        binding.arcSeekBar.setOnChangeListener(object : ArcSeekBar.OnChangeListener {
            override fun onStartTrackingTouch(isCanDrag: Boolean) {
            }

            override fun onProgressChanged(progress: Float, max: Float, fromUser: Boolean) {
                if (fromUser) {
                    LocalData.lastRefreshTime = curTime
                    level = progress.toInt()
                    val data = viewModel.roomData.value ?: return
                    data.setTemp = level + TEMP_OFFSET
                    viewModel.roomData.postValue(data)
                }
            }

            override fun onStopTrackingTouch(isCanDrag: Boolean) {
                if (isCanDrag) {
                    sendTemp(level)
                }
            }

            override fun onSingleTapUp() {
                sendTemp(level)
            }

        })

        //风速
        binding.rangeSeekBar.setOnRangeChangedListener(object : OnRangeChangedListener {
            override fun onRangeChanged(
                view: RangeSeekBar?,
                leftValue: Float,
                rightValue: Float,
                isFromUser: Boolean
            ) {
            }

            override fun onStartTrackingTouch(view: RangeSeekBar?, isLeft: Boolean) {
            }

            override fun onStopTrackingTouch(view: RangeSeekBar?, isLeft: Boolean) {
                val data = viewModel.roomData.value ?: return
                val windSpeed = (view?.leftSeekBar?.progress!! + 1).toInt()
                scopeNetLife {
                    setWindSpeed(
                        LocalData.familyData.value?.gateway ?: "",
                        data,
                        windSpeed,
                        RoomUtils.isMaster(viewModel.roomData.value?.code)
//                        viewModel.roomData.value!!.isMaster
                    ).await()
                }
                LogUtils.d("设置风速:$windSpeed")
            }

        })
    }

    private fun sendTemp(level: Int) {

        val data = viewModel.roomData.value ?: return
        data.setTemp = this.level + TEMP_OFFSET
        LogUtils.d("设置温度:${level + TEMP_OFFSET}")

        scopeNetLife {
            setTemp(
                LocalData.familyData.value?.gateway ?: "",
                data,
                (level + TEMP_OFFSET)
            ).await()
        }
        viewModel.roomData.postValue(data)

    }

    override fun onClickLimit(view: View) {
        viewClicked(view)
    }

    override fun onClickAlpha(view: View) {
        viewClicked(view)
    }

    private fun viewClicked(view: View) {
        val data = viewModel.roomData.value ?: return
        when (view) {
            binding.llSwitch -> {   //总开关
                data.power = !data.power
                scopeNetLife {
                    setPower(LocalData.familyData.value?.gateway ?: "", data).await()
                }
            }


            binding.ivAdd,
            binding.ivLess -> {
                if (view == binding.ivAdd) {
                    if (data.setTemp < MAX_TEMP) {
                        data.setTemp += 1
                    }
                } else {
                    if (data.setTemp > MIN_TEMP) {
                        data.setTemp -= 1
                    }
                }
                LogUtils.d("设置温度:${data.setTemp}")
                //防止连点 取消上一次请求
                tempScope?.cancel()
                tempScope = scopeNetLife {
                    delay(300)
                    setTemp(
                        LocalData.familyData.value?.gateway ?: "", data, (data.setTemp)
                    ).await()
                }

            }

            binding.tvCo2 -> {
                goDataChart("二氧化碳","co2")
            }

            binding.tvPm25 -> {
                goDataChart("PM2.5","pm25")
            }

            binding.tvHomeHumidity2 -> {
                goDataChart("湿度", "humidity")
            }

            binding.tvHomeTemp2 -> {
                goDataChart("温度","temp")
            }

            binding.llTimer -> {
                if (data.timerStatus) {
                    data.timerStatus = false
                    scopeNetLife {
                        setTimer(
                            LocalData.familyData.value?.gateway ?: "",
                            data,
                            data.timerStatus,
                            0f
                        ).await()
                        viewModel.roomData.postValue(data)
                        LocalData.lastRefreshTime = curTime
                    }
                } else {
                    showTimerPicker(data)
                }
            }

            binding.llXinFeng -> {
                data.freshAir = !data.freshAir
                scopeNetLife {
                    setFreshAir(LocalData.familyData.value?.gateway ?: "", data).await()
                }
            }

            binding.llShuiMian -> {
                data.sleepMode = !data.sleepMode
                scopeNetLife {
                    setSleep(LocalData.familyData.value?.gateway ?: "", data).await()
                }
            }

            else -> {
                val modeType = when (view) {
                    binding.llZhiLeng -> ModeType.ZHI_LENG
                    binding.llZhiRe -> ModeType.ZHI_RE
                    binding.llChuShi -> ModeType.CHU_SHI
                    binding.llSongFeng -> ModeType.SONG_FENG
                    binding.llJiaShi -> ModeType.JIA_SHI
                    else -> {
                        ModeType.ZHI_LENG
                    }
                }
                data.power = true
                data.mode = modeType.typeCode
                scopeNetLife {
                    setMode(LocalData.familyData.value?.gateway ?: "", data, modeType).await()
                }
            }
        }
        viewModel.roomData.postValue(data)
        LocalData.lastRefreshTime = curTime
    }


    private fun showTimerPicker(data: RoomData) {
        var optionWheelLayout: NumberWheelLayout? = null
        IAlertDialog
            .build(this)
            .setTitle(R.string.timed_off)
            .setContentView(R.layout.dialog_timer)
            .setCancelOutside(false)
            .setNegButtonText(R.string.cancel)
            .setNegButtonTextColor(resources.getColor(R.color.main_text_color, null))
            .setNegClickListener { dialogInterface ->
                dialogInterface.dismiss()
            }
            .setPosClickListener { dialogInterface ->
                data.duration = optionWheelLayout?.wheelView?.getCurrentItem<Float>() ?: 0.5f
                data.timerStatus = true
                scopeNetLife {
                    setTimer(
                        LocalData.familyData.value?.gateway ?: "",
                        data,
                        data.timerStatus,
                        data.duration
                    ).await()
                }
                viewModel.roomData.postValue(data)
                LocalData.lastRefreshTime = curTime
                dialogInterface.dismiss()
                LogUtils.d("设置定时:${data.duration}")
            }
            .setDismissible(false)
            .setAlpha(1.0F)
            .setPosButtonTextColor(resources.getColor(R.color.btn_blue, null))
            .setOnViewHandler { holder, _ ->
                optionWheelLayout = holder.getView(R.id.wheel_option)
                optionWheelLayout?.labelView?.textSize = 16.0f
                optionWheelLayout?.labelView?.setTextColor(act.getColor(R.color.login_btn_color))
//                wheelView?.setDefaultValue(duration)

            }.show()
    }

    /** 开始轮询  最低 [POLL_REFRESH_TIME] 间隔*/
    private fun startPoll() {
        if (pollJob == null) {
            var scope: AndroidScope? = null
            pollJob = lifecycleScope.launchWhenResumed {
                while (!act.isFinishing) {
                    val last = LocalData.lastRefreshTime
                    val less = (POLL_REFRESH_TIME - (curTime - last) / 1000).coerceAtLeast(0)
                    if (less == 0L) {
                        scope?.cancel() // 如果存在则取消
                        scope = scopeNetLife {

                            scopeNetLife {
                                viewModel.roomData.value?.recordId?.let {
                                    val data = getRoomInfo(it).await()
                                    viewModel.roomData.postValue(data)
                                }
                            }
                            LocalData.lastRefreshTime = curTime
                        }
                    }
                    delay(1000)
                }
            }
        }
    }

    private fun showDialog() {
        if (mRightTopPlusPop == null) {
            mRightTopPlusPop =
                CustomPopupWindow(act, R.layout.room_ctrl_popup, CustomPopupWindow.TYPE_FULL_SCREEN)
        }
        mRightTopPlusPop?.showAtLocation(view, Gravity.END or Gravity.TOP, 0, 0)

        mRightTopPlusPop?.contentView?.findViewById<View>(R.id.tv_device_info)
            ?.setClickLimitListener {
                closeRightTopPop()
                act.clearGoTo(
                    WebActivity.getNewWebIntent(
                        act,
                        "https://app.yongxulvjian.com/#/DeviceInfo/${viewModel.roomData.value?.recordId ?: ""}",
                        "设备信息"
                    )
                )
            }

        mRightTopPlusPop?.contentView?.findViewById<View>(R.id.tv_edit_name)
            ?.setClickLimitListener {
                closeRightTopPop()
                findNavController().navigate(R.id.action_roomCtrlFragment_to_roomSettingFragment)
            }
    }

    private fun closeRightTopPop() {
        if (mRightTopPlusPop?.isShowing == true) {
            mRightTopPlusPop?.dismiss()
        }
    }

    private fun goDataChart(typeName: String, type: String) {
        act.clearGoTo(
            WebActivity.getNewWebIntent(
                act,
                "https://app.yongxulvjian.com/#/DataChart/${viewModel.roomData.value?.recordId}/${type}",
                typeName
            )
        )
    }
}