//
//  Star.swift
//  MVMCoreUI
//
//  Created by Lekshmi S on 15/09/20.
//  Copyright © 2020 Verizon Wireless. All rights reserved.
//

@objcMembers open class Star: View {
    
    //--------------------------------------------------
    // MARK: - Properties
    //--------------------------------------------------
    private var starLayer: CAShapeLayer?
    private var progressLayer: CAShapeLayer?
    private let maskLayer = CAShapeLayer()
    public var starModel: StarModel? {
        return model as? StarModel
    }
    @Percent public var percent = 0 {
        didSet {
            updateAccessibilityLabel()
            setNeedsDisplay()
        }
    }
    public var size: CGFloat = 30 {
        didSet {
            widthConstraint?.constant = size
            setNeedsDisplay()
        }
    }
    public var fillColor = UIColor.mvmBlack {
        didSet {
            setNeedsDisplay()
        }
    }
    public var borderColor: CGColor = UIColor.mvmBlack.cgColor {
        didSet {
            setNeedsDisplay()
        }
    }
    
    //--------------------------------------------------
    // MARK: - Constraints
    //--------------------------------------------------
    public var widthConstraint: NSLayoutConstraint?
    public var heightConstraint: NSLayoutConstraint?
    
    //------------------------------------------------------
    // MARK: - State Handling
    //------------------------------------------------------
    open override func draw(_ rect: CGRect) {
        //Draw progress
        progressLayer?.removeFromSuperlayer()
        let progress = drawProgress()
        layer.addSublayer(progress)
        progressLayer = progress
        
        //Draw the star
        starLayer?.removeFromSuperlayer()
        let star = drawStar()
        layer.addSublayer(star)
        starLayer = star
        
        //Mask the star
        maskLayer.removeFromSuperlayer()
        maskLayer.path = star.path
        layer.mask = maskLayer
    }
    
    func drawProgress() -> CAShapeLayer {
        let shapeLayer = CAShapeLayer()
        let width = bounds.size.width * percent / 100.0
        shapeLayer.path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: width, height: bounds.height)).cgPath
        shapeLayer.fillColor = fillColor.cgColor
        return shapeLayer
    }
    
    func drawStar() -> CAShapeLayer {
        let shapeLayer = CAShapeLayer()
        shapeLayer.frame = bounds
        let starPath = UIBezierPath()
        let center = shapeLayer.position
        let theta = .pi / CGFloat(5.0)
        let outerRadius = center.x * 1.039
        let excessRadius = outerRadius - center.x
        let innerRadius = CGFloat(outerRadius * 0.382)
        let leftEdgePointX = (center.x + cos(4.0 * theta) * outerRadius) + excessRadius
        let horizontalOffset = leftEdgePointX / 2.0
        let offsetCenter = CGPoint(x: center.x - horizontalOffset, y: center.y)
        for i in 0 ..< 10 {
            let radius = i % 2 == 0 ? outerRadius : innerRadius
            let pointX = offsetCenter.x + cos(CGFloat(i) * theta) * radius
            let pointY = offsetCenter.y + sin(CGFloat(i) * theta) * radius
            let point = CGPoint(x: pointX, y: pointY)
            if i == 0 {
                starPath.move(to: point)
            } else {
                starPath.addLine(to: point)
            }
        }
        starPath.close()
        // Rotate the path so the star points up as expected
        var pathTransform  = CGAffineTransform.identity
        pathTransform = pathTransform.translatedBy(x: center.x, y: center.y)
        pathTransform = pathTransform.rotated(by: CGFloat(-.pi / 2.0))
        pathTransform = pathTransform.translatedBy(x: -center.x, y: -center.y)
        starPath.apply(pathTransform)
        shapeLayer.path = starPath.cgPath
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.opacity = 1.0
        shapeLayer.lineWidth = 1
        shapeLayer.strokeColor = borderColor
        return shapeLayer
    }
    
    //--------------------------------------------------
    // MARK: - MoleculeViewProtocol
    //--------------------------------------------------
    open override func reset() {
        super.reset()
        borderColor = UIColor.mvmBlack.cgColor
        fillColor = .mvmBlack
        percent = 0
    }
    
    public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
        super.set(with: model, delegateObject, additionalData)
        guard let model = model as? StarModel else { return }
        percent = model.percent
        if let fillColor = model.fillColor?.uiColor {
            self.fillColor = fillColor
        }
        if let borderColor = model.borderColor?.cgColor {
            self.borderColor = borderColor
        }
        size = model.size
        updateAccessibilityLabel()
    }
    
    //--------------------------------------------------
    // MARK: - MVMCoreViewProtocol
    //--------------------------------------------------
    open override func setupView() {
        super.setupView()
        backgroundColor = .clear
        widthConstraint = widthAnchor.constraint(equalToConstant: 30)
        widthConstraint?.isActive = true
        heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1)
        heightConstraint?.isActive = true
        isAccessibilityElement = true
        updateAccessibilityLabel()
    }
    
    // MARK: - Accessibility
    func updateAccessibilityLabel() {
        accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "star")
        accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "star_percent") ?? "", Int(percent))
    }
}
