         return path
     }
 
+    
+    /// A method for generating a UIBezierPath for a end cap layer
+    ///
+    /// - returns: A UIBezierPath that is a end cap that uses the current
+    /// radius, and lineWidth.
     private func endCapPath() -> UIBezierPath {
         let c = circleCenter()
         let capCenter = CGPointMake(c.x, c.y - circleRadius())

    
    @IBInspectable var color: UIColor? {
        didSet {
            circlePathLayer.strokeColor = color?.CGColor
            endCapLayer.fillColor = color?.CGColor
            startCapLayer.fillColor = color?.CGColor
        }
    }
    
    @IBInspectable var lineWidth: CGFloat = 1 {
        didSet {
            circlePathLayer.lineWidth = lineWidth
            endCapLayer.path = endCapPath().CGPath
            startCapLayer.path = endCapPath().CGPath
        }
    }
    
    @IBInspectable var shadowRadius: CGFloat = 10 {
        didSet {
            endCapLayer.shadowRadius = shadowRadius
        }
    }

    @IBInspectable var shadowOffset: CGSize = CGSizeZero {
        didSet {
            endCapLayer.shadowOffset = shadowOffset
        }
    }

    @IBInspectable var shadowOpacity: Float = 0.5 {
        didSet {
            endCapLayer.shadowOpacity = shadowOpacity
        }
    }

    @IBInspectable var shadowColor: UIColor? {
        didSet {
            endCapLayer.shadowColor = shadowColor?.CGColor
        }
    }
    
    @IBInspectable var rotationDuration: Float = 0.5 {
        didSet {
//            endCapLayer.rotationDuration = rotationDuration
//            circlePathLayer.rotationDuration = rotationDuration
        }
    }
        
    private let circlePathLayer = CAShapeLayer()
    private let endCapLayer = CAShapeLayer()
    private let startCapLayer = CAShapeLayer()
    
    private var oldAngle: CGFloat = 0
    private var oldProgress: CGFloat = 0
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        circlePathLayer.strokeEnd = 0.0
        setupShapeLayers()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        circlePathLayer.strokeEnd = 0.0
        setupShapeLayers()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()

        reframeLayers(rect)
    }

    
    /// A private method that is called to perform the actual steps in updating
    /// the progress indicators.
    private func updateLayerProgress() {
        var fromStroke: CGFloat
        var toStroke: CGFloat
        var fromAngle: CGFloat
        var toAngle: CGFloat
        
        fromStroke = arcLayer.strokeEnd

        if progress > 1.0 {
            toStroke = 1.0
            arcLayer.strokeEnd = 1.0
        } else {
            toStroke = progress
            arcLayer.strokeEnd = progress
        }

        fromAngle = oldAngle

        let delta: CGFloat = CGFloat(M_PI * 2.0) * progress - oldAngle
        let rotate = CATransform3DRotate(endLayer.transform, delta, 0, 0, 1)
        toAngle = oldAngle + delta

        
        endLayer.transform = rotate

        endLayer.addAnimation(endCapAnimation(fromAngle, toAngle: toAngle), forKey: "transform.rotation.z")
        arcLayer.addAnimation(circleAnimation(fromStroke, toStroke: toStroke, fromAngle: fromAngle, toAngle: toAngle), forKey: "strokeEnd")
        
        oldAngle = toAngle
    }
    
    
    /// A utility used to setup the shapeLayers on initialization.   Each layer
    /// is initialized with the correct properties and loaded into view's
    /// CALayer hierarchy.
    private func setupShapeLayers() {
        let frame = circleFrame()

        setupShapeLayer(startLayer, frame: frame)

        setupShapeLayer(arcLayer, frame: frame)
        arcLayer.lineWidth = lineWidth

        setupShapeLayer(endLayer, frame: frame)
        endLayer.shadowColor = UIColor.blackColor().CGColor
        endLayer.shadowRadius = lineWidth
        endLayer.shadowOpacity = 0.6
        endLayer.shadowOffset = CGSizeMake(lineWidth, 0)
    }


    /// A utility method used to perform redundant setup steps for a CAShapeLayer.
    /// This method also adds the shape layer to the views layer.
    ///
    /// - parameter shapeLayer: A CAShapeLayer to initialize and add into the
    /// view's CALayer hiearchy
    /// - parameter frame: A CGRect that is the new frame to use
    private func setupShapeLayer(shapeLayer: CAShapeLayer, frame: CGRect) {
        shapeLayer.fillColor = UIColor.clearColor().CGColor
        shapeLayer.strokeColor = color?.CGColor
