
/*
 * weinre is available under *either* the terms of the modified BSD license *or* the
 * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
 * 
 * Copyright (c) 2010, 2011 IBM Corporation
 */

requireClass ./Weinre
requireClass ./WebSocketXhr
requireClass ./IDLTools
requireClass ./Binding
requireClass ./Ex

//-----------------------------------------------------------------------------
class Socket(url)
    this._url        = url
    
    this.error       = null
    this._opening    = false
    this._opened     = false
    this._closed     = false
    this._interfaces = {}
    
    this._open()

//-----------------------------------------------------------------------------
init
    var Verbose = false
    var InspectorBackend

//-----------------------------------------------------------------------------
static method setInspectorBackend(inspectorBackend)
    InspectorBackend = inspectorBackend
    
//-----------------------------------------------------------------------------
static method verbose(value)
    if (arguments.length >= 1) {
        Verbose = !!value
    }
    
    return Verbose

//-----------------------------------------------------------------------------
method open
    Weinre.deprecated()

//-----------------------------------------------------------------------------
method _open
    if (this._opened || this._opening) return
    if (this._closed) throw new Ex(arguments, "socket has already been closed")
    
    this._opening = true 
    this._socket = new WebSocketXhr(this._url)
    this._socket.addEventListener("open",    Binding(this, "_handleOpen"))
    this._socket.addEventListener("error",   Binding(this, "_handleError"))
    this._socket.addEventListener("message", Binding(this, "_handleMessage"))
    this._socket.addEventListener("close",   Binding(this, "_handleClose"))

//-----------------------------------------------------------------------------
method close
    if (this._closed) return
    
    this._opened = false
    this._closed = true
    
    this._socket.close()

//-----------------------------------------------------------------------------
method send(data)
    this._socket.send(data)

//-----------------------------------------------------------------------------
method getWebSocket
    return this._socket

//-----------------------------------------------------------------------------
method registerInterface(intfName, intf, validate)
    if (validate) IDLTools.validateAgainstIDL(intf.constructor, intfName)
    
    if (this._interfaces[intfName]) throw new Ex(arguments, "interface " + intfName + " has already been registered")
    
    this._interfaces[intfName] = intf

//-----------------------------------------------------------------------------
method createProxy(intfName)
    var proxy = {}
    
    IDLTools.buildProxyForIDL(proxy, intfName)

    var self = this
    proxy.__invoke = function __invoke(intfName, methodName, args) {
        self._sendMethodInvocation(intfName, methodName, args)
    }
    
    return proxy

//-----------------------------------------------------------------------------
method _sendMethodInvocation(intfName, methodName, args)
    if (typeof intfName   != "string") throw new Ex(arguments, "expecting intf parameter to be a string")
    if (typeof methodName != "string") throw new Ex(arguments, "expecting method parameter to be a string")
    
    var data = {
            "interface": intfName,
            "method":    methodName,
            "args":      args
    }
    
    data = JSON.stringify(data)
    
    this._socket.send(data)
    
    if (Verbose) {
        console.log(this.constructor.name + "[" + this._url + "]: send " + intfName + "." + methodName + "(" + JSON.stringify(args) + ")")
    }

//-----------------------------------------------------------------------------
method getState
    if (this._opening) return "opening"
    if (this._opened)  return "opened"
    if (this._closed)  return "closed"
    return "unknown"

//-----------------------------------------------------------------------------
method isOpen
    return this._opened == true

//-----------------------------------------------------------------------------
method _handleOpen
    this._opening = false
    this._opened  = true
    
    if (Verbose) {
        console.log(this.constructor.name + "[" + this._url + "]: opened")
    }

//-----------------------------------------------------------------------------
method _handleError(message)
    this.error = message
    this.close()

    if (Verbose) {
        console.log(this.constructor.name + "[" + this._url + "]: error: " + message)
    }

//-----------------------------------------------------------------------------
method _handleMessage(message)
    var data
    
    try {
        data = JSON.parse(message.data)
    }
    catch (e) {
        throw new Ex(arguments, "invalid JSON data received: " + e + ": '" + message.data + "'")
    }

    var intfName   = data["interface"]
    var methodName = data.method
    var args       = data.args

    var methodSignature = intfName + "." + methodName + "()"
    
    var intf = this._interfaces[intfName]
    if (!intf && InspectorBackend && intfName.match(/.*Notify/)) {
        intf = InspectorBackend.getRegisteredDomainDispatcher(intfName.substr(0,intfName.length-6))
    }
    
    if (!intf) throw new Ex(arguments, "request for non-registered interface:" + methodSignature)
    
    var method = intf[methodName]
    if (typeof method != "function") throw new Ex(arguments, "request for unknown method on interface: " + methodSignature)
    
    try {
        method.apply(intf, args)
    }
    catch (e) {
        console.log("Weinre.Socket._handleMessage() invocation exception on " + methodSignature + ": " + e)
    }
    
    if (Verbose) {
        console.log(this.constructor.name + "[" + this._url + "]: recv " + intfName + "." + methodName + "(" + JSON.stringify(args) + ")")
    }

//-----------------------------------------------------------------------------
method _handleClose
    this._reallyClosed = true
    
    if (Verbose) {
        console.log(this.constructor.name + "[" + this._url + "]: closed")
    }
