package com.zj365.health.fragment

import com.xty.network.model.*
import android.annotation.SuppressLint
import android.graphics.Color
import android.graphics.DashPathEffect
import android.graphics.Matrix
import android.graphics.Typeface
import android.os.Build
import android.os.Bundle
import android.text.SpannableString
import android.text.Spanned
import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.text.isDigitsOnly
import androidx.fragment.app.Fragment
import com.bigkoo.pickerview.adapter.ArrayWheelAdapter
import com.blankj.utilcode.util.TimeUtils
import com.contrarywind.view.WheelView
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.components.YAxis
import com.github.mikephil.charting.data.BarData
import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.IFillFormatter
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tamsiree.rxkit.RxTimeTool
import com.xty.base.fragment.BaseVmFrag
import com.xty.base.utils.OrganStatusCalcUtil
import com.xty.common.Const
import com.xty.common.LogUtils
import com.xty.common.TimeSelect
import com.xty.common.arouter.ARouterUrl
import com.xty.common.arouter.RouteManager
import com.xty.common.weight.tablayout.TabEntity
import com.xty.common.weight.tablayout.listener.CustomTabEntity
import com.xty.common.weight.tablayout.listener.OnTabSelectListener
import com.zj365.health.R
import com.zj365.health.act.HealthMainAct
import com.zj365.health.act.exception.BaseExceptionDataAct
import com.zj365.health.databinding.FragXlBinding
import com.zj365.health.vm.XlVm
import com.zj365.health.weight.HealthDialog
import com.zj365.health.weight.IMarkView
import com.xty.network.model.XlBean
import java.lang.Float.max
import java.lang.Float.min
import java.text.SimpleDateFormat
import java.util.*

/**
 * 心率
 */
class XinlvFrag : BaseVmFrag<XlVm>() {

    val binding by lazy { FragXlBinding.inflate(layoutInflater) }
    override fun setLayout(): View = binding.root
    override fun setViewModel() = XlVm()

    private var isDemonstrate: Boolean = false
    var type = 1
    val fomartStr by lazy { arrayOf("HH:mm", "HH:mm", "MM-dd", "MM-dd", "yy-MM") }
    private val weekStr by lazy { resources.getStringArray(R.array.week_day) }
    private val icons = arrayOf(
        R.mipmap.shuzhuangtu,
        R.mipmap.ic_shuzhuangtu_yixuan,
        R.mipmap.ic_zhexiant,
        R.mipmap.zhexiant_yixuan
    )

    val timeSelect by lazy {
        TimeSelect(requireContext()) {
            type = 1
            dayDate = binding.tvShowDate.text.toString()
            mViewModel.getXlData(type, binding.tvShowDate.text.toString(), id, isDemonstrate)
        }
    }

    val timeMonthSelect by lazy {
        TimeSelect(requireContext()) {
            type = 3
            mouthDate = binding.tvShowDate.text.toString()
            mViewModel.getXlData(type, binding.tvShowDate.text.toString(), id, isDemonstrate)

        }
    }
    val timeYearSelect by lazy {
        TimeSelect(requireContext()) {
            type = 4
            yearDate = binding.tvShowDate.text.toString()
            mViewModel.getXlData(type, binding.tvShowDate.text.toString(), id, isDemonstrate)
        }
    }

    var tip =
        "人的心率在非静息状态下会不断变化，属正常情况！同时，不同心率监测设备采集心率的方法和算法有所不同，同一时间通过不同心率监测装置出现心率数据偏差亦属正常现象。中健三六五心率变异算法会将采集的心率整体变化趋势与不同状态下的正常心率模型对比，请您及时关注心率变化。"
    val tipDialog by lazy {
        HealthDialog(requireContext(), true, tip) {
        }
    }
    var lineValue = arrayListOf<Entry>()  //曲线数据
    var barValue = arrayListOf<BarEntry>()  //柱状数据
    var id = ""

    override fun initData() {
        super.initData()
        id = arguments?.getString("id").toString()
    }

