     case ZPosition
 }
 
-public struct Animation {
+public struct AnimationDescriptor {
     let view: UIView
+    let delay: Double
     let property: AnimatableProperty
     let endValue: AnyObject
     let duration: Double
     let function: FunctionType
+    
+    public func getFrameAnimations() -> (origin: AnimationDescriptor, size: AnimationDescriptor) {
+        let frame = (endValue as! NSValue).CGRectValue()
+        let animOrigin = AnimationDescriptor(view: view, delay: delay, property: .Origin, endValue: NSValue(CGPoint: frame.origin), duration: duration, function: function)
+        let animSize = AnimationDescriptor(view: view, delay: delay, property: .Size, endValue: NSValue(CGSize: frame.size), duration: duration, function: function)
+        
+        return (origin: animOrigin, size: animSize)
+    }
 }
 
+internal extension CGColor {
+    func getUIColor() -> UIColor {
+        return UIColor(CGColor: self)
+    }
+}
+
+internal extension UIView {
+    func update(properties: ViewProperties) {
+        frame = properties.frame
+        backgroundColor = properties.backgroundColor
+        layer.borderColor = properties.borderColor?.CGColor
+        layer.borderWidth = properties.borderWidth
+        layer.cornerRadius = properties.cornerRadius
+        layer.opacity = properties.opacity
+        layer.shadowColor = properties.shadowColor?.CGColor
+        layer.shadowOffset = properties.shadowOffset
+        layer.shadowOpacity = properties.shadowOpacity
+        layer.shadowPath = properties.shadowPath
+        layer.shadowRadius = properties.shadowRadius
+        layer.transform = properties.transform
+    }
+}
+
+internal class ViewProperties: NSObject {
+    var origin: CGPoint
+    var size: CGSize
+    var frame: CGRect {
+        get {
+            return CGRect(origin: origin, size: size)
+        }
+        set {
+            origin = newValue.origin
+            size = newValue.size
+        }
+    }
+    
+    var center: CGPoint {
+        get {
+            return position
+        }
+        set {
+            position = newValue
+        }
+    }
+    var position:CGPoint
+
+    var backgroundColor: UIColor?
+    
+    var borderColor: UIColor?
+    var borderWidth: CGFloat
+    var cornerRadius: CGFloat
+    
+    var opacity: Float
+    var alpha: CGFloat {
+        get {
+            return CGFloat(opacity)
+        }
+        set {
+            opacity = Float(newValue)
+        }
+    }
+    
+    var shadowColor: UIColor?
+    var shadowOffset: CGSize
+    var shadowOpacity: Float
+    var shadowPath: CGPath?
+    var shadowRadius: CGFloat
+    
+    var transform: CATransform3D
+    
+    init(view: UIView) {
+        frame = view.frame
+        position = view.layer.position
+        backgroundColor = view.layer.backgroundColor?.getUIColor()
+        borderColor = view.layer.borderColor?.getUIColor()
+        borderWidth = view.layer.borderWidth
+        cornerRadius = view.layer.cornerRadius
+        opacity = view.layer.opacity
+        
+        shadowColor = view.layer.shadowColor?.getUIColor()
+        shadowOffset = view.layer.shadowOffset
+        shadowOpacity = view.layer.shadowOpacity
+        shadowPath = view.layer.shadowPath
+        shadowRadius = view.layer.shadowRadius
+        
+        transform = view.layer.transform
+    }
+}
+
 public struct KRAnimation {
-    public static func chain(animations: [Animation]..., reverses: Bool = false, repeatCount: Double = 1.0, completion: (() -> Void)? = nil) {
-        // FIXME: - Remove in multi view support
+    public static func chain(animDescriptors: [AnimationDescriptor]..., reverses: Bool = false, repeatCount: Double = 1.0, completion: (() -> Void)? = nil) {
+        // FIXME: - Change in multi view support
         /**************************************/
-        let view = animations[0][0].view
-        guard animations.flatten().reduce(true, combine: { $0.0 && ($0.1.view == view) }) == true else { fatalError() }
-        /**************************************/
-        
-        CATransaction.begin()
-        var updatedValues = [AnimatableProperty: AnyObject]()
+        let view = animDescriptors[0][0].view
+        guard animDescriptors.flatten().reduce(true, combine: { $0.0 && ($0.1.view == view) }) == true else { fatalError() }
+        
+        var updatedProperties = ViewProperties(view: view)
         var totalDuration = 0.0
         var chainedAnims = [CAAnimation]()
-        
+        /**************************************/
+        
+        CATransaction.begin()
         CATransaction.setCompletionBlock {
-            updateValues(view, updatedValues: updatedValues)
+            view.update(updatedProperties)
             view.layer.removeAllAnimations()
             completion?()
         }
         
-        for animArray in animations {
-            if animArray.count == 1 {
-                let anim = animArray[0]
+        for animDescArray in animDescriptors {
+            if animDescArray.count == 1 {
+                let animDesc = animDescArray[0]
                 
-                let keyframeAnimation = getKeyframeAnimation(anim)
-                keyframeAnimation.beginTime = totalDuration
-                keyframeAnimation.values = getValues(updatedValues[anim.property], animation: anim)
+                let anim = getAnimation(animDesc, viewProperties: updatedProperties, setDelay: true)
+                anim.beginTime += totalDuration
+                totalDuration = anim.beginTime + anim.duration
                 
-                totalDuration += anim.duration
-                chainedAnims.append(keyframeAnimation)
-                
-                updatedValues[anim.property] = anim.endValue
+                chainedAnims.append(anim)
             } else {
                 var groupedAnimations = [CAKeyframeAnimation]()
                 
                 let animationGroup = CAAnimationGroup()
-                animationGroup.beginTime = totalDuration
+                animationGroup.beginTime = totalDuration + animArray[0].delay
                 animationGroup.duration = animArray[0].duration
                 animationGroup.fillMode = kCAFillModeForwards
                 animationGroup.removedOnCompletion = false

//
//  Animation.swift
//  KRAnimation
//
//  Created by Joshua Park on 6/17/16.

        animGroup.fillMode = kCAFillModeForwards
        animGroup.removedOnCompletion = false
        
        view.layer.addAnimation(animGroup, forKey: nil)
        
        CATransaction.commit()
    }
