//
//  Wheel.swift
//  MobileFirstFramework
//
//  Created by Ryan on 10/24/19.
//  Copyright © 2019 Verizon Wireless. All rights reserved.
//

import UIKit

@objcMembers open class Wheel: View, MVMCoreUIViewConstrainingProtocol {
    
    var heightConstraint: NSLayoutConstraint?
    weak var gradientLayer: CALayer?
    var graphModel: WheelModel? {
        return model as? WheelModel
    }
    
// MARK: setup
    open override func setupView() {
        super.setupView()
        heightConstraint = heightAnchor.constraint(equalToConstant: 0)
        heightConstraint?.isActive = true
        widthAnchor.constraint(equalTo: heightAnchor).isActive = true
    }

    override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
        super.set(with: model, delegateObject, additionalData)
        guard let model = model as? WheelModel else { return }
        createGraphCircle(model)
        rotationAnimation(model)
    }
    
    class func getAngle(_ piValue: Double) -> Double {
        return piValue / (2.0 * Double.pi) * 360.0
    }
    
    class func getPiValue(_ angle: Double) -> Double {
        return angle / 360.0 * 2.0 * Double.pi
    }
    
// MARK: circle
    open func createGraphCircle(_ graphObject: WheelModel) {
        if let sublayers = layer.sublayers {
            for sublayer in sublayers {
                sublayer.removeAllAnimations()
                sublayer.removeFromSuperlayer()
            }
        }
        heightConstraint?.constant = graphObject.diameter
        
        let gradient = CAGradientLayer()
        gradient.type = .conic
        gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
        gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
        gradient.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
        gradient.colors = graphObject.colors.map({ (color) -> CGColor in
            return color.cgColor
        })
        gradientLayer = gradient
        layer.addSublayer(gradient)
        
        let center = CGPoint(x: gradient.bounds.midX, y: gradient.bounds.midY)
        let radius = (graphObject.diameter - graphObject.lineWidth) / 2.0
        let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: (3 / 2 * .pi), endAngle: -(1 / 2 * .pi), clockwise: false)
        let mask = CAShapeLayer()
        mask.fillColor = UIColor.clear.cgColor
        mask.strokeColor = UIColor.white.cgColor
        mask.lineWidth = graphObject.lineWidth
        mask.path = path.cgPath
        gradient.mask = mask
    }
    
//MARK: MVMCoreUIViewConstrainingProtocol
    public func needsToBeConstrained() -> Bool {
        return true
    }
    
//MARK: Animation
    func rotationAnimation(_ object: WheelModel) {
        MVMCoreDispatchUtility.performBlock(onMainThread:{
            let rotation = CABasicAnimation(keyPath: "transform.rotation")
            let animationHandler = WheelAnimationHandler.shared
            let startAngle =  animationHandler.getAnimationStartAngle(object.duration, CACurrentMediaTime())
            if startAngle == 0.0 {
                animationHandler.storeAnimation(object.duration, CACurrentMediaTime())
            }
            var fromValue = Wheel.getPiValue(0.0 + startAngle), toValue = Wheel.getPiValue(360.0 + startAngle)
            if !object.clockwise {
                fromValue = Wheel.getPiValue(360.0 - startAngle)
                toValue = Wheel.getPiValue(0.0 - startAngle)
            }
            rotation.fromValue = fromValue
            rotation.toValue = toValue
            rotation.duration = object.duration
            rotation.timingFunction = CAMediaTimingFunction(name: .linear)
            rotation.fillMode = .both
            rotation.isRemovedOnCompletion = false
            rotation.repeatCount = Float.greatestFiniteMagnitude
            
            self.gradientLayer?.add(rotation, forKey: "rotation")
        })
    }
}
