//
//  ChartPointsContextFillLayer.swift
//  Loop
//
//  Copyright © 2017 LoopKit Authors. All rights reserved.
//

import SwiftCharts
import CoreGraphics
import UIKit

struct ChartPointsFill {
    let chartPoints: [ChartPoint]
    let fillColor: UIColor
    let createContainerPoints: Bool
    let blendMode: CGBlendMode
    fileprivate var screenPoints: [CGPoint] = []

    init?(chartPoints: [ChartPoint], fillColor: UIColor, createContainerPoints: Bool = true, blendMode: CGBlendMode = .normal) {
        guard chartPoints.count > 1 else {
            return nil;
        }

        var chartPoints = chartPoints

        if createContainerPoints {
            // Create a container line at value position 0
            if let first = chartPoints.first {
                chartPoints.insert(ChartPoint(x: first.x, y: ChartAxisValueInt(0)), at: 0)
            }

            if let last = chartPoints.last {
                chartPoints.append(ChartPoint(x: last.x, y: ChartAxisValueInt(0)))
            }
        }

        self.chartPoints = chartPoints
        self.fillColor = fillColor
        self.createContainerPoints = createContainerPoints
        self.blendMode = blendMode
    }

    var areaPath: UIBezierPath {
        let path = UIBezierPath()

        if let point = screenPoints.first {
            path.move(to: point)
        }

        for point in screenPoints.dropFirst() {
            path.addLine(to: point)
        }

        return path
    }
}


final class ChartPointsFillsLayer: ChartCoordsSpaceLayer {
    let fills: [ChartPointsFill]

    init?(xAxis: ChartAxis, yAxis: ChartAxis, fills: [ChartPointsFill?]) {
        self.fills = fills.compactMap({ $0 })

        guard fills.count > 0 else {
            return nil
        }

        super.init(xAxis: xAxis, yAxis: yAxis)
    }

    override func chartInitialized(chart: Chart) {
        super.chartInitialized(chart: chart)

        let view = ChartPointsFillsView(
            frame: chart.bounds,
            chartPointsFills: fills.map { (fill) -> ChartPointsFill in
                var fill = fill

                fill.screenPoints = fill.chartPoints.map { (point) -> CGPoint in
                    return modelLocToScreenLoc(x: point.x.scalar, y: point.y.scalar)
                }

                return fill
            }
        )

        chart.addSubview(view)
    }
}


class ChartPointsFillsView: UIView {
    let chartPointsFills: [ChartPointsFill]
    var allowsAntialiasing = false

    init(frame: CGRect, chartPointsFills: [ChartPointsFill]) {
        self.chartPointsFills = chartPointsFills

        super.init(frame: frame)

        backgroundColor = .clear
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else { return }

        context.saveGState()
        context.setAllowsAntialiasing(allowsAntialiasing)

        for fill in chartPointsFills {
            context.setFillColor(fill.fillColor.cgColor)
            fill.areaPath.fill(with: fill.blendMode, alpha: 1)
        }

        context.restoreGState()
    }
}
