BloodOxygenVC.swift 12.2 KB
//
//  BloodOxygenVC.swift
//  Twear
//
//  Created by yangbin on 2021/11/25.
//

import UIKit
import Charts
import SwiftDate

class BloodOxygenVC: UIViewController, DateSegmentViewDelegate, RangeSliderDelegate, ChartViewDelegate, BluetoothSyncDelegate {
    
    @IBOutlet weak var dateSegmentView: DateSegmentView!
    @IBOutlet weak var lineChartView: LineChartView!
    @IBOutlet weak var sliderView: RangeSliderView!
    @IBOutlet weak var dateLabel: UILabel!
    @IBOutlet weak var boLabel: UILabel!
    @IBOutlet weak var averageLabel: UILabel!
    @IBOutlet weak var hightLabel: UILabel!
    @IBOutlet weak var lowLabel: UILabel!
//    @IBOutlet weak var rangeLabel: UILabel!
    @IBOutlet weak var analysisLabel: UILabel!
    
    private var dateType: DateType = .day
    private var selectedDate = Date()
    private lazy var monthDays = DateInRegion().monthDays
    private var minArray: [Int] = []
    private var maxArray: [Int] = []
    private var points: [Double] = []
    
    
    private var boArray: [BloodOxygenModel] = [] {
        didSet {
            if boArray.count == 0 {
                resetLabel()
            }
            points = []
//            let bo = boArray.max{$0.value < $1.value}
//            let maxBo = max(bo?.value ?? 100, 100)
//            lineChartView.leftAxis.axisMaximum = Double(maxBo)
        }
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.setNavigationBarHidden(true, animated: true)
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        BluetoothManager.shared.unRegisterSyncDelegate(self)
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        dateSegmentView.selectedColor = UIColor.rgbColorFromHex(0xFF3600)
        dateSegmentView.delegate = self
        sliderView.delegate = self
        BluetoothManager.shared.registerSyncDelegate(self)
        
        view.layoutIfNeeded()
        setupChartView()
        didSelectedDate(date: DateInRegion(), dateType: .day)
    }
    
    func didReceiveBloodOxygen() {
        didSelectedDate(date: DateInRegion(selectedDate), dateType: dateType)
    }
    @IBAction func share(_ sender: Any) {
        let shareView = ShareView(view.captureImage)
        shareView.show()
    }
    //MARK: DateSegmentViewDelegate
    func didSelectedDate(date: DateInRegion, dateType: DateType) {
        self.dateType = dateType
        monthDays = date.monthDays
        selectedDate = date.date
        minArray = []
        maxArray = []
        
        var boResult: (boArray: [BloodOxygenModel], minBo: [Int], maxBo: [Int]) = ([], minArray, maxArray)
        switch dateType {
        case .day:
            boResult = BloodOxygenModel.getBloodOxygenByDay(selectedDate)
            dateLabel.text = date.dateAt(.startOfDay).toString(.custom("HH:mm"))
        case .week:
            boResult = BloodOxygenModel.getBloodOxygenByWeek(selectedDate)
            dateLabel.text = (date.dateAt(.startOfWeek)+1.days).toString(.custom("yyyy.MM.dd")) + " " + LocString("周一") + " " + LocString("平均血氧")
        case .month:
            boResult = BloodOxygenModel.getBloodOxygenByMonth(selectedDate)
            dateLabel.text = date.dateAt(.startOfMonth).toString(.custom("yyyy.MM.dd")) + " " + LocString("平均血氧")
        case .year:
            boResult = BloodOxygenModel.getBloodOxygenByYear(selectedDate)
            dateLabel.text = date.dateAtStartOf(.year).toString(.custom("yyyy.MM")) + " " + LocString("平均血氧")
        }
        
        minArray = boResult.minBo
        maxArray = boResult.maxBo
        boArray = boResult.boArray
        
        updateChartView()
        
    }
    
    //MARK: RangeSliderDelegate
    func sliderDidChanged(index: Int) {
        lineChartView.highlightValues([Highlight(x: points[index], y: 0, dataSetIndex: 0)])
        updateLable(index)
    }
    
