
/*
 * 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
 */

require ../common/Ex
require ../common/Binding
require ../common/Callback
require ../common/Socket
require ../common/Weinre

require ./NodeStore
require ./CSSStore
require ./ElementHighlighter
require ./InjectedScriptHostImpl
require ./WebInspectorApplicationCacheHandlerImpl
require ./WebInspectorBackendHandlerImpl
require ./WebInspectorControllerHandlerImpl
require ./WebInspectorDOMHandlerImpl   
require ./WebInspectorDebugHandlerImpl
require ./WebInspectorProfilerHandlerImpl
require ./WebInspectorResourceHandlerImpl
require ./WeinreTargetEventsImpl

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
class Target
    this.initialize()

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
static method main
    Weinre.target = new Target()
    
    Weinre.addCSSProperties = function addCSSProperties(properties) {
        CSSStore.addCSSProperties(properties)
    }
    
//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
method setWeinreServerURLFromScriptSrc()
    if (window.WeinreServerURL) return
    
    var elements = document.getElementsByTagName("script")

    var scripts = ["Target.", "target-script.", "target-script-min."]
    for (var i=0; i<elements.length; i++) {
        var element = elements[i]
        
        for (j=0; j<scripts.length; j++) {
            if (-1 != element.src.indexOf("/" + scripts[j])) {
                var pattern = /(http:\/\/(.*?)\/)/
                var match   = pattern.exec(element.src)
                if (match) {
                    window.WeinreServerURL = match[1]
                    return 
                }
            }
        }
    }
    
    var message = "unable to calculate the weinre server url; explicity set the variable window.WeinreServerURL instead" 
    alert(message)
    throw new Ex(arguments, message)

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
method initialize()
    this.setWeinreServerURLFromScriptSrc()
    
    if (window.WeinreServerURL[window.WeinreServerURL.length-1] != "/") {
        window.WeinreServerURL += "/"
    }   
    
    var injectedScriptHost = new InjectedScriptHostImpl()
    Weinre.injectedScript = injectedScriptConstructor(injectedScriptHost, window, 0, "?")
    
    window.addEventListener("load", Binding(this, "onLoaded"), false)

    var webSocket = new Socket(window.WeinreServerURL + "ws/target")
    Weinre.webSocket = webSocket

    Weinre.WebInspectorApplicationCacheHandler = new WebInspectorApplicationCacheHandlerImpl()
    Weinre.WebInspectorBackendHandler          = new WebInspectorBackendHandlerImpl()  
    Weinre.WebInspectorControllerHandler       = new WebInspectorControllerHandlerImpl()
    Weinre.WebInspectorDOMHandler              = new WebInspectorDOMHandlerImpl()        
    Weinre.WebInspectorDebugHandler            = new WebInspectorDebugHandlerImpl()
    Weinre.WebInspectorProfilerHandler         = new WebInspectorProfilerHandlerImpl()
    Weinre.WebInspectorResourceHandler         = new WebInspectorResourceHandlerImpl()

    webSocket.registerInterface("WebInspectorApplicationCacheHandler", Weinre.WebInspectorApplicationCacheHandler, true)
    webSocket.registerInterface("WebInspectorBackendHandler",          Weinre.WebInspectorBackendHandler,          true)
    webSocket.registerInterface("WebInspectorControllerHandler",       Weinre.WebInspectorControllerHandler,       true)
    webSocket.registerInterface("WebInspectorDOMHandler",              Weinre.WebInspectorDOMHandler,              true)
    webSocket.registerInterface("WebInspectorDebugHandler",            Weinre.WebInspectorDebugHandler,            true)
    webSocket.registerInterface("WebInspectorProfilerHandler",         Weinre.WebInspectorProfilerHandler,         true)
    webSocket.registerInterface("WebInspectorResourceHandler",         Weinre.WebInspectorResourceHandler,         true)
    
    webSocket.registerInterface("WeinreTargetEvents", new WeinreTargetEventsImpl(), true)

    Weinre.WeinreTargetCommands  = webSocket.createProxy("WeinreTargetCommands")
    window.WebInspector          = webSocket.createProxy("WebInspector")

//  Weinre.Socket.verbose(true)
    webSocket.open()
    webSocket._socket.addEventListener("open", Binding(this, this.cb_webSocketOpened))
    
    Weinre.nodeStore = new NodeStore()
    Weinre.cssStore  = new CSSStore()

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
method cb_webSocketOpened()
    Weinre.WeinreTargetCommands.registerTarget(window.location.href, Binding(this, this.cb_registerTarget))

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
method cb_registerTarget(targetId)
    Weinre.targetId    = targetId
    Weinre.connectorId = targetId
    
    Callback.setConnectorId(targetId)

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
method onLoaded()

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
method setDocument()
    Weinre.elementHighlighter = new ElementHighlighter()
    
    var nodeId = Weinre.nodeStore.getNodeId(document)
    var nodeData = Weinre.nodeStore.getNodeData(nodeId, 2)

    WebInspector.setDocument(nodeData)
