StepViewController.swift 13.6 KB
//
//  StepViewController.swift
//  Twear
//
//  Created by yangbin on 2021/11/19.
//

import UIKit
import Charts
import SwiftDate

class StepViewController: 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 stepLabel: UILabel!
    @IBOutlet weak var calorieLabel: UILabel!
    @IBOutlet weak var dayStepLabel: UILabel!
    @IBOutlet weak var analysisLabel: UILabel!
    
    @IBOutlet weak var stepsGoalLabel: UILabel!
    @IBOutlet weak var stepSliderLabel: UILabel!
    @IBOutlet weak var goalPerLabel: UILabel!
    @IBOutlet weak var stepProgressView: StepProgressView!
    
    @IBOutlet weak var circleProgress1: CircleProgressView!
    @IBOutlet weak var circleProgress2: CircleProgressView!
    @IBOutlet weak var circleProgress3: CircleProgressView!
    @IBOutlet weak var circleProgress4: CircleProgressView!
    @IBOutlet weak var circleProgress5: CircleProgressView!
    @IBOutlet weak var circleProgress6: CircleProgressView!
    @IBOutlet weak var circleProgress7: CircleProgressView!
    
    private var dateType: DateType = .day
    let user = UserInfo
    
    private var selectedXValue: Double = 0
    private var selectedDate = Date()
    lazy private var monthDays = DateInRegion().monthDays
    
    private var points: [Double] = []
