 
 public class GridLogo: UIView {
     
-    var mystic: CGFloat = 4
-    var turns = 9
-    var xstep = [1,0,-1,0]
-    var ystep = [0,1,0,-1]
+    static let xstep = [1,0,-1,0]
+    static let ystep = [0,1,0,-1]
     
-    var md: CGFloat!
-    var strokeRatio: CGFloat!
-    var last: CGPoint!
-    var curr: CGPoint!
-    var scalestep: CGFloat!
+    static func shapeLayerWithLogoPath(strokeColor: UIColor, lineJoin: String, lineWidth: CGFloat, turns: Int, md: CGFloat) -> CAShapeLayer {
+        
+        var curr = CGPointZero
+        var last = CGPointZero
+        var scalestep: CGFloat
+        let path = UIBezierPath()
+        path.moveToPoint(curr)
+        
+        for i in 0 ..< turns {
+            scalestep = round((CGFloat(i) + 1) / 2.0) * CGFloat(md)
+            curr = CGPoint(x: CGFloat(last.x) + (scalestep * CGFloat(xstep[i % 4])), y: CGFloat(last.y) + (scalestep * CGFloat(ystep[i % 4]))).toInt()
+            
+            if i + 1 == turns {
+                curr = CGPoint(x: CGFloat(curr.x) - (md * CGFloat(xstep[i % 4])), y: CGFloat(curr.y) - (md * CGFloat(ystep[i % 4]))).toInt()
+            }
+            
+            path.addLineToPoint(curr)
+            last  = curr
+        }
+        
+        let shapeLayer = CAShapeLayer()
+        shapeLayer.path = path.CGPath
+        shapeLayer.strokeColor = strokeColor.CGColor
+        shapeLayer.fillColor = nil
+        shapeLayer.lineWidth = lineWidth
+        shapeLayer.lineJoin = lineJoin
+        return shapeLayer
+    }
     
-    weak var bgLayer: CAShapeLayer?
-    weak var fgLayer: CAShapeLayer?
-    var pathAnimationIn: CABasicAnimation!
-    var pathAnimationOut: CABasicAnimation!
-    var pathAnimationGroup: CAAnimationGroup!
+    static func setupAnimation(duration: CFTimeInterval, repeatCount: Float) -> CAAnimationGroup {
+        
+        let pathAnimationIn = CABasicAnimation(keyPath: "strokeEnd")
+        let pathAnimationOut = CABasicAnimation(keyPath: "strokeStart")
+        let pathAnimationGroup = CAAnimationGroup()
+        
+        
+        
+        let startPos: CGFloat = 0.0
+        let endPos: CGFloat = 1.0
+        
+        
+        pathAnimationIn.fromValue = startPos
+        pathAnimationIn.toValue = endPos
+        pathAnimationIn.duration = duration / 2
+        pathAnimationIn.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
+        
+        
+        pathAnimationOut.fromValue = startPos
+        pathAnimationOut.toValue = endPos
+        pathAnimationOut.duration = duration / 2
+        pathAnimationOut.beginTime = duration / 2
+        pathAnimationOut.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
+        
+        
+        pathAnimationGroup.animations = [pathAnimationIn, pathAnimationOut]
+        pathAnimationGroup.duration = duration
+        pathAnimationGroup.repeatCount = repeatCount
+        pathAnimationGroup.removedOnCompletion = false
+        pathAnimationGroup.fillMode = kCAFillModeBackwards
+        
+        return pathAnimationGroup
+    }
     
-    private var duration: CFTimeInterval = 5.0
-    private var startPos: CGFloat = 0.0
-    private var endPos: CGFloat = 1.0
+    private var mystic: CGFloat = 4
+    private var turns: Int
+    private var md: CGFloat
+    private let bgLayer: CAShapeLayer
+    private let fgLayer: CAShapeLayer
+    private let pathAnimationGroup: CAAnimationGroup
+    private var duration: CFTimeInterval
     private var reverses = false
-    private var repeatCount: Float = 14.5
-    private var lineWidth: CGFloat?
-    
+    private var lineWidth: CGFloat
     private let fadeDuration = dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC)))
     
     let fadeInAnimation: CABasicAnimation = {

    }
    
    public func hide(completionHandler: (() -> Void)? = nil) {
        self.fgLayer?.opacity = 0
        self.bgLayer?.opacity = 0
        
        self.fgLayer?.addAnimation(self.fadeOutAnimation, forKey: "fade")
        self.bgLayer?.addAnimation(self.fadeOutAnimation, forKey: "fade")
        
        dispatch_after(self.fadeDuration, dispatch_get_main_queue()) {
            self.fgLayer?.removeAllAnimations()
            completionHandler?()
        }
    }
    
    func startAnimation() {
        self.fgLayer?.removeAllAnimations()
        self.fgLayer?.addAnimation(pathAnimationGroup, forKey: "group")
    }
    
    func endAnimation() {
        self.fgLayer?.removeAllAnimations()
    }
    
    func shapeLayerWithLogoPath(strokeColor: UIColor, lineJoin: String) -> CAShapeLayer {
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = logoPath.CGPath
        shapeLayer.strokeColor = strokeColor.CGColor
        shapeLayer.fillColor = nil
        if lineWidth == nil {
            shapeLayer.lineWidth = self.strokeRatio
        } else {
            shapeLayer.lineWidth = self.lineWidth!
        }
        shapeLayer.lineJoin = lineJoin
        return shapeLayer
    }
    
    func addBackground(color: UIColor) {
        if bgLayer == nil {
            let background = shapeLayerWithLogoPath(color, lineJoin: kCALineJoinMiter)
            self.bgLayer = background
            self.layer.addSublayer(background)
        }
    }
    
    override public func needsUpdateConstraints() -> Bool {
        return true
    }
    
}
        return animation
    }()
    
    public init(mystic m: CGFloat, duration d: CFTimeInterval, lineWidth lw: CGFloat = 1, bgColor: UIColor = UIColor(red: 51/255, green: 51/255, blue: 48/255, alpha: 1), fgColor: UIColor = UIColor(red: 1, green: 246/255, blue: 153/255, alpha: 1), turns t: Int = 9, repeatCount: Float = 14) {
        
        mystic = m
        duration = d
        lineWidth = lw
        md = m
        turns = t
        bgLayer = GridLogo.shapeLayerWithLogoPath(bgColor, lineJoin: kCALineJoinMiter, lineWidth: lineWidth, turns: turns, md: md)
        fgLayer = GridLogo.shapeLayerWithLogoPath(fgColor, lineJoin: kCALineJoinMiter, lineWidth: lineWidth, turns: turns, md: md)
        pathAnimationGroup = GridLogo.setupAnimation(duration, repeatCount: repeatCount)
        
        super.init(frame: CGRectZero)
        layer.addSublayer(bgLayer)
        layer.addSublayer(fgLayer)
        userInteractionEnabled = false
        
    }
    
    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    
    
    public func show(completionHandler: (() -> Void)? = nil) {
        self.startAnimation()
        
        self.fgLayer.opacity = 1
        self.bgLayer.opacity = 1
        
        self.fgLayer.addAnimation(self.fadeInAnimation, forKey: "fade")
        self.bgLayer.addAnimation(self.fadeInAnimation, forKey: "fade")
        
        dispatch_after(self.fadeDuration, dispatch_get_main_queue()) {
            completionHandler?()
