     
     public func map(pattern: String,
                     queue: dispatch_queue_t = dispatch_get_main_queue(),
-                    handler: Route.MapHandler) -> Void {
+                    handler: Route.RouteHandler) -> Void {
         dispatch_async(accessQueue) {
-            self.routes.insert(Route.register(pattern, queue: queue, handler: handler), atIndex: 0)
+            self.routes.insert(Route(pattern, queue: queue, handler: .Route(handler)), atIndex: 0)
         }
     }
     
     public func proxy(pattern: String,
                       queue: dispatch_queue_t = dispatch_get_main_queue(),
-                      handler: Proxy.ProxyHandler) -> Void {
+                      handler: Route.ProxyHandler) -> Void {
         dispatch_async(accessQueue) {
-            self.proxies.insert(Proxy.register(pattern, queue: queue, handler: handler), atIndex: 0)
+            self.routes.insert(Route(pattern, queue: queue, handler: .Proxy(handler)), atIndex: 0)
         }
     }
     


import Foundation

public typealias Parameters = [String: String]

protocol Routable {
    associatedtype Handler
    
    var pattern: String { get set }
    var dynamicSegments: [String] { get set }
    var queue: dispatch_queue_t { get set }
    var handler: Handler { get set }
    
    init(pattern: String, dynamicSegments: [String], queue: dispatch_queue_t, handler: Handler)
    static func register(pattern: String, queue: dispatch_queue_t, handler: Handler) -> Self
    func matches(route: String, inout parameters: Parameters) -> Bool
}

extension Routable {
    static func register(pattern: String, queue: dispatch_queue_t, handler: Handler) -> Self {
        var pattern = pattern
        var dynamicSegments = [String]()
        while let range = pattern.rangeOfString(":[a-zA-Z0-9-_]+", options: [.RegularExpressionSearch, .CaseInsensitiveSearch]) {
            dynamicSegments.append(pattern.substringWithRange(range).stringByReplacingOccurrencesOfString(":", withString: ""))
            pattern.replaceRange(range, with: "([^/]+)")
        }
        
        return self.init(pattern: pattern, dynamicSegments: dynamicSegments, queue: queue, handler: handler)
    }
    
    func matches(route: String, inout parameters: Parameters) -> Bool {
        guard let matches = (try? NSRegularExpression(pattern: pattern, options: .CaseInsensitive))
            .flatMap({ $0.matchesInString(route, options: [], range: NSMakeRange(0, route.characters.count)) })?
            .first else {
                return false
        }
        
        if dynamicSegments.count > 0 && dynamicSegments.count == matches.numberOfRanges - 1 {
            [Int](1 ..< matches.numberOfRanges).forEach { (index) in
                parameters[dynamicSegments[index-1]] = (route as NSString).substringWithRange(matches.rangeAtIndex(index))
            }
        }
        
        return true
    }
}

public struct Route: Routable {
    public typealias MapHandler = (String, Parameters, Completed) -> Void
    public typealias Completed = () -> Void
    
    var pattern: String
    var dynamicSegments: [String]
    var queue: dispatch_queue_t
    var handler: MapHandler
    
    init(pattern: String, dynamicSegments: [String], queue: dispatch_queue_t, handler: MapHandler) {
        self.pattern = pattern
        self.dynamicSegments = dynamicSegments
        self.queue = queue
        self.handler = handler
    }
}

public struct Proxy: Routable {
    public typealias ProxyHandler = (String, Parameters, Next) -> Void
    public typealias Next = (String?, Parameters?) -> Void
    
    var pattern: String
    var dynamicSegments: [String]
    var queue: dispatch_queue_t
    var handler: ProxyHandler
    
    init(pattern: String, dynamicSegments: [String], queue: dispatch_queue_t, handler: ProxyHandler) {
        self.pattern = pattern
        self.dynamicSegments = dynamicSegments
        self.queue = queue
        self.handler = handler
    }
}

public final class Routing {
    private var routes: [Route] = [Route]()
    private var proxies: [Proxy] = [Proxy]()
    private var accessQueue = dispatch_queue_create("Routing Access Queue", DISPATCH_QUEUE_SERIAL)
    private var routingQueue = dispatch_queue_create("Routing Queue", DISPATCH_QUEUE_SERIAL)
    

                            break
                        }
                    }
                }
                
                for route in _routes where !route.isProxy && route.matches(matchedString) != nil {
                    dispatch_async(route.queue) {
                        if case let .Route(handler) = route.handler {
                            handler(matchedString, parameters) {
                                dispatch_semaphore_signal(semaphore)
                            }
                        }
                    }
                    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
                }
            }
        }
        return true
    }
    
}
