package com.zj365.health.fragment

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.TextUtils
import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
import android.util.Log
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.RxConstTool
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.MMkvHelper
import com.xty.common.TimeSelect
import com.xty.common.arouter.ARouterUrl
import com.xty.common.arouter.RouteManager
import com.xty.common.event.NSuanOpenEvent
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.FragUricAcidBinding
import com.zj365.health.vm.UricAcidVm
import com.zj365.health.weight.DialogTip
import com.zj365.health.weight.HealthDialog
import com.zj365.health.weight.IMarkView
import com.xty.network.model.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.lang.Float.max
import java.lang.Float.min
import java.text.SimpleDateFormat
import java.util.*

/**
 * 尿酸
 */
class UricAcidFrag : BaseVmFrag<UricAcidVm>() {

    private val binding by lazy { FragUricAcidBinding.inflate(layoutInflater) }
    override fun setLayout(): View = binding.root
    override fun setViewModel() = UricAcidVm()

    private var dayDate: String = ""
    private var isDemonstrate: Boolean = false
    private var sex = "1"
    private var isPermission = false
    private var isCompleteInfo = false
    private var expireTimeStr: String = ""
    var type = 2
    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) }
    val dialogBind by lazy {
        DialogTip(requireContext(), "需绑定中健三六五健康手表，才能查看", "去绑定") {
            RouteManager.goAct(ARouterUrl.DEVICE_CHOICE)
        }
    }
    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.getUricAcidInfo(type, binding.tvShowDate.text.toString(), id, isDemonstrate)
        }
    }

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

        }
    }
    val timeYearSelect by lazy {
        TimeSelect(requireContext()) {
            type = 4
            yearDate = binding.tvShowDate.text.toString()
            mViewModel.getUricAcidInfo(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()
        if (id == "0" || id.isNullOrEmpty()) {
            id = if (MMkvHelper.getLong(Const.USER_ID).toString() == "0") {
                ""
            } else {
                MMkvHelper.getLong(Const.USER_ID).toString()
            }
        }
        sex = arguments?.getString("sex").toString()
        OrganStatusCalcUtil.mSex = sex
    }

    override fun initView() {
        super.initView()
        initTab()
        initTimeSelect()
        isDemonstrate = (requireActivity() as HealthMainAct).isDemonstrate
        binding.mOrganView.ivSecond.setOnClickListener {
            if (isDemonstrate) {
                (requireActivity() as HealthMainAct).dialogBind.show()
                return@setOnClickListener
            }
            val text = binding.mOrganView.tvSecondName.text.toString()
            bundle.clear()
            bundle.putString("sex", sex)
            bundle.putString(BaseExceptionDataAct.exceptionKey, text)
            bundle.putStringArrayList(BaseExceptionDataAct.exceptionList, highList)
            bundle.putStringArrayList(BaseExceptionDataAct.exceptionListTime, highListTime)
            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", "8")//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 {
            tip = "尿酸是嘌呤代谢的终末产物，嘌呤代谢紊乱，能量代谢异常以及肾脏对尿酸的排泄障碍，均可以引起血浆" +
                    "尿酸浓度升高，或者是降低。人体尿酸的正常值有男性和女性之分，一般男性的正常参考值为：150～420umol/L，而女" +
                    "性的正常参考值在89～359umol/L之间。"
            tipDialog.setHintContent(tip)
            tipDialog.show()
        }
        binding.tvModelingExplain.setOnClickListener {
            tip = "尿酸建模出值重要提示:\n" +
                    "1、建模期间，累计有效佩戴满72小时；\n" +
                    "2、建模完成后，每天18:00至第二天6:00期间，佩戴时长累计满6小时，APP出具尿酸值；\n" +
                    "3、尿酸值每天7：00出值。本次值为前一天18:00到当天早上6:00尿酸平均值。"
            tipDialog.setContent(tip)
            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.getUricAcidInfo(type, binding.mTvTime.text.toString(), id, isDemonstrate)
            } else {
                mViewModel.getUricAcidInfo(type, null, id, isDemonstrate)
            }
        }
        //如果没有开通尿酸
        binding.tvUricAcidInfo.setOnClickListener {
            if (isDemonstrate) {
                dialogBind.show()
                return@setOnClickListener
            }

//            if (!isPermission) {  //如果没有开通，前去开通
////                bundle.clear()
////                bundle.putString("id", id)
////                RouteManager.goAct(ARouterUrl.NS_OPEN, bundle)
//                bundle.clear()
//                bundle.putString("expireTime", expireTimeStr)
//                bundle.putString("userId", id)
//                bundle.putInt("pageType", 2)
//                RouteManager.goAct(ARouterUrl.OPEN_OR_RENEW, bundle)
//                return@setOnClickListener
//            }

            //如果用户是去完善和修改信息
            bundle.clear()
            bundle.putString("id", id)
            bundle.putBoolean("alter", true)
            bundle.putString("time", expireTimeStr)
            RouteManager.goAct(ARouterUrl.NS_MESSAGE_PERFECT, bundle)
            return@setOnClickListener
        }
        //马上开通按钮
        binding.tvOpen.setOnClickListener {
            bundle.clear()
            bundle.putString("expireTime", expireTimeStr)
            bundle.putString("userId", id)
            bundle.putInt("pageType", 2)
            RouteManager.goAct(ARouterUrl.OPEN_OR_RENEW, bundle)
        }
        //续费按钮
        binding.tvRenew.setOnClickListener {
            bundle.clear()
            bundle.putString("expireTime", expireTimeStr)
            bundle.putString("userId", id)
            bundle.putInt("pageType", 2)
            RouteManager.goAct(ARouterUrl.OPEN_OR_RENEW, bundle)
        }

        if (isDemonstrate) {
//            binding.tvUricAcidInfo.text = "马上开通"
            binding.tvOpen.visibility = View.GONE
            binding.tvRenew.visibility = View.GONE
            binding.compareTv.visibility = View.VISIBLE
        }

        val content = SpannableString("立即续费")
        val underlineSpan = UnderlineSpan()
        content.setSpan(
            underlineSpan,
            0,
            content.length,
            Spanned.SPAN_INCLUSIVE_INCLUSIVE
        )
        binding.tvRenew.text = content

        binding.tvTips.text = "了解尿酸：\n正常情况下，人体内的尿酸大约有1200 mg，每天新生成约600 mg，同时排泄掉600 mg，处于平衡的状态。" +
                "但如果体内产生过多来不及排泄或者尿酸排泄机制退化，则体内尿酸滞留过多，当血液尿酸浓度大于7 mg/dl，导致人体体液变酸，长期将会引发痛风。" +
                "过于疲劳或是休息不足也可导致代谢相对迟缓进而导致痛风发病。\n\n" +
                " 尿酸的正常值是什么？\n" +
                "正常尿酸值为：89-359μmol/L；受性别因素影响：男性在150~416μmol/L,女性89~357μmolL。\n\n" +
                "尿酸的异常代表什么？\n" +
                "排除生理因素后，尿酸的增高：提示产生过多以及排泄障碍，可以有助于判断单纯高尿酸血症、痛风、肾炎等疾病。尿酸的减低：提示肝脏代谢功能减低或者肾重吸收异常，有助于判断肝坏死、肝豆状核变性等。\n\n" +
                "\n" +
                "尿酸监测算法原理：反射光谱分析原理+核心算法\n" +
                "手表测尿酸的原理是通过手表上内置的光学传感器检测皮肤下血液中尿酸含量的变化，主要基于反射光谱分析原理，即通过LED发射出的绿色光线照射到皮肤上，再由光学传感器检测被皮肤和血液反射回来的光线强度，从而测量尿酸含量，再将测量出来的数据通过核心算法进行分析处理并得出相关尿酸数值。\n" +
                "\n\n\n" +
                "测量结果仅供参考，不作为医疗诊断依据。"

        loadData()
    }

    private fun loadData() {

        binding.mDesc.text = if (sex == "1") {  //男性
            "正常尿酸：150-420μmol/L"
        } else {  // 女性
            "正常尿酸：89-359μmol/L"
        }

        if (isDemonstrate) {
            val time = TimeUtils.date2String(Date(), "yyyy-MM-dd hh:mm:ss")
            binding.tvNsValue.text = "300"
            binding.tvTestTime.text = time
            binding.tvEndTime.text = "2088-12-21 18:00:00"

            binding.mOrganView.tvFirstValue.text = setSpan(1)
            binding.mOrganView.ivFirst.visibility = View.VISIBLE

            binding.mOrganView.tvSecondValue.text = setSpan(0)
            binding.mOrganView.ivSecond.visibility = View.INVISIBLE

        } else {
            //尿酸头部信息,这里有判断是否绑定了尿酸设备
            mViewModel.getUricAcidHead(id)
        }
        mViewModel.getUricAcidInfo(type, binding.tvShowDate.text.toString(), id, isDemonstrate)
    }

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

    @SuppressLint("SimpleDateFormat", "SetTextI18n")
    override fun observer() {

        mViewModel.userInfo.observe(this) {
            //是否完善信息
            isCompleteInfo = it.data.writeState != "0"
        }

        mViewModel.oneDayData.observe(this) {
            if (it.data.model.isNotEmpty()) {
                getOrganStatu(it.data.model[0], sex)
            }
        }

        mViewModel.uricAcideInfo.observe(this) {
            expireTimeStr = it.data.expireTime
            if (!TextUtils.isEmpty(expireTimeStr)) {
                binding.tvEndTime.text = "到期时间:${expireTimeStr}"
            } else {
                binding.tvEndTime.text = ""
            }

            when (it.data.status) {
                0 -> { //没有绑定设备
                    if (TextUtils.isEmpty(expireTimeStr)) {
                        isPermission = false
                        binding.tvUricAcidInfo.visibility = View.GONE
                        binding.tvTestTime.visibility = View.GONE
                        binding.tvNsValue.text = "未开通"
                        binding.tvUnit.visibility = View.GONE
                        binding.compareTv.visibility = View.GONE

                        binding.tvOpen.visibility = View.VISIBLE
                        binding.tvRenew.visibility = View.GONE
                    } else {
                        binding.tvOpen.visibility = View.GONE
                        binding.tvRenew.visibility = View.VISIBLE
                        binding.tvUnit.visibility = View.VISIBLE
                        binding.compareTv.visibility = View.VISIBLE
                        binding.tvUricAcidInfo.text = "尿酸信息"
                        binding.tvUricAcidInfo.visibility = View.VISIBLE

                        val uricAcidValue = it.data?.data?.uaValue?.toInt()
                        if (uricAcidValue != 0 && uricAcidValue != null) {
                            binding.tvNsValue.text = uricAcidValue.toString()
                        } else {
                            binding.tvNsValue.text = "--"
                        }
                    }
                    binding.mOrganView.tvFirstValue.text = setSpan(0)
                    binding.mOrganView.tvSecondValue.text = setSpan(0)
                    binding.tvModelingExplain.visibility = View.GONE
                    return@observe
                }

                1 -> { //建模中
                    isPermission = true
                    binding.tvUricAcidInfo.visibility = View.VISIBLE
                    binding.tvUricAcidInfo.text = "尿酸信息"
                    binding.tvNsValue.text = "建模中"
                    binding.tvTestTime.visibility = View.GONE
                    binding.mOrganView.tvFirstValue.text = setSpan(0)
                    binding.mOrganView.tvSecondValue.text = setSpan(0)
                    binding.tvUnit.visibility = View.GONE
                    binding.tvOpen.visibility = View.GONE
                    binding.tvRenew.visibility = View.GONE
                    binding.compareTv.visibility = View.VISIBLE
                    binding.tvModelingExplain.visibility = View.VISIBLE
                }

                else -> {
                    isPermission = true
                    //用户的其他信息,这里判断用户是否完善了信息
                    mViewModel.getUserInfo(id)
                    binding.tvUricAcidInfo.text = "尿酸信息"
                    binding.tvNsValue.text = ""
                    binding.tvTestTime.visibility = View.VISIBLE
                    binding.tvUnit.visibility = View.VISIBLE
                    binding.tvOpen.visibility = View.GONE
                    binding.tvRenew.visibility = View.GONE
                    binding.compareTv.visibility = View.VISIBLE
                    binding.tvModelingExplain.visibility = View.GONE
                }
            }

            it.data?.data?.let { data ->
                val uricAcidValue = data.uaValue?.toInt()

                if (sex == "1") { //男性
                    if (uricAcidValue != null && uricAcidValue > 420) {

                        binding.mOrganView.tvFirstValue.text = setSpan(0)
                        binding.mOrganView.ivFirst.visibility = View.INVISIBLE

                        binding.mOrganView.tvSecondValue.text = setSpan(1)
                        binding.mOrganView.ivSecond.visibility = View.VISIBLE
                    } else {
                        binding.mOrganView.tvFirstValue.text = setSpan(1)
                        binding.mOrganView.ivFirst.visibility = View.VISIBLE

                        binding.mOrganView.tvSecondValue.text = setSpan(0)
                        binding.mOrganView.ivSecond.visibility = View.INVISIBLE
                    }
                } else { //女性
                    if (uricAcidValue != null && uricAcidValue > 359) {

                        binding.mOrganView.tvFirstValue.text = setSpan(0)
                        binding.mOrganView.ivFirst.visibility = View.INVISIBLE

                        binding.mOrganView.tvSecondValue.text = setSpan(1)
                        binding.mOrganView.ivSecond.visibility = View.VISIBLE
                    } else {
                        binding.mOrganView.tvFirstValue.text = setSpan(1)
                        binding.mOrganView.ivFirst.visibility = View.VISIBLE

                        binding.mOrganView.tvSecondValue.text = setSpan(0)
                        binding.mOrganView.ivSecond.visibility = View.INVISIBLE
                    }
                }

                if (uricAcidValue != 0) {
                    binding.tvNsValue.text = uricAcidValue.toString()
                } else {
                    binding.tvNsValue.text = "--"
                }
                val expireDay = RxTimeTool.getIntervalByNow(
                    expireTimeStr,
                    RxConstTool.TimeUnit.DAY,
                    SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                ) + 1
                LogUtils.d("过期时间还剩：$expireDay 天；有效期截至：$expireTimeStr")
                if (expireDay > 30) {
                    binding.tvRenew.visibility = View.GONE
                } else if (it.data.status == 2) {
                    binding.tvRenew.visibility = View.VISIBLE
                }

                val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                val calendar = Calendar.getInstance()
                calendar.time = format.parse(data.time!!)!!
                val myFormat = SimpleDateFormat("yyyy-MM-dd HH:mm")

                binding.tvTestTime.text = myFormat.format(calendar.time)

                mViewModel.getCurrentUricAcidValue(data.timeDay, id, isDemonstrate)
            }

        }

        mViewModel.dataLive.observe(this) {
            if (it == null || it[type] == null) {
                return@observe
            }

            // 这里把日的原始数据暂存起来，跳转异常页面时使用
            val daysModelList: MutableList<UricAcidInfoBean.Model> = it[type]!!.model
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                when (type) {

                    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])
        }
    }


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

        for (i in rever) {
            //中间两端在x轴显示尺度 其他情况下不显示
            lineValue.add(
                Entry(
                    (list.size - 1 - i).toFloat(),
                    list[list.size - i - 1].uaValue,
                    tipTime(list[list.size - i - 1])
                )
            )
            barValue.add(
                BarEntry(
                    (list.size - 1 - i).toFloat(),
                    list[list.size - i - 1].uaValue,
                    tipTime(list[list.size - i - 1])
                )
            )
        }

        binding.mLineChart.clear()
        binding.mBarChart.clear()
        initChart(list, bean.value.minData.toFloat(), bean.value.maxData.toFloat())

    }

    private fun setSpan(time: 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
    }

    private fun tipTime(
        bean: UricAcidInfoBean.Model
    ): String {
        when (type) {
            1, 3 -> {
                if (bean.uaValue == 0f) {
                    bean.uaValue = 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}月"
            }
        }
    }

    var normalTime: Int = 0
    var highTime: Int = 0
    var lowTime: Int = 0
    var highList = ArrayList<String>()
    var highListTime = ArrayList<String>()

    fun getOrganStatu(data: UricAcidInfoBean.Model, sex: String) {

        highList.clear()
        highListTime.clear()

        when (OrganStatusCalcUtil.UricAcidStatu(data.uaValue, sex)) {//1：正常 2：尿酸

            2 -> {
                highTime++
                highList.add(data.uaValue.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]
    }

    /**
     * 初始化 曲线
     */
    private fun initChart(list: MutableList<UricAcidInfoBean.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

            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=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, "μmol/L",
                IMarkView.MarkPage.UricAcid
            )
            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.uaValue,
                    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, "μmol/L",
                IMarkView.MarkPage.UricAcid
            )
            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.uaValue,
                    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<UricAcidInfoBean.Model>): MutableList<MutableList<UricAcidInfoBean.Model>> {
        val segments = mutableListOf<MutableList<UricAcidInfoBean.Model>>()
        var currentSegment = mutableListOf<UricAcidInfoBean.Model>()

        for (model in dataList) {
            if (model.uaValue.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<UricAcidInfoBean.Model>>): MutableList<MutableList<UricAcidInfoBean.Model>> {
        when (type) {
            1 -> {
                if (segmentsCompare[0][0].time != "00:00") {
                    val d = mutableListOf<UricAcidInfoBean.Model>()
                    val b = UricAcidInfoBean.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<UricAcidInfoBean.Model>()
                    val b = UricAcidInfoBean.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<UricAcidInfoBean.Model>()
                    val b = UricAcidInfoBean.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<UricAcidInfoBean.Model>()
                    val b = UricAcidInfoBean.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<UricAcidInfoBean.Model>()
                    val b = UricAcidInfoBean.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<UricAcidInfoBean.Model>()
                    val b = UricAcidInfoBean.Model(0f, "$month-$daysInMonth")
                    d.add(b)
                    segmentsCompare.add(d)
                }
            }

            4 -> {
                if (segmentsCompare[0][0].time != "01") {
                    val d = mutableListOf<UricAcidInfoBean.Model>()
                    val b = UricAcidInfoBean.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<UricAcidInfoBean.Model>()
                    val b = UricAcidInfoBean.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(":")
                val hours = parts[0].toInt()
                val 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 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()
        val day = TimeUtils.date2String(currentDay, "yyyy-MM-dd")
        weekDate = "${TimeUtils.date2String(getDateAdd(6), "yyyy-MM-dd")}至$day"
        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 = weekDate
                        type = 2
                    }

                    1 -> {  //月
                        binding.tvShowDate.text = mouthDate
                        type = 3
                    }

                    2 -> {  //年
                        binding.tvShowDate.text = yearDate
                        type = 4
                    }
                }
                mViewModel.getUricAcidInfo(
                    type,
                    binding.tvShowDate.text.toString(),
                    id,
                    isDemonstrate
                )
            }

            override fun onTabReselect(position: Int) {
            }

        })
    }

    private fun initTimeSelect() {

        val currentDay = Date()
        val day = TimeUtils.date2String(currentDay, "yyyy-MM-dd")
        weekDate = "${TimeUtils.date2String(getDateAdd(6), "yyyy-MM-dd")}至$day"
        binding.tvShowDate.text = weekDate

        binding.tvShowDate.setOnClickListener {
            when (type) {

                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.getUricAcidInfo(
                        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
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onRefresh(event: NSuanOpenEvent) {
        Log.e("simon", event.toString())
        loadData()
    }
}