                 untypedValue = element
             }
         }
-
+        
         if untypedValue == nil //This can only occur when the rootObject is nil and the path consists only of .SelfReference
-        || (substituteNSNullWithNil && untypedValue is NSNull) {
-            return nil
-        }
-
+            || (substituteNSNullWithNil && untypedValue is NSNull) {
+                return nil
+        }
+        
         guard let value = untypedValue as? T else {
             let error = JSONPathError.UnexpectedType(path: path, componentStack: componentsErrorStack, T.self)
             return try errorHandler(error)
         }
-
+        
         return value
     }
-
-
+    
+    
     //MARK: Non-optional value fetching
-
+    
     public func valueAtPath<T>(path: JSONPath, errorHandler: (JSONPathError) throws -> T) rethrows -> T {
         
         guard let value = try optionalValueAtPath(path, substituteNSNullWithNil: false, errorHandler: { try errorHandler($0) }) else {

        case InvalidSubscript(path: JSONPath, componentStack: JSONPathComponentsStack)
        case MissingValue(path: JSONPath)
    }


    //MARK:- Optional value fetching

    public func optionalValueAtPath<T>(path: JSONPath, substituteNSNullWithNil: Bool = true) -> T? {
        return optionalValueAtPath(path, substituteNSNullWithNil: substituteNSNullWithNil, errorHandler: { _ in return nil })
    }

    
    public func optionalValueAtPath<T>(path: JSONPath, substituteNSNullWithNil: Bool = true, errorHandler: ((JSONPathError) throws -> T?)) rethrows -> T? {
        var untypedValue: Any? = object
        var componentsErrorStack = JSONPathError.JSONPathComponentsStack()

        for component in path.components {
            componentsErrorStack.append((component, untypedValue))

            switch component {
            case .SelfReference:
                break

            case .Numeric(let number):
                //Check the collection is valid
                guard let array = untypedValue as? NSArray else {
                    let error = JSONPathError.UnexpectedType(path: path, componentStack: componentsErrorStack, NSArray.self)
                    return try errorHandler(error)
                }

                //Check the index is valid
                guard let index = absoluteIndexForRelativeIndex(Int(number)) else {
                    //TODO: The erro should be invalidIndex
                    let error = JSONPathError.InvalidSubscript(path: path, componentStack: componentsErrorStack)
                    return try errorHandler(error)
                }
                untypedValue = array[index]

            case .Text(let key):
                guard let dict = untypedValue as? NSDictionary else {
                    let error = JSONPathError.UnexpectedType(path: path, componentStack: componentsErrorStack, NSDictionary.self)
                    return try errorHandler(error)
                }

                //Check the index is valid
                guard let element = dict[key] else {
                    let error = JSONPathError.InvalidSubscript(path: path, componentStack: componentsErrorStack)



public final class JSONReader: Equatable {
    
    //MARK:- Errors
    
    public enum Error: ErrorType {
        case MissingValue
        case UnexpectedType(expectedType: Any.Type, actualType: Any.Type)
    }
    
    
    /// The object to attempt to fetch values from
    public let object: Any?
    
    public var isEmpty: Bool {
        return object == nil
    }
    
    
    //MARK:- Instance life cycle
    
    convenience public init(data: NSData, allowFragments: Bool = false) throws {
        let options: NSJSONReadingOptions = allowFragments ? [NSJSONReadingOptions.AllowFragments] : []
        let object = try NSJSONSerialization.JSONObjectWithData(data, options: options)
        self.init(object: object)
    }
    
    
    public init(object: Any?) {
        self.object = object
    }
    
    
    private convenience init() {
        self.init(object: nil)
    }
    
    
    //MARK:- Value access
    
    public func value<T>() -> T? {
        return object as? T
    }
    
    
    public func value<T>(errorHandler: (JSONReader.Error) throws -> T) rethrows -> T {
        guard object != nil else {
            let error = Error.MissingValue
            return try errorHandler(error)
        }
        
        guard let value = object as? T else {
            let error = Error.UnexpectedType(expectedType: T.self, actualType: object.dynamicType)
            return try errorHandler(error)
        }
        
        return value
    }
    
    
    //MARK:- Element access
    
    public func isValidIndex(relativeIndex: Int) -> Bool {
        guard let array = object as? NSArray else {
            return false
        }
        
        return array.absoluteIndexForRelativeIndex(relativeIndex) != nil
    }
    
    
    
    public subscript(relativeIndex: Int) -> JSONReader {
        guard let array = object as? NSArray,
            let index = array.absoluteIndexForRelativeIndex(relativeIndex) else {
                return JSONReader()
        }
        
        return JSONReader(object: array[index])
    }
    
    
    public func isValidKey(key: String) -> Bool {
        guard let collection = object as? NSDictionary else {
            return false
        }
        
        return collection[key] != nil
    }
    
    
    public subscript(key: String) -> JSONReader {
        guard let collection = object as? NSDictionary,
            let element = collection[key] else {
                return JSONReader()
        }
        
        return JSONReader(object: element)
    }
}
