import AppKit

class CircularProgressView: NSView {
    private var _value: CGFloat = 0.0
    var value: CGFloat {
        get { _value }
        set {
            if newValue > maxValue {
                _value = 1.0
            } else if newValue < minValue {
                _value = 0.0
            } else {
                _value = newValue / maxValue
            }
            advanceProgress(to: _value)
        }
    }
    var minValue: Double = 0
    var maxValue: Double = 1

    var animationSpeed: Double = 0.5
    var backgroundColor: NSColor = NSColor.darkGray
    var foregroundColor: NSColor = NSColor.systemBlue

    private let backgroundLayer = CAShapeLayer()
    private let foregroundLayer = CAShapeLayer()

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
        drawCirlces()
    }

    override func layout() {
        super.layout()
        foregroundLayer.frame = bounds
    }

    private func drawCirlces() {
        let lineWidth = bounds.width * 0.3

        let bgMutablePath = CGMutablePath()
        bgMutablePath.addArc(
            center: CGPoint(x: bounds.midX, y: bounds.midY),
            radius: min(bounds.width, bounds.height) / 2 - (lineWidth / 2),
            startAngle: CGFloat.zero, endAngle: CGFloat(2 * Double.pi),
            clockwise: true
        )
        backgroundLayer.path = bgMutablePath
        backgroundLayer.fillColor = NSColor.clear.cgColor
        // backgroundLayer.strokeColor =
        //     NSColor(name: nil) {
        //         getColors(.lightGray, .darkGray, for: $0)
        //     }.cgColor
        backgroundLayer.strokeColor = backgroundColor.cgColor
        backgroundLayer.lineWidth = lineWidth

        let fgMutablePath = CGMutablePath()
        fgMutablePath.addArc(
            center: CGPoint(x: bounds.midX, y: bounds.midY),
            radius: min(bounds.width, bounds.height) / 2 - (lineWidth / 2),
            startAngle: CGFloat.zero, endAngle: CGFloat(2 * Double.pi),
            clockwise: true
        )
        foregroundLayer.path = fgMutablePath
        foregroundLayer.fillColor = NSColor.clear.cgColor
        foregroundLayer.strokeColor = foregroundColor.cgColor
        foregroundLayer.lineCap = .round
        foregroundLayer.lineWidth = lineWidth
        foregroundLayer.strokeEnd = value
        foregroundLayer.transform =
            CATransform3DMakeRotation(CGFloat(Double.pi / 2), 0, 0, 1)

        layer?.addSublayer(backgroundLayer)
        layer?.addSublayer(foregroundLayer)
    }

    private func advanceProgress(to value: Double) {
        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.duration = animationSpeed
        animation.fromValue =
            foregroundLayer.presentation()?.value(forKeyPath: "strokeEnd")
            ??
            value
        animation.toValue = value
        foregroundLayer.strokeEnd = CGFloat(value)
        foregroundLayer.add(animation, forKey: "pathAnimation")
    }
}