    override fun initView() {
        super.initView()
        initTab()
        initTimeSelect()
        binding.mOrganView.ivSecond.setOnClickListener {
            if (isDemonstrate) {
                (requireActivity() as HealthMainAct).dialogBind.show()
                return@setOnClickListener
            }
            val text = binding.mOrganView.tvSecondName.text.toString()
            bundle.clear()
            bundle.putString(BaseExceptionDataAct.exceptionKey, text)
            bundle.putStringArrayList(BaseExceptionDataAct.exceptionList, highList)
            bundle.putStringArrayList(BaseExceptionDataAct.exceptionListTime, highListTime)
            moveToErrorShow(bundle)
        }

        binding.mOrganView.ivThree.setOnClickListener {
            val text = binding.mOrganView.tvThreeName.text.toString()
            bundle.clear()
            bundle.putString(BaseExceptionDataAct.exceptionKey, text)
            bundle.putStringArrayList(BaseExceptionDataAct.exceptionList, lowList)
            bundle.putStringArrayList(BaseExceptionDataAct.exceptionListTime, lowListTime)
            moveToErrorShow(bundle)
        }
        binding.mLineChart.setNoDataText(getString(R.string.line_chart_not_data))
        binding.mLineChart.setNoDataTextColor(
            ContextCompat.getColor(
                requireContext(),
                R.color.col_455
            )
        )
        binding.compareTv.setOnClickListener {
            if (isDemonstrate) {
                (requireActivity() as HealthMainAct).dialogBind.show()
                return@setOnClickListener
            }
            bundle.clear()
            bundle.putString("id", id)
            bundle.putString("type", "1")//1 心率
            RouteManager.goAct(ARouterUrl.COMPARE_DATA_ACT, bundle)
        }
        binding.zhexianTv.setOnClickListener {
            binding.mLineChart.visibility = View.VISIBLE
            binding.mBarChart.visibility = View.GONE
            binding.zhuzhuanTv.setImageResource(icons[0])
            binding.zhexianTv.setImageResource(icons[3])
        }
        binding.zhuzhuanTv.setOnClickListener {
            binding.mLineChart.visibility = View.GONE
            binding.mBarChart.visibility = View.VISIBLE
            binding.zhuzhuanTv.setImageResource(icons[1])
            binding.zhexianTv.setImageResource(icons[2])
        }
        binding.mTip.setOnClickListener {
            tipDialog.show()
        }
        binding.mGroup.setOnCheckedChangeListener { group, checkedId ->
            when (checkedId) {
                R.id.mDay -> {
                    binding.mTvTime.visibility = View.VISIBLE
                    var selTime = binding.mTvTime.text.toString()
                    val date2String = RxTimeTool.date2String(Date(), SimpleDateFormat("yyyy-MM-dd"))
                    type = 1
                }

                R.id.mWeek -> {
                    binding.mTvTime.visibility = View.GONE
                    type = 2
                }

                R.id.mMonth -> {
                    binding.mTvTime.visibility = View.GONE
                    type = 3
                }

                R.id.mYear -> {
                    binding.mTvTime.visibility = View.GONE
                    type = 4
                }
            }
            setAvgInfo(null)
            if (type < 2) {
                mViewModel.getXlData(type, binding.mTvTime.text.toString(), id, isDemonstrate)
            } else {
                mViewModel.getXlData(type, null, id, isDemonstrate)
            }

        }
        isDemonstrate = (requireActivity() as HealthMainAct).isDemonstrate
        if (isDemonstrate) {
            binding.tvXinLv.text = "84"
            binding.tvTestTime.text = RxTimeTool.getCurTimeString(
                SimpleDateFormat("HH:mm")
            )
        }
        mViewModel.getXlData(
            type,
            RxTimeTool.getCurTimeString(SimpleDateFormat("yyyy-MM-dd")),
            id,
            isDemonstrate
        )
        mViewModel.getSetting(Const.Xl_SETTING)
        mViewModel.getLastData(id)
//        binding.mTvTime.text = RxTimeTool.getCurTimeString(SimpleDateFormat("yyyy-MM-dd"))
//        binding.mTvTime.setOnClickListener {
//
//
//
//        }


        binding.tvTips.text ="了解心率：\n心率是指人体心脏每分钟搏动的次数，为人的基本生命体征之一；成年人安静状态下的心率一般为50-100次每分钟，" +
                "其通常会因年龄、性别或其他生理因素产生个体差异。运动时心跳会加速，心肺功能较好的运动员心率通常会比普通成年人的心跳要慢。\n\n" +
                "心率过速：\n成年人在安静、清醒的情况下心率达到100次/分钟，婴幼儿150次/分就称为心率过速。\n\n" +
                "心率过缓：\n成年人在安静、清醒的情况下心率低于50次/分钟；\n\n" +
                "如心率偏高，什么情况下建议及时就医?\n" +
                "当心率超过正常值范围时(成人在安静、清醒的情况下正常心率范围为50~100次/分)。尤其是伴有症状时，如:心慌气短，" +
                "头晕、黑朦等，建议到医院就诊。首先，建议您到就近的社区医院就诊，完善心电图等基本检查，排查常见病。不能确诊或者需要进一步诊疗时，可以到上级医院或专科医院就诊。\n" +
                "\n\n\n" +
                "测量结果仅供参考，不作为医疗诊断依据。"

    }

    private fun moveToErrorShow(bundle: Bundle) {
        RouteManager.goAct(ARouterUrl.XINLV_EXCEPTION_DATA_ACT, bundle)
    }


