import Foundation
import ClefNative

@objc(ClefPlugin) class ClefPlugin: CDVPlugin {
    var clef: Clef!
    
    override func pluginInitialize() {
        super.pluginInitialize()
        clef = Clef(appID: "")
    }
    
    func register(command: CDVInvokedUrlCommand) {
        let gateway = CordovaGateway(delegate: self.commandDelegate, command: command)
        
        self.clef.registerDevice { (let id: String?, let err: NSError?) in
            if err != nil {
                gateway.send(err!)
            } else {
                gateway.send(id!)
            }
        }
    }
    
    func isRegistered(command: CDVInvokedUrlCommand) {
        let gateway = CordovaGateway(delegate: self.commandDelegate, command: command)
        gateway.send(self.clef.isRegistered())
    }
    
    func configure(command: CDVInvokedUrlCommand) {
        let gateway = CordovaGateway(delegate: self.commandDelegate, command: command)
        guard let appID = command.argumentAtIndex(0) as? String else {
            gateway.sendRawError("Invalid appID")
            return
        }
        
        self.clef.configure(appID)
        gateway.sendSuccess()
    }
    
    func unregister(command: CDVInvokedUrlCommand) {
        let gateway = CordovaGateway(delegate: self.commandDelegate, command: command)
        self.clef.resetData()
        gateway.sendSuccess()
    }
    
    func signIn(command: CDVInvokedUrlCommand) {
        let gateway = CordovaGateway(delegate: self.commandDelegate, command: command)
        let delegate = GatewayAuthenticationDelegate(gateway: gateway)
        self.clef.authenticate(delegate)
    }
}

class GatewayAuthenticationDelegate: AuthenticationDelegate {
    let gateway: CordovaGateway

    init(gateway: CordovaGateway) {
        self.gateway = gateway
    }
    
    func onAuthentication(loginID: String) {
        gateway.send(loginID)
    }
    
    func onError(error: NSError) {
        gateway.send(error)
    }
    
    func onCancel() {
        gateway.sendRawError("cancelled")
    }
}

struct CordovaGateway {
    let delegate: CDVCommandDelegate
    let command: CDVInvokedUrlCommand
    
    func send(result: CDVPluginResult) {
        self.delegate.sendPluginResult(result, callbackId: command.callbackId)
    }
    
    func send(error: NSError) {
        self.send(self.makeErrorResult(error))
    }
    
    func sendSuccess() {
        self.send(makeBoolResult(true))
    }
    
    func send(bool: Bool) {
        self.send(makeBoolResult(bool))
    }
    
    func send(data: String) {
        self.send(makeStringResult(data))
    }
    
    func sendRawError(errorString: String) {
        self.send(makeRawErrorResult(errorString))
    }
    
    func makeBoolResult(bool: Bool) -> CDVPluginResult {
        return CDVPluginResult(status: CDVCommandStatus_OK, messageAsBool: bool)
    }
    
    func makeStringResult(string: String) -> CDVPluginResult {
        return CDVPluginResult(status: CDVCommandStatus_OK, messageAsString: string)
    }
    
    func makeRawErrorResult(errorString: String) -> CDVPluginResult {
        return CDVPluginResult(status: CDVCommandStatus_ERROR, messageAsString: errorString)
    }
    
    func makeErrorResult(error: NSError) -> CDVPluginResult {
        return makeRawErrorResult(error.localizedDescription)
    }
}