//    private var maxStep = 11000
    
    private var stepArray: [StepModel] = [] {
        didSet {
            if stepArray.count == 0 {
                resetLabel()
            } else {
                stepLabel.text = "\(stepArray.first?.number ?? 0)"
            }
            points = []
//            let goal = StepsGoal
            
            let step = stepArray.max{$0.number < $1.number}
            let maxStep = step?.number ?? user.stepsGoal
            if dateType != .day && maxStep != 0 {
                lineChartView.leftAxis.axisMaximum = Double(maxStep) * 1.2
            } else {
                lineChartView.leftAxis.axisMaximum = Double(user.stepsGoal)
            }
        }
    }
    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(0x3EE1CD)
        dateSegmentView.delegate = self
        sliderView.delegate = self
        BluetoothManager.shared.registerSyncDelegate(self)
        updateWeekProgress()
        view.layoutIfNeeded()
        setupChartView()
        didSelectedDate(date: DateInRegion(), dateType: .day)
    }
    
    private func updateWeekProgress() {
        let progressArray: [CircleProgressView] = [circleProgress1, circleProgress2, circleProgress3, circleProgress4, circleProgress5, circleProgress6, circleProgress7]
        let array = StepModel.getLastWeekSteps()
        for (i, step) in array.enumerated() {
            progressArray[i].label.text = step.date!.toString(.custom("MM/dd"))
            progressArray[i].value = step.percent
        }
    }
    
    func didReceiveStep() {
        didSelectedDate(date: DateInRegion(selectedDate), dateType: dateType)
    }
 
    //MARK: DateSegmentViewDelegate
    func didSelectedDate(date: DateInRegion, dateType: DateType) {
        self.dateType = dateType
        monthDays = date.monthDays
        selectedDate = date.date
        
        switch dateType {
        case .day:
            stepArray = StepModel.getStepsByDay(selectedDate)
            dateLabel.text = date.dateAt(.startOfDay).toString(.custom("HH:mm"))
        case .week:
            stepArray = StepModel.getStepsByWeek(selectedDate)
            dateLabel.text = (date.dateAt(.startOfWeek)+1.days).toString(.custom("yyyy.MM.dd")) + " 周一"
        case .month:
            stepArray = StepModel.getStepsByMonth(selectedDate)
            dateLabel.text = date.dateAt(.startOfMonth).toString(.custom("yyyy.MM.dd"))
        case .year:
            stepArray = StepModel.getStepsByYear(selectedDate)
            dateLabel.text = date.dateAtStartOf(.year).toString(.custom("yyyy.MM"))
        }
        
        updateChartView()
        setupSliderViewScale()
    }
    
    //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 stepArray.count == 1 {
            lineChartView.highlightValues([Highlight(x: points[0], y: 0, dataSetIndex: 0)])
        } else {
            sliderView.didSelectedValue(entry.x)
        }
    }
    @IBAction func share(_ sender: Any) {
        let shareView = ShareView(view.captureImage)
        shareView.show()
    }
    
    private func resetLabel() {
        stepLabel.text = "--"
        dayStepLabel.text = "--"
        calorieLabel.text = "--"
        updateProgressView(StepModel())
        analysisLabel.text = "\(LocString("亲,您已超过"))0%\(LocString("的同类用户"))"
    }

    private func updateProgressView(_ step: StepModel) {
        stepsGoalLabel.text = "\(user.stepsGoal)"
        stepSliderLabel.text = "\(step.number)"
//        let per = step.percent
        goalPerLabel.text = "\(step.percent)%"
        stepProgressView.value = step.percent
    }
    
    private func updateLable(_ index: Int) {
        if stepArray.count == 0 {//||  stepArray[index].number == 0 {
            resetLabel()
            return
        }
   
//        updateProgressView(stepArray[index])
        stepLabel.text = "\(stepArray[index].number)"
//        dayStepLabel.text =
        calorieLabel.text = "\(String(format:"%.2f", stepArray[index].calorie))"
        if dateType == .day {
            if stepArray.count > 0, let step = stepArray.last {
                dayStepLabel.text = "\(step.number)"
                updateProgressView(step)
            }
        } else {
            dayStepLabel.text = "\(stepArray[index].number)"
        }
        
        let sDate = stepArray[index].date!
        var number = stepArray[index].number
        switch dateType {
        case .day:
            dateLabel.text = sDate.toString(.custom("HH:mm"))
            number = stepArray.last?.number ?? 0
        case .week:
            dateLabel.text = sDate.toString(.custom("yyyy.MM.dd")) + " " + sDate.weekText
        case .month:
            dateLabel.text = sDate.toString(.custom("yyyy.MM.dd"))
        case .year:
            dateLabel.text = sDate.toString(.custom("yyyy.MM"))
        }
        var per: String = "0"
        
        
        switch number {
        case 0..<100:
            per = "0"
        case 100..<8000:
            per = String(format:"%.1f",Float(number)/100)
        case 8000..<10000:
            per = String(format:"%.1f",80+Float(number)/200)
        case 10000..<20000:
            per = String(format:"%.1f",90+Float(number)/1000)
        default:
            per = "99.9"
        }
        
        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 step in stepArray {
//            if step.number > 0 {
                var pointX: Double = 0
                switch dateType {
                case .day:
                    if step.date!.hour == 23 {
                        pointX = 24
                    } else {
                        pointX = Double((step.date!+1.hours).hour)+Double(step.date!.minute)/60.0
                    }
                case .week:
                    pointX = Double(step.date!.weekIndex)
                case .month:
                    pointX = Double(step.date!.day-1)
                case .year:
                    pointX = Double(step.date!.month-1)
                }
                points.append(pointX)
            
                dataEntries.append(ChartDataEntry(x: pointX, y: Double(step.number)))
//            }
        }
        
        if stepArray.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(0x1DDCC5)// 十字线颜色
        dataSet.drawHorizontalHighlightIndicatorEnabled = false
        dataSet.mode = .horizontalBezier
        dataSet.setColor(UIColor.rgbColorFromHex(0x1DDCC5))
//        if dataEntries.count == 1 {
//            dataSet.lineWidth = 5
//        } else {
            dataSet.lineWidth = 1
//        }
        
        dataSet.drawFilledEnabled = true //填充绘制
        let gradientColors = [UIColor.rgbColorFromHex(0x1DDCC5).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)])
    }
    
    
    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_step", isLast: true)
 
    }
    

    private func getChartViewX(_ x: Int) -> CGFloat {
        return lineChartView.pixelForValues(x: Double(x), y: 0, axis: .left).x
    }
    
    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 = -4
        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.axisMaximum = 11000
        leftAxis.granularity = 500
        
        let litmitLine = ChartLimitLine(limit: 0, 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: "StepReferenceVC")
        navigationController?.pushViewController(vc, animated: true)
    }
    
    @IBAction func gotoMotionVC(_ sender: Any) {
        navigationController?.tabBarController?.selectedIndex = 1
        self.navigationController?.popToRootViewController(animated: false)
        
    }
    
    @IBAction func back(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
    
    deinit {
        print("deinit\(NSStringFromClass(type(of: self)))!!!!!!!")
    }


}