    override fun observer() {
        mViewModel.dataLive.observe(this) {
            if (it == null || it[type] == null) {
                return@observe
            }
            // 这里把日的原始数据暂存起来，跳转异常页面时使用
            val daysModelList: MutableList<XlBean.Model> = it[type]!!.model
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                when (type) {
                    1 -> {//日
                        it[type]!!.model = it[type]!!.mapDataToTimeNodes(it[type]!!.model)
                    }

                    2 -> {//周
                        val split = binding.tvShowDate.text.toString().split("至")
                        val start = split[0]
                        val end = split[1]
                        it[type]!!.model = it[type]!!.fillMissingData(it[type]!!.model, start, end)
                    }

                    3 -> {//月
                        it[type]!!.model = it[type]!!.fillMissingData(
                            it[type]!!.model,
                            binding.tvShowDate.text.toString()
                        )
                    }

                    4 -> {//年
                        it[type]!!.model = it[type]!!.fillMissingData(it[type]!!.model)
                    }
                }
            }
            setValuss(daysModelList, it[type])
        }
        mViewModel.setting.observe(this) {

            if (it.data.isNotEmpty()) {
                binding.mDesc.text = "${it.data[0].name}：${it.data[0].content}"
            }
        }
        mViewModel.lastData.observe(this) {
            it.data?.let {
                binding.tvXinLv.text = "${it.hrData.toInt()}"
                binding.tvTestTime.text = RxTimeTool.milliseconds2String(
                    it.time.toLong() * 1000,
                    SimpleDateFormat("HH:mm")
                )
            }
        }
    }


    //设置数据
    private fun setValuss(daysModelList: MutableList<XlBean.Model>, bean: XlBean?) {
        if (bean == null) {
            return
        }
        setAvgInfo(bean.value)
        val list = bean.model
        lineValue.clear()
        barValue.clear()
        val rever = (list.indices).reversed()

        if (selectDay()) {//如果是当天才操作
            normalTime = 0
            highTime = 0
            lowTime = 0
            highList.clear()
            highListTime.clear()
            lowList.clear()
            lowListTime.clear()
        }

        for (t in daysModelList.indices) {
            if (selectDay()) {//如果是当天才操作
                getOrganStatu(daysModelList[daysModelList.size - t - 1])
            }
        }
        for (i in rever) {
//            var times = list[i].time.toLong() * 1000
//            var strTime = RxTimeTool.milliseconds2String(times, SimpleDateFormat(fomartStr[type]))
//            LogUtils.d("时间:$strTime")
            //中间两端在x轴显示尺度 其他情况下不显示
            lineValue.add(
                Entry(
                    (list.size - 1 - i).toFloat(),
                    list[list.size - i - 1].hrData.toFloat(),
                    tipTime(list[list.size - i - 1])
                )
            )
            barValue.add(
                BarEntry(
                    (list.size - 1 - i).toFloat(),
                    list[list.size - i - 1].hrData.toFloat(),
                    tipTime(list[list.size - i - 1])
                )
            )
        }
        if (selectDay()) {//如果是当天才操作
            setOrganStatu()
        }
        binding.mLineChart.clear()
        binding.mBarChart.clear()
        initChart(list, bean.value.min.toFloat(), bean.value.max.toFloat())
    }

    private fun tipTime(
        bean: XlBean.Model
    ): String {
        when (type) {
            1, 3 -> {
                if (bean.hrData == 0f) {
                    bean.hrData = Float.NaN
                }
                return bean.time
            }

            2 -> {
                val parts = bean.time.split("-")
                val year = parts[0]
                val month = parts[1]
                val day = parts[2]

                return "$month-$day"
            }

            else -> {
                return "${bean.time}月"
            }
        }
    }

    /**
     * 是否是选的日，只有选日的时候才会刷新正常，异常状态
     */
    private fun selectDay(): Boolean {
        return type < 2
    }

    private fun setOrganStatu() {

        binding.mOrganView.tvFirstName.text = "正常"
        binding.mOrganView.tvFirstValue.text = setSpan(normalTime, 0)
        if (normalTime == 0) {
            binding.mOrganView.ivFirst.visibility = View.INVISIBLE
        } else {
            binding.mOrganView.ivFirst.visibility = View.VISIBLE
        }
        binding.mOrganView.tvSecondName.text = "心动过速"
        binding.mOrganView.tvSecondValue.text = setSpan(highTime, 1)
        if (highTime == 0) {
            binding.mOrganView.ivSecond.visibility = View.INVISIBLE
        } else {
            binding.mOrganView.ivSecond.visibility = View.VISIBLE
        }
        binding.mOrganView.tvThreeName.text = "心动过缓"
        binding.mOrganView.tvThreeValue.text = setSpan(lowTime, 2)
        if (lowTime == 0) {
            binding.mOrganView.ivThree.visibility = View.INVISIBLE
        } else {
            binding.mOrganView.ivThree.visibility = View.VISIBLE
        }

        binding.mOrganView.root.visibility = View.VISIBLE
    }

    private fun setSpan(time: Int, organStatu: Int): SpannableString {
        var statuSpan = SpannableString("${time}次")

        statuSpan.setSpan(
            ForegroundColorSpan(
                //设置字体颜色
                ContextCompat.getColor(
                    requireContext(), R.color.black
                )
            ), 0, statuSpan.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        //设置字体大小(绝对值,单位：像素),第二个参数boolean dip，如果为true，表示前面的字体大小单位为dip，否则为像素
        statuSpan.setSpan(
            AbsoluteSizeSpan(24, true),
            0, statuSpan.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        //设置字体样式: NORMAL正常，BOLD粗体，ITALIC斜体，BOLD_ITALIC粗斜体
        statuSpan.setSpan(
            StyleSpan(Typeface.BOLD),
            0, statuSpan.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        );

        return statuSpan
    }

    /**
     * 带ImageSpan图片设置
     */
//    private fun setSpan(time: Int, organStatu: Int): SpannableString {
//        var imageStr = "\t\t$organStatu"//imageSpan 占位符
//        var statuSpan = SpannableString("${time}次$imageStr")
//
//        statuSpan.setSpan(
//            ForegroundColorSpan(
//                //设置字体颜色
//                ContextCompat.getColor(
//                    requireContext(), R.color.white)
//            ),0, statuSpan.length - imageStr.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
//        //设置字体大小(绝对值,单位：像素),第二个参数boolean dip，如果为true，表示前面的字体大小单位为dip，否则为像素
//        statuSpan.setSpan(
//            AbsoluteSizeSpan(24, true),
//            0, statuSpan.length - imageStr.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
//        //设置字体样式: NORMAL正常，BOLD粗体，ITALIC斜体，BOLD_ITALIC粗斜体
//        statuSpan.setSpan(
//            StyleSpan(Typeface.BOLD),
//            0, statuSpan.length - imageStr.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//
//
//        var image = requireContext().getDrawable(
//            when (organStatu) {
//                0 ->
//                    R.mipmap.icon_normal
//                else ->
//                    R.mipmap.icon_error
//            }
//        )
//        image?.setBounds(0, 0, image.minimumWidth, image.minimumHeight)
//        statuSpan.setSpan(image?.let { ImageSpan(it, ImageSpan.ALIGN_CENTER) },
//            statuSpan.length - 1, statuSpan.length,
//            Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
//
//        return statuSpan
//    }

    var normalTime: Int = 0
    var highTime: Int = 0
    var lowTime: Int = 0
    var highList = ArrayList<String>()
    var lowList = ArrayList<String>()
    var highListTime = ArrayList<String>()
    var lowListTime = ArrayList<String>()
    fun getOrganStatu(data: XlBean.Model) {
        val hrData = data.hrData
        when (OrganStatusCalcUtil.heartStatu(hrData.toInt())) {//0:正常 1：过缓 2：过速
            1 -> {
                lowTime++
                lowList.add(hrData.toInt().toString())
                lowListTime.add(data.time)
            }

            2 -> {
                highTime++
                highList.add(hrData.toInt().toString())
                highListTime.add(data.time)
            }

            else ->
                normalTime++
        }

    }


    /**
     * 周数据
     */
    private fun getWeeks(time: Long): String {
        var calendear = Calendar.getInstance()
        var strData = RxTimeTool.milliseconds2String(time, SimpleDateFormat("yyyy-MM-dd"))
        var times = strData.split("-")
        calendear.set(times[0].toInt(), times[1].toInt() - 1, times[2].toInt())
        var intWeek = calendear.get(Calendar.DAY_OF_WEEK)
        return weekStr[intWeek - 1]
    }

    /**
     * 设置平均值
     */
    fun setAvgInfo(bean: XlBean.Value?) {
        if (bean == null) {
            binding.mAvg.setValue("-")
            binding.mMax.setValue("-")
            binding.mMin.setValue("-")
        } else {
            binding.mAvg.setValue("${bean.avg}")
            binding.mMax.setValue("${bean.max}")
            binding.mMin.setValue("${bean.min}")
        }
    }

    /**
     * 初始化 曲线
     */
    private fun initChart(list: MutableList<XlBean.Model>, min: Float, max: Float) {
        binding.mLineChart.let {
            it.clear()
            it.setNoDataText(getString(R.string.line_chart_not_data))
            it.setNoDataTextColor(ContextCompat.getColor(requireContext(), R.color.col_455))
            it.setLayerType(View.LAYER_TYPE_SOFTWARE, null)

            it.setBackgroundColor(Color.WHITE) ///color
            it.description.isEnabled = false
            it.setTouchEnabled(true)

            it.setScaleEnabled(false)
            it.setPinchZoom(false)

            it.setDrawGridBackground(false)
            it.maxHighlightDistance = 300f


            it.isDragEnabled = true
            val m = Matrix()
            m.postScale(1.5f, 1f)
            it.viewPortHandler.refresh(m, it, false)
            it.isScaleXEnabled = true                 //支持x轴缩放
            it.isScaleYEnabled = false

//            if (lineValue.size > 6) {
//                it.isDragEnabled = true
//                val m = Matrix()
//                m.postScale(1.5f, 1f)
//                it.viewPortHandler.refresh(m, it, false)
//                it.isScaleXEnabled = true                 //支持x轴缩放
//                it.isScaleYEnabled = false
//            } else {
//                it.isDragEnabled = false
//                it.isScaleXEnabled = false                 //支持x轴缩放
//                it.isScaleYEnabled = false
//            }


            val x = it.xAxis
            x.granularity = 1f  //精准设置
            x.textColor = ContextCompat.getColor(requireContext(), R.color.col_92a)
            x.isEnabled = true
            x.setDrawGridLines(false)  //不绘制y
            x.setDrawAxisLine(false)
            //   x.setLabelCount(lineValue.size,false)
            // x.labelRotationAngle=-45f
            x.position = XAxis.XAxisPosition.BOTTOM
            x.setAvoidFirstLastClipping(false)
            x.setValueFormatter { value, axis ->
                var index = value.toInt()
                //Log.e("x轴", "$value")
                if (index < 0 || index >= lineValue.size) {
                    ""
                } else {
                    "${lineValue[value.toInt()].data}"
                }
            }
            //y轴
            /*   val y = it.axisLeft
               y.axisMaximum=200f
               y.axisMinimum=0f
               y.axisMaxLabels=6
             //y.setLabelCount(6, true)
               y.textColor = ContextCompat.getColor(requireContext(), R.color.col_92a)
               y.setDrawAxisLine(false)
               y.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART)
               y.gridColor = ContextCompat.getColor(requireContext(), R.color.col_92a)
               y.setGridDashedLine(DashPathEffect(floatArrayOf(5f, 5f), 0f))
               y.setDrawGridLines(true)  //绘制横者的x轴
               y.setDrawZeroLine(true)


   */
            //y轴
            val y = it.axisLeft
//            y.axisMaximum=max
//            y.axisMinimum=min
            y.setLabelCountAndMaxMinValue(6, false, min - 10f, max + 10f)
            y.textColor = ContextCompat.getColor(requireContext(), R.color.col_92a)
            y.setDrawAxisLine(false)
            y.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART)
            y.gridColor = ContextCompat.getColor(requireContext(), R.color.col_0F2)
            y.setGridDashedLine(DashPathEffect(floatArrayOf(5f, 0f), 0f))
            y.setDrawGridLines(true)  //绘制横者的x轴
            y.setDrawZeroLine(true)


            var markerView = IMarkView(
                requireContext(), R.layout.mark_view, "次/分",
                IMarkView.MarkPage.XLv
            )
            it.marker = markerView
            markerView.chartView = it
            it.axisRight.isEnabled = false
            it.legend.isEnabled = false

            //   it.animateXY(2000, 2000)  //设置xy轴进入的动画
            it.invalidate()
        }

        val barsetsNew: java.util.ArrayList<ILineDataSet> = java.util.ArrayList()
        var segments = splitDataIntoSegments(list)
        if (segments.size > 0) {
            segments = checkData(segments)
        }

        val dataSets = segments.mapNotNull { segment ->
            if (segment.isEmpty()) return@mapNotNull null

            val entries = segment.mapIndexed { index, model ->
                Entry(
                    convertTimeToIndex(model.time, index).toFloat(),
                    model.hrData,
                    lineValue[convertTimeToIndex(model.time, index)].data
                )
            }
            return@mapNotNull setData(entries)
        }

        if (!lineValue.isNullOrEmpty()) {
            barsetsNew.addAll(dataSets)
            val bard = LineData(barsetsNew)
            binding.mLineChart.data = bard
            binding.mLineChart.invalidate()
//                if (lineValue.size > 10) {
//                    it.setVisibleXRangeMaximum(1f)
//                }
            binding.mLineChart.moveViewToX(lineValue[lineValue.size - 1].x)
        }

        binding.mBarChart.let {
            it.clear()
            it.setNoDataText(getString(R.string.line_chart_not_data))
            it.setNoDataTextColor(ContextCompat.getColor(requireContext(), R.color.col_455))
            it.setLayerType(View.LAYER_TYPE_SOFTWARE, null)

            it.setBackgroundColor(Color.WHITE) ///color
            it.description.isEnabled = false
            it.setTouchEnabled(true)
            it.setPinchZoom(true)//柱形图的横坐标缩放，

            it.setDrawGridBackground(false)//背景网格是否绘制
            it.maxHighlightDistance = 300f//设置高亮（Highlight）的最大距离


            it.isDragEnabled = true//是否启用拖动（drag）功能。
            val m = Matrix()
            m.postScale(
                when (type) {
                    1 -> {
                        11.5f
                    }

                    3 -> {
                        3.5f
                    }

                    else -> {
                        1f
                    }
                }, 0f
            )
            it.viewPortHandler.refresh(m, it, false)
            it.isScaleXEnabled = true  //支持x轴缩放
            it.isScaleYEnabled = false //支持Y轴缩放

            val x = it.xAxis
            x.granularity = 1f  //精准设置
            x.textColor = ContextCompat.getColor(requireContext(), R.color.col_92a)
            x.textSize = 9f
            x.axisMinimum = -0.5f
            x.axisMaximum = (barValue.size - 0.5).toFloat()
//                x.labelCount = 6
            x.isEnabled = true
            x.setDrawGridLines(false)  //不绘制y
            x.setDrawAxisLine(false)
            x.xOffset = 0f
            x.position = XAxis.XAxisPosition.BOTTOM
            x.setValueFormatter { value, axis ->
                var index = value.toInt()
                //Log.e("x轴", "$value")
                if (index < 0 || index >= barValue.size) {
                    ""
                } else {
                    "${barValue[value.toInt()].data}"
                }
            }
            val y = it.axisLeft
            y.setLabelCountAndMaxMinValue(6, false, min - 10, max + 10)
            y.textColor = ContextCompat.getColor(requireContext(), R.color.col_92a)
            y.setDrawAxisLine(false)
            y.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART)
            y.gridColor = ContextCompat.getColor(requireContext(), R.color.col_0F2)
            y.setGridDashedLine(DashPathEffect(floatArrayOf(5f, 0f), 0f))
            y.setDrawGridLines(true)  //绘制横者的x轴
            y.setDrawZeroLine(true)
            var markerView = IMarkView(
                requireContext(), R.layout.mark_view, "次/分",
                IMarkView.MarkPage.XLv
            )
            it.marker = markerView
            markerView.chartView = it
            it.axisRight.isEnabled = false
            it.legend.isEnabled = false
            //   it.setVisibleXRangeMaximum(10f)
            //   it.animateXY(2000, 2000)  //设置xy轴进入的动画

        }

        if (barValue.isEmpty()) {
            return
        }
        binding.mBarChart.moveViewToX(barValue[barValue.size - 1].x)

//        var d = BarData(set1)
//        d.setValueTextSize(9f)
//        d.setDrawValues(false)

        val dataBarSets = segments.mapNotNull { segment ->
            if (segment.isEmpty()) return@mapNotNull null

            val entries = segment.mapIndexed { index, model ->
                BarEntry(
                    convertTimeToIndex(model.time, index).toFloat(),
                    model.hrData,
                    barValue[convertTimeToIndex(model.time, index)].data
                )
            }
            return@mapNotNull setBarData(entries)
        }

        val bard = BarData(dataBarSets)
        bard.barWidth = calculateBarWidth(bard.dataSetCount)
        binding.mBarChart.data = bard
        binding.mBarChart.invalidate()
    }

    private fun setBarData(entries: List<BarEntry>): BarDataSet {
        val set1: BarDataSet
        if (binding.mBarChart.data != null && binding.mBarChart.data.dataSetCount > 0) {
            set1 = binding.mBarChart.data.getDataSetByIndex(1) as BarDataSet
            set1.entries = entries
            binding.mBarChart.data.notifyDataChanged()
            binding.mBarChart.notifyDataSetChanged()
        } else {
            set1 = BarDataSet(entries, "DataSet 2")
            set1.setDrawValues(false) // 不显示值
            set1.valueTextColor = ContextCompat.getColor(requireContext(), R.color.col_9BDd)
            set1.highLightColor =
                ContextCompat.getColor(requireContext(), R.color.col_EFF)  //设置点后高亮颜色
            set1.color = ContextCompat.getColor(requireContext(), R.color.col_9BDd) //xian de yanse
            val data = BarData(set1)
            data.setValueTextSize(9f)
            data.setDrawValues(false)
        }
        return set1
    }

    private fun calculateBarWidth(dataCount: Int): Float {
        val maximumBarWidth = 0.3f // 设置最大柱形图宽度
        val minimumBarWidth = 0.3f // 设置最小柱形图宽度

        val defaultBarWidth = 0.3f // 默认柱形图宽度
        val availableWidth = 1.0f - (dataCount + 1) * 0.1f // 可用宽度减去间距占用

        val calculatedBarWidth = availableWidth / dataCount.toFloat()
        return max(minimumBarWidth, min(maximumBarWidth, calculatedBarWidth))
    }

    fun splitDataIntoSegments(dataList: MutableList<XlBean.Model>): MutableList<MutableList<XlBean.Model>> {
        val segments = mutableListOf<MutableList<XlBean.Model>>()
        var currentSegment = mutableListOf<XlBean.Model>()

        for (model in dataList) {
            if (model.hrData.toFloat().isNaN()) {
                // 遇到 Float.NaN，如果当前线段不为空，则添加到结果中，并开始新的线段
                if (currentSegment.isNotEmpty()) {
                    segments.add(currentSegment)
                    currentSegment = mutableListOf()
                }
            } else {
                // 遇到有效数据，将其添加到当前线段中
                currentSegment.add(model)
            }
        }

        // 将最后一个线段添加到结果中
        if (currentSegment.isNotEmpty()) {
            segments.add(currentSegment)
        }

        return segments
    }

    private fun checkData(segmentsCompare: MutableList<MutableList<XlBean.Model>>): MutableList<MutableList<XlBean.Model>> {
        when (type) {
            1 -> {
                if (segmentsCompare[0][0].time != "00:00") {
                    val d = mutableListOf<XlBean.Model>()
                    val b = XlBean.Model(0f, "00:00")
                    d.add(b)
                    segmentsCompare.add(d)
                }
                if (!TimeUtils.isToday(
                        binding.tvShowDate.text.toString(),
                        SimpleDateFormat("yyyy-MM-dd")
                    ) &&
                    segmentsCompare[segmentsCompare.size - 1][segmentsCompare[segmentsCompare.size - 1].size - 1].time != "23:50"
                ) {
                    val d = mutableListOf<XlBean.Model>()
                    val b = XlBean.Model(0f, "23:50")
                    d.add(b)
                    segmentsCompare.add(d)
                }
            }

            2 -> {
                val split = binding.tvShowDate.text.toString().split("至")
                val start = split[0]
                val end = split[1]

                if (segmentsCompare[0][0].time != start) {
                    val d = mutableListOf<XlBean.Model>()
                    val b = XlBean.Model(0f, start)
                    d.add(b)
                    segmentsCompare.add(d)
                }
                if (segmentsCompare[segmentsCompare.size - 1][segmentsCompare[segmentsCompare.size - 1].size - 1].time != end) {
                    val d = mutableListOf<XlBean.Model>()
                    val b = XlBean.Model(0f, end)
                    d.add(b)
                    segmentsCompare.add(d)
                }
            }

            3 -> {
                val split = binding.tvShowDate.text.toString().split("-")
                val year = split[0]//2023
                val month = split[1]//08

                val calendar = Calendar.getInstance()
                calendar.set(Calendar.YEAR, year.toInt())
                calendar.set(Calendar.MONTH, month.toInt() - 1) // Calendar.MONTH is 0-based
                val daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH)

                if (segmentsCompare[0][0].time != "$month-01") {
                    val d = mutableListOf<XlBean.Model>()
                    val b = XlBean.Model(0f, "$month-01")
                    d.add(b)
                    segmentsCompare.add(d)
                }
                if (!isCurYearMonth(
                        binding.tvShowDate.text.toString(),
                        SimpleDateFormat("yyyy-MM")
                    ) &&
                    segmentsCompare[segmentsCompare.size - 1][segmentsCompare[segmentsCompare.size - 1].size - 1].time != "$month-$daysInMonth"
                ) {
                    val d = mutableListOf<XlBean.Model>()
                    val b = XlBean.Model(0f, "$month-$daysInMonth")
                    d.add(b)
                    segmentsCompare.add(d)
                }
            }

            4 -> {
                if (segmentsCompare[0][0].time != "01") {
                    val d = mutableListOf<XlBean.Model>()
                    val b = XlBean.Model(0f, "01")
                    d.add(b)
                    segmentsCompare.add(d)
                }
                if (segmentsCompare[segmentsCompare.size - 1][segmentsCompare[segmentsCompare.size - 1].size - 1].time != "12") {
                    val d = mutableListOf<XlBean.Model>()
                    val b = XlBean.Model(0f, "12")
                    d.add(b)
                    segmentsCompare.add(d)
                }
            }
        }


        return segmentsCompare
    }

    private fun isCurYearMonth(dateString: String, dateFormat: SimpleDateFormat): Boolean {
        val date = dateFormat.parse(dateString)
        if (date == null) {
            LogUtils.w("isCurYearMonth, date == null")
            return false
        }
        val calendar = Calendar.getInstance()
        calendar.time = date

        val currentYear = Calendar.getInstance().get(Calendar.YEAR)
        val currentMonth = Calendar.getInstance().get(Calendar.MONTH)

        val isCurrentYear = calendar.get(Calendar.YEAR) == currentYear
        val isCurrentMonth = calendar.get(Calendar.MONTH) == currentMonth

        return isCurrentYear && isCurrentMonth
    }

    fun convertTimeToIndex(time: String, cur: Int): Int {
        var index = 0
        when (type) {
            1 -> {
                // 将时间格式转换为小时和分钟
                val parts = time.split(":")
                var hours = 0
                var minutes = 0
                if (parts.size > 1) {
                    hours = parts[0].toInt()
                    minutes = parts[1].toInt()
                }
                // 计算对应的分钟数
                val totalMinutes = hours * 60 + minutes

                // 计算对应的索引值
                index = totalMinutes / 10
            }

            2 -> {
                val split = binding.tvShowDate.text.toString().split("至")
                val rangeStart = split[0]
                val rangeEnd = split[1]
                val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
                try {
                    val startDate = formatter.parse(rangeStart)
                    val endDate = formatter.parse(rangeEnd)
                    val inputDateObj = formatter.parse(time)
                    if (startDate == null || endDate == null || inputDateObj == null) {
                        LogUtils.w("data formatter result is null")
                        return 0
                    }
                    val calendar = Calendar.getInstance()
                    calendar.time = startDate
                    while (calendar.time <= endDate) {
                        if (calendar.time == inputDateObj) {
                            println("Index: $index")
                            break
                        }
                        calendar.add(Calendar.DATE, 1)
                        index++
                    }

                } catch (e: java.text.ParseException) {
                    e.printStackTrace()
                }
            }

            3 -> {
                // 将08-01格式转换为序号
                val parts = time.split("-")
                val month = parts[0].toInt()
                val day = parts[1].toInt()
                index = day - 1
            }

            else -> {
                index = if (time.isDigitsOnly()) (time.toInt() - 1) else 0
            }
        }

        return if (index < 0) cur + 1 else index
    }

    /**
     * 设置曲线数据
     */
    private fun setData(values: List<Entry>?): LineDataSet {

        val set1: LineDataSet
        if (binding.mLineChart!!.data != null && binding.mLineChart!!.data.dataSetCount > 0) {
            set1 = binding.mLineChart!!.data.getDataSetByIndex(0) as LineDataSet
            set1.values = values
            binding.mLineChart!!.data.notifyDataChanged()
            binding.mLineChart!!.notifyDataSetChanged()
        } else {
            // create a dataset and give it a type
            set1 = LineDataSet(values, "DataSet 1")
            set1.mode = LineDataSet.Mode.LINEAR
            set1.cubicIntensity = 0.2f
            set1.setDrawFilled(true)
            set1.lineWidth = 2.5f
            set1.circleRadius = 2f
            // 分段后，数据若有一个点需要显示
            set1.setDrawCircles(values?.size == 1)
            set1.highLightColor =
                ContextCompat.getColor(requireContext(), R.color.col_e0b)  //设置点后高亮颜色
            set1.enableDashedHighlightLine(10f, 5f, 0f)
            set1.setCircleColor(
                ContextCompat.getColor(
                    requireContext(),
                    R.color.col_41c
                )
            )    //#41C4AF
            set1.color = ContextCompat.getColor(requireContext(), R.color.col_41c) //xian de yanse
            //背景填充
            val drawable = ContextCompat.getDrawable(requireContext(), R.drawable.shape_curve)
            set1.fillDrawable = drawable
            //set1.setFillColor(Color.WHITE);
            set1.fillAlpha = 100
            set1.setDrawHorizontalHighlightIndicator(false)
            set1.fillFormatter =
                IFillFormatter { dataSet, dataProvider -> binding.mLineChart!!.axisLeft.axisMinimum }

            set1.setValueFormatter { value, entry, dataSetIndex, viewPortHandler ->
                "$value"
            }
            // create a data object with the data sets
            val data = LineData(set1)
            //data.setValueTypeface(tfLight)
            data.setValueTextSize(9f)
            data.setDrawValues(false)

            // set data
            //  binding.mLineChart!!.data = data

        }
        return set1
    }

    var dayDate = ""
    var weekDate = ""
    var mouthDate = ""
    var yearDate = ""
    private fun getDateAdd(days: Int): Date? {
        val c = Calendar.getInstance()
        c.add(Calendar.DAY_OF_MONTH, -days)
        return c.time
    }

    private val mTabEntities: ArrayList<CustomTabEntity> = ArrayList()
    private val mFragments: SparseArray<Fragment> = SparseArray()
    private val mTitles = arrayOf(
        "日", "周", "月", "年"
    )

    private fun initTab() {

        val currentDay = Date()
        dayDate = TimeUtils.date2String(currentDay, "yyyy-MM-dd")
        weekDate = "${TimeUtils.date2String(getDateAdd(6), "yyyy-MM-dd")}至$dayDate"
        mouthDate = TimeUtils.date2String(currentDay, "yyyy-MM")
        yearDate = TimeUtils.date2String(currentDay, "yyyy")
        mTabEntities.clear()
        mFragments.clear()
        mTitles.forEach {
            mTabEntities.add(
                TabEntity(
                    it, android.R.drawable.ic_delete, android.R.drawable.ic_delete
                )
            )
        }
        binding.commonTabLayout.setTabData(mTabEntities)
        binding.commonTabLayout.setOnTabSelectListener(object : OnTabSelectListener {
            @SuppressLint("SetTextI18n")
            override fun onTabSelect(position: Int) {
                binding.commonTabLayout.currentTab = position

                when (position) {
                    0 -> {
                        binding.tvShowDate.text = dayDate
                        type = 1
                    }

                    1 -> {
                        binding.tvShowDate.text = weekDate
                        type = 2
                    }

                    2 -> {
                        binding.tvShowDate.text = mouthDate
                        type = 3
                    }

                    3 -> {
                        binding.tvShowDate.text = yearDate
                        type = 4
                    }
                }
                mViewModel.getXlData(type, binding.tvShowDate.text.toString(), id, isDemonstrate)
            }

            override fun onTabReselect(position: Int) {
            }

        })

    }

    private fun initTimeSelect() {
        //日筛选
        val calendar = Calendar.getInstance()
        timeSelect.startDate.set(1922, 1, 1)
        timeSelect.endDate.set(
            calendar[Calendar.YEAR], calendar[Calendar.MONTH], if (calendar[Calendar.HOUR] >= 11) {
                calendar[Calendar.DATE]
            } else {
                calendar[Calendar.DATE]
            }
        )
        binding.tvShowDate.text = RxTimeTool.getCurTimeString(SimpleDateFormat("yyyy-MM-dd"))

        binding.tvShowDate.setOnClickListener {
            when (type) {
                1 -> {
                    timeSelect.selectTime(it, "yyyy-MM-dd")
                }

                2 -> {
                    bottomSheetDialog?.show()
                }

                3 -> {
                    timeMonthSelect.selectTimeWithYearMonth(it, "yyyy-MM")
                }

                4 -> {
                    timeYearSelect.selectTimeWithYear(it, "yyyy")
                }
            }
        }
        binding.ivPosition.setOnClickListener {
            when (type) {
                1 -> {
                    timeSelect.selectTime(binding.tvShowDate, "yyyy-MM-dd")
                }

                2 -> {
                    bottomSheetDialog?.show()
                }

                3 -> {
                    timeMonthSelect.selectTimeWithYearMonth(binding.tvShowDate, "yyyy-MM")
                }

                4 -> {
                    timeYearSelect.selectTimeWithYear(binding.tvShowDate, "yyyy")
                }
            }
        }

        initBottomDialog()
    }

    private var bottomSheetDialog: BottomSheetDialog? = null

    fun initBottomDialog() {
        if (bottomSheetDialog == null) {
            bottomSheetDialog = BottomSheetDialog(this.requireContext())
            bottomSheetDialog?.let { dialog ->
                val view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_layout, null)
                dialog.setContentView(view)
                val wheelView = view.findViewById<WheelView>(R.id.wheelView)
                wheelView.setCyclic(false)
                wheelView.adapter = ArrayWheelAdapter(buildWeekLower26())
                val windowHeight = (resources.displayMetrics.heightPixels * 0.6).toInt()
                dialog.behavior.peekHeight = windowHeight

                dialog.behavior.isHideable = false
                dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED

                val cancelButton = view.findViewById<TextView>(R.id.cancel_button)
                val confirmButton = view.findViewById<TextView>(R.id.confirm_button)

                cancelButton.setOnClickListener {
                    // 点击取消按钮的操作
                    dialog.dismiss()
                }

                confirmButton.setOnClickListener {
                    // 点击确定按钮的操作
                    val item = wheelView.adapter.getItem(wheelView.currentItem)
                    binding.tvShowDate.text = item.toString()
                    weekDate = binding.tvShowDate.text.toString()
                    mViewModel.getXlData(2, binding.tvShowDate.text.toString(), id, isDemonstrate)
                    // 点击确定按钮的操作
                    dialog.dismiss()
                }
            }
        }
    }

    fun buildWeekLower26(): MutableList<String> {
        val startDate = Calendar.getInstance()
        startDate.firstDayOfWeek = Calendar.MONDAY
        startDate.add(Calendar.YEAR, -1)
        val endDate = Calendar.getInstance()

        val dateRanges: MutableList<String> = ArrayList()
        var currentMonday = startDate.clone() as Calendar
        currentMonday.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY)

        while (currentMonday.before(endDate)) {
            val currentSunday = currentMonday.clone() as Calendar
            currentSunday.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY)

            val formattedDateRange =
                SimpleDateFormat("yyyy-MM-dd").format(currentMonday.time) + "至" + SimpleDateFormat(
                    "yyyy-MM-dd"
                ).format(
                    currentSunday.time
                )
            dateRanges.add(formattedDateRange)

            currentMonday.add(Calendar.WEEK_OF_YEAR, 1)
        }

        dateRanges.reverse()
        return dateRanges
    }
}