    //MARK: ChartViewDelegate
    func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
        if boArray.count == 1 {
            lineChartView.highlightValues([Highlight(x: points[0], y: 0, dataSetIndex: 0)])
        } else {
            sliderView.didSelectedValue(entry.x)
        }
    }
    
    private func resetLabel() {
        boLabel.text = "--"
        averageLabel.text = "--"
//        rangeLabel.text = "--"
        hightLabel.text = "__"
        lowLabel.text = "__"
        analysisLabel.text = "\(LocString("亲,您已超过"))0%\(LocString("的同类用户"))"
    }
    
    private func updateLable(_ index: Int) {
        if boArray.count == 0 {
            resetLabel()
            return
        }
        
        if dateType == .day {
            let boResult = BloodOxygenModel.getAverageByDay(selectedDate)
            averageLabel.text = boResult.bo.value == -1 ? "--" : "\(boResult.bo.value)"
//            rangeLabel.text = "\(boResult.maxBo)-\(boResult.minBo)"
            hightLabel.text = "\(boResult.maxBo)"
            lowLabel.text = "\(boResult.minBo)"
        } else {
            averageLabel.text = boArray[index].value == -1 ? "--" : "\(boArray[index].value)"
//            rangeLabel.text = "\(maxArray[index])-\(minArray[index])"
            hightLabel.text = "\(maxArray[index])"
            lowLabel.text = "\(minArray[index])"
        }
        
        
        boLabel.text = "\(boArray[index].value)"
        
        let sDate = boArray[index].date!
        switch dateType {
        case .day:
            dateLabel.text = sDate.toString(.custom("HH:mm"))
        case .week:
            dateLabel.text = sDate.toString(.custom("yyyy.MM.dd")) + " " + sDate.weekText + " " + LocString("平均血氧")
        case .month:
            dateLabel.text = sDate.toString(.custom("yyyy.MM.dd")) + " " + LocString("平均血氧")
        case .year:
            dateLabel.text = sDate.toString(.custom("yyyy.MM")) + " " + LocString("平均血氧")
        }

       
        
        
        var per = "0"
        switch boArray[index].value {
        case 0..<60:
            per = "\(boArray[index].value)"
        case 60..<70:
            per = "\(60+(boArray[index].value-60)/2)"
        case 70..<80:
            per = "\(65+(boArray[index].value-70))"
        case 80..<90:
            per = "\(75+(boArray[index].value-80)/2)"
        case 90...110:
            per = "\(80+(boArray[index].value-90))"
        default:
            break
        }
        
        analysisLabel.text = "\(LocString("亲,您已超过"))\(per)%\(LocString("的同类用户"))"
    }
    
    
    private func updateChartView() {
        let xAxis = lineChartView.xAxis
        switch dateType {
        case .day:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: DayXValues)
            xAxis.labelCount = 9
            xAxis.axisMinimum = -2.9
            xAxis.axisMaximum = 24 + 2
        case .week:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: WeekXValues)
            xAxis.labelCount = 7
            xAxis.axisMinimum = -0.8
            xAxis.axisMaximum = 6 + 0.8
        case .month:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: MonthXValues(monthDays))
            xAxis.labelCount = 8
            xAxis.axisMinimum = -3.5
            xAxis.axisMinLabels = 8
            xAxis.axisMaximum = Double(monthDays-1) + 2.1
        case .year:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: MonthValues)
            xAxis.labelCount = 12
            xAxis.axisMinimum = -1.3
            xAxis.axisMaximum = 11 + 0.8
        }
        
        var dataEntries = [ChartDataEntry]()
        
        
        
        for bo in boArray {
            if bo.value > 0 {
                var pointX: Double = 0
                switch dateType {
                case .day:
                    pointX = Double(bo.date!.hour)+Double(bo.date!.minute)/60.0
                case .week:
                    pointX = Double(bo.date!.weekIndex)
                case .month:
                    pointX = Double(bo.date!.day-1)
                case .year:
                    pointX = Double(bo.date!.month-1)
                }
                points.append(pointX)
                dataEntries.append(ChartDataEntry(x: pointX, y: Double(bo.value)))
            }
        }
        
        
        if dataEntries.count == 1 {
            dataEntries.append(ChartDataEntry(x: dataEntries[0].x+0.2, y: dataEntries[0].y))
        }
        
        let dataSet = LineChartDataSet(entries: dataEntries)
        dataSet.drawCirclesEnabled = false
        dataSet.drawValuesEnabled = false
        dataSet.highlightEnabled = true//选中拐点,是否开启高亮效果(显示十字线)
        dataSet.highlightLineWidth = 1
        dataSet.highlightColor = UIColor.rgbColorFromHex(0xFF3600)// 十字线颜色
        dataSet.drawHorizontalHighlightIndicatorEnabled = false
        dataSet.mode = .horizontalBezier
        dataSet.setColor(UIColor.rgbColorFromHex(0xFF3600))
        dataSet.lineWidth = 1
        
        
        dataSet.drawFilledEnabled = true //填充绘制
        let gradientColors = [UIColor.rgbColorFromHex(0xD82D00).cgColor, UIColor.rgbColorFromHex(0xFFFFFF).cgColor]
        let gradient = CGGradient(colorsSpace: nil, colors: gradientColors as CFArray, locations: [1.0, 0.0])
        dataSet.fillAlpha = 1
        dataSet.fill = Fill(linearGradient: gradient!, angle: 90)
        lineChartView.data = LineChartData(dataSets: [dataSet])
        lineChartView.highlightValues([Highlight(x: 0, y: 0, dataSetIndex: 0)])
        
        
        setupSliderViewScale()
    }
    
    
    
    private func setupSliderViewScale() {
        var endPointX: Int = 0
        switch dateType {
        case .day:
            endPointX = 24
        case .week:
            endPointX = 6
        case .month:
            endPointX = monthDays-1
        case .year:
            endPointX = 11
        }
        sliderView.setDrawSpace(startPointX: getChartViewX(0), endPointX: getChartViewX(endPointX), range: 0...endPointX, points: points, imageName: "slider_bo", isLast: true)
    }
    
    private func getChartViewX(_ x: Int) -> CGFloat {
        return lineChartView.pixelForValues(x: Double(x), y: 0, axis: .left).x
    }
    
    private func setupChartView() {
        lineChartView.delegate = self
        lineChartView.chartDescription?.enabled = false //图描述
        lineChartView.legend.enabled = false //左下角图例
        lineChartView.setScaleEnabled(false) //可滑动
        lineChartView.rightAxis.enabled = false //不绘制右边轴的信息
        
        let leftAxis = lineChartView.leftAxis
        leftAxis.labelTextColor = ChartsTextColor
        leftAxis.labelFont = ChartsTextFont(11)
        leftAxis.yOffset = -5
        leftAxis.xOffset = -3
        leftAxis.gridLineDashLengths = [2.0, 2.0]  //设置虚线样式的网格线
        leftAxis.gridColor = LineColor
        leftAxis.gridLineWidth = 1
        leftAxis.axisLineWidth = 0
        leftAxis.drawGridLinesBehindDataEnabled = false
        leftAxis.labelPosition = .insideChart
        
        leftAxis.axisMinimum = 90 //设置左侧Y轴最小值
        leftAxis.axisMaximum = 100
        leftAxis.granularity = 2
        
        let litmitLine = ChartLimitLine(limit: 90, label: "")
        litmitLine.lineWidth = 1
        litmitLine.lineColor = LineColor
        leftAxis.addLimitLine(litmitLine)
        leftAxis.drawLimitLinesBehindDataEnabled = false  //设置限制线绘制在折线图的后面
        
        
        let xAxis = lineChartView.xAxis
        xAxis.granularity = 1 //间隔
        xAxis.labelPosition = .bottom
        xAxis.labelFont = ChartsTextFont(11)
        xAxis.labelTextColor = ChartsTextColor
        xAxis.drawGridLinesBehindDataEnabled = false
        xAxis.axisLineColor = LineColor
        xAxis.axisLineWidth = 1
        xAxis.gridLineDashLengths = [6, 666]
        xAxis.gridColor = LineColor
        xAxis.drawAxisLineEnabled = false
    }
    @IBAction func gotoReferenceVC(_ sender: Any) {
        let vc = UIStoryboard.loadViewControllerIdentifier(storyboardName: "Home", identifier: "BOReferenceVC")
        navigationController?.pushViewController(vc, animated: true)
    }
    
    @IBAction func back(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
    

}