             self.eventSemaphores[actionId] = sem
         }
         
-//        print("Dispatch \(actionId)")
         // dispatch event
         self.sendEventWithName("callAction", body: ["id": actionId, "action": functionName, "args": args])
         

        return reply
    }
    
    public func publishEvent(eventName: String, args: AnyObject) {
        self.sendEventWithName("publishEvent", body: ["event": eventName, "args": args])
    }
    
    @objc(replyToAction:response:error:)
    func replyToAction(actionId: NSInteger, response: NSDictionary, error: String) {
//        print("Response \(actionId)")
        
        dispatch_async(semaphoresDispatchQueue) {
            // lookup the semaphore for this action
            if let sem = self.eventSemaphores[actionId] {
                // place response in cache and signal on this semaphore
                self.replyCache[actionId] = ["result": response, "error": error]
                dispatch_semaphore_signal(sem)
            } else {
                print("disgarding action reply \(actionId)")
            }
        }
    }

    @objc(registerAction:)
    func registerAction(actionName: String) {
        self.registeredActions.insert(actionName)
        
        // check for actions waiting to be executed
        dispatch_async(lockDispatchQueue) {
            if let queued = self.awaitingRegistration[actionName] {
                // trigger each waiting action
                queued.forEach { (args, callback) in
                    dispatch_async(self.callbackDispatchQueue, {
                        self.callAction(actionName, args: args, callback: callback)
                    })
                }
                self.awaitingRegistration[actionName] = []
            }
        }
    }
    
}
