SleepReportCell.swift 12.7 KB
//
//  SleepReportCell.swift
//  Twear
//
//  Created by yangbin on 2022/1/1.
//

import UIKit
import Charts
import SwiftDate

class SleepReportCell: UICollectionViewCell {
    
    @IBOutlet weak var barChartView: BarChartView!
    @IBOutlet weak var deepLabel: UILabel!
    @IBOutlet weak var lightLabel: UILabel!
    @IBOutlet weak var awakeLabel: UILabel!
    @IBOutlet weak var lengthLabel: UILabel!
    @IBOutlet weak var dateLabel: UILabel!
    
    lazy private var monthDays = DateInRegion().monthDays
    private var sleepArray: [SleepModel] = []
    
    @IBOutlet weak var locLabel1: UILabel!
    @IBOutlet weak var locLabel2: UILabel!
    @IBOutlet weak var locLabel3: UILabel!
    @IBOutlet weak var locLabel4: UILabel!
    
    private var sleepSummaryArray: [SleepSummary] = []
    private var barWidth: Double = 1.0/60.0
    var dateType: DateType = .day {
        didSet {
            updateChartView()
        }
    }
    
    
    private func updateChartView() {
        setupChartView()
        let nowDate = DateInRegion().date
        switch dateType {
        case .day:
            sleepArray = SleepModel.getSleepByDay(nowDate)
            dateLabel.text = nowDate.dateAt(.startOfDay).toString(.custom("yyyy.MM.dd"))
        case .week:
            sleepSummaryArray = SleepModel.getSleepByWeek(nowDate)
            dateLabel.text = ((nowDate-1.days).dateAt(.startOfWeek)+1.days).toString(.custom("MM.dd")) + "-" + ((nowDate-1.days).dateAt(.endOfWeek)+1.days).toString(.custom("MM.dd"))
        case .month:
            sleepSummaryArray = SleepModel.getSleepByMonth(nowDate)
            dateLabel.text = nowDate.toString(.custom("yyyy.MM"))
        case .year:
            sleepSummaryArray = SleepModel.getSleepByYear(nowDate)
            dateLabel.text = "\(nowDate.year).01-\(nowDate.year).12"
        }
//        let startDate = nowDate.dateAtStartOf(.day)
//        sleepArray = [SleepModel(type: .light, startDate: startDate+10.minutes, endDate: startDate+30.minutes), SleepModel(type: .awake, startDate: startDate+30.minutes, endDate: startDate+100.minutes), SleepModel(type: .light, startDate: startDate+100.minutes, endDate: startDate+160.minutes), SleepModel(type: .deep, startDate: startDate+160.minutes, endDate: startDate+500.minutes), SleepModel(type: .awake, startDate: startDate+500.minutes, endDate: startDate+540.minutes)]
        
        if dateType == .day {
            if sleepArray.count == 0 {
                resetLabel()
            } else {
                let sleep = SleepModel.querySleepPercentage(sleepArray)
                updateLable(length: sleep.length, awake: sleep.awake_pct, deep: sleep.deep_pct, light: sleep.light_pct)
            }
        } else {
            if sleepSummaryArray.count == 0 {
                resetLabel()
            } else {
                updateLable(length: sleepSummaryArray.average(\.sleepLength), awake: sleepSummaryArray.average(\.awake_pct), deep: sleepSummaryArray.average(\.deep_pct), light: sleepSummaryArray.average(\.light_pct))
            }
        }
        if dateType == .day {
            barChartView.leftAxis.valueFormatter = IndexAxisValueFormatter(values: [LocString(""), LocString(""), LocString("")])
            barChartView.leftAxis.yOffset = -30
            barChartView.leftAxis.axisMaximum = 3
            var awakeEntries = [BarChartDataEntry]()
            var deepEntries = [BarChartDataEntry]()
            var lightEntries = [BarChartDataEntry]()
//            var emptyEntries = [BarChartDataEntry]()
            let xAxis = barChartView.xAxis
            var startPoint: Double = 0
//            var sleepXValues: [String] = []
            if let startDate = sleepArray.first?.startDate, let endDate =  sleepArray.last?.endDate {
                startPoint = Double(startDate.hour) + Double(startDate.minute)/60.0
                if startPoint > 20 {
                    startPoint = startPoint - 24
                }
                var endPoint = Double(endDate.hour) + Double(endDate.minute)/60.0
                if endPoint > 20 {
                    endPoint = endPoint - 24
                }
            
                xAxis.labelCount = 2
                xAxis.axisMinimum = -0.8012345
                xAxis.axisMaximum = (endPoint - startPoint) + 0.5
                xAxis.valueFormatter = CDTimeAxisValueFormatter(min: -0.8012345, max: (endPoint - startPoint) + 0.5, labelCount: 2, values: [startDate.toString(.custom("HH:mm")), endDate.toString(.custom("HH:mm"))])
                
            } else {
                xAxis.labelCount = 2
                xAxis.axisMinimum = -0.8012345
                xAxis.axisMaximum = 11.5
                xAxis.valueFormatter = CDTimeAxisValueFormatter(min: -0.8012345, max: 11.5, labelCount: 2, values: ["22:00", "09:00"])
            }
            
            for sleep in sleepArray {
                var startX = Double(sleep.startDate!.hour) + Double(sleep.startDate!.minute)/60.0
                if startX > 20 {
                    startX = startX - 24
                }
                startX = startX - startPoint
//                let startX = Double(sleep.startDate!.hour) + Double(sleep.startDate!.minute)/60.0
                for n in 0..<sleep.length {
                    let pointX = startX+Double(n)*barWidth
                    switch sleep.type {
                    case .awake:
                        awakeEntries.append(BarChartDataEntry(x: pointX, yValues: [0.2, 0.6]))
                    case .deep:
                        deepEntries.append(BarChartDataEntry(x: pointX, yValues: [2.2, 0.6]))
                    case .light:
                        lightEntries.append(BarChartDataEntry(x: pointX, yValues: [1.2, 0.6]))
                    default:
                        break
                    }
//                    emptyEntries.append(BarChartDataEntry(x: pointX, y: 3))
                }
            }
            
//            let highlightSet = BarChartDataSet(entries: emptyEntries)
//            highlightSet.colors = [.white]
//            highlightSet.highlightEnabled = false
//            highlightSet.highlightColor = UIColor.rgbColorFromHex(0x9B0AFB)
            
            let awakeSet = BarChartDataSet(entries: awakeEntries)
            awakeSet.colors = [.white, UIColor.rgbColorFromHex(0xFF8875)]
            awakeSet.drawValuesEnabled = false
            awakeSet.highlightEnabled = false
            
            let lightSet = BarChartDataSet(entries: lightEntries)
            lightSet.colors = [.white, UIColor.rgbColorFromHex(0xD742C4)]
            lightSet.drawValuesEnabled = false
            lightSet.highlightEnabled = false
            
            let deepSet = BarChartDataSet(entries: deepEntries)
            deepSet.colors = [.white, UIColor.rgbColorFromHex(0x9733ED)]
            deepSet.drawValuesEnabled = false
            deepSet.highlightEnabled = false
            
            let chartData = BarChartData(dataSets: [awakeSet, lightSet, deepSet])
            chartData.barWidth = barWidth*1.5
            barChartView.data = chartData
            
        } else {
            barChartView.leftAxis.valueFormatter = nil
            barChartView.leftAxis.yOffset = -5
            barChartView.leftAxis.axisMaximum = 12
            var dataEntries = [BarChartDataEntry]()
            var barWidth: Double = 0.6
            for sleep in sleepSummaryArray {
                if sleep.sleepLength > 0 {
                    var pointX: Double = 0
                    switch dateType {
                    case .day:
                        break
                    case .week:
                        barWidth = 0.25
                        pointX = Double(sleep.endDate!.weekIndex)
                    case .month:
                        pointX = Double(sleep.endDate!.day-1)
                    case .year:
                        barWidth = 0.4
                        pointX = Double(sleep.endDate!.month-1)
                    }
                    
                    dataEntries.append(BarChartDataEntry(x: pointX, y: Double(sleep.light+sleep.deep)/60))
                }
            }
            let dataSet = BarChartDataSet(entries: dataEntries)
            dataSet.colors = [UIColor.rgbColorFromHex(0x9733ED)]
            dataSet.highlightEnabled = false
            dataSet.highlightColor = UIColor.rgbColorFromHex(0x9B0AFB)
            dataSet.drawValuesEnabled = false
            let chartData = BarChartData(dataSets: [dataSet])
            chartData.barWidth = barWidth
            barChartView.data = chartData
        }
        
        
        
        
    }
    
    
    private func setupChartView() {
        
        barChartView.chartDescription?.enabled = false //图描述
        barChartView.legend.enabled = false //左下角图例
        barChartView.setScaleEnabled(false) //可滑动
        barChartView.rightAxis.enabled = false //不绘制右边轴的信息
        
        let leftAxis = barChartView.leftAxis
        leftAxis.labelTextColor = ChartsTextColor
        leftAxis.labelFont = ChartsTextFont(11)
        
        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 = 0 //设置左侧Y轴最小值
        
        leftAxis.granularity = 1
        
        let litmitLine = ChartLimitLine(limit: 0, label: "")
        litmitLine.lineWidth = 1
        litmitLine.lineColor = LineColor
        leftAxis.addLimitLine(litmitLine)
        leftAxis.drawLimitLinesBehindDataEnabled = false  //设置限制线绘制在折线图的后面
        
        
        let xAxis = barChartView.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
        
        
        switch dateType {
        case .day:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: DayXValues)
            xAxis.labelCount = 9
//            if sleepArray.count > 0 {
                xAxis.axisMinimum = -0.8
                xAxis.axisMaximum = 9.5
//            } else {
//                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
        }
        
    }
    
    private func resetLabel() {
        lengthLabel.toTimeType2(length: -1, 25, 15)
        deepLabel.toUnitMode(text: "--", unit: "%", font: BoldFont(23), unitFont: RegularFont(13))
        awakeLabel.toUnitMode(text: "--", unit: "%", font: BoldFont(23), unitFont: RegularFont(13))
        lightLabel.toUnitMode(text: "--", unit: "%", font: BoldFont(23), unitFont: RegularFont(13))
    }
    
    
    private func updateLable(length: Int, awake: Int, deep: Int, light: Int) {
        lengthLabel.toTimeType2(length: length, 25, 15)
        deepLabel.toUnitMode(text: "\(deep)", unit: "%", font: BoldFont(23), unitFont: RegularFont(13))
        awakeLabel.toUnitMode(text: "\(awake)", unit: "%", font: BoldFont(23), unitFont: RegularFont(13))
        lightLabel.toUnitMode(text: "\(light)", unit: "%", font: BoldFont(23), unitFont: RegularFont(13))
        
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        if (AppSettings.shared.language == .Chinese || AppSettings.shared.language == .English || AppSettings.shared.language == .Japanese) {
            locLabel1.font = RegularFont(13)
            locLabel2.font = RegularFont(13)
            locLabel3.font = RegularFont(13)
            locLabel4.font = RegularFont(13)
        } else {
            locLabel1.font = RegularFont(10)
            locLabel2.font = RegularFont(10)
            locLabel3.font = RegularFont(10)
            locLabel4.font = RegularFont(10)
        }
    }
    
}