
/*
 * 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 ../common/Binding
requireClass ../common/Weinre

requireClass ./ConnectorList
requireClass ./DOMTemplates as dt

//-----------------------------------------------------------------------------
class RemotePanel < WebInspector.Panel
    super("remote")

    this.initialize()

//-----------------------------------------------------------------------------
method initialize()
    
    // main div
    var div = dt.DIV()
    div.style.position = "absolute"
    div.style.top      = "1em"
    div.style.right    = "1em"
    div.style.left     = "1em"
    div.style.bottom   = "1em"
    div.style.overflow = "auto"

    // create icon
    var icon = dt.IMG({
        src: "../images/weinre-icon-128x128.png"
    })
    
    icon.style.float = "right"
    div.appendChild(icon)
        
    // create target and client lists
    this.targetList = new TargetList()
    this.clientList = new ClientList()
    
    div.appendChild(this.targetList.getElement())
    div.appendChild(this.clientList.getElement())
    
    // create server properties
    this.serverProperties = dt.DIV({
        $className: "weinreServerProperties"
    })
        
    div.appendChild(dt.H1("Server Properties"))
    div.appendChild(this.serverProperties)
    
    // add main div to page
    this.element.appendChild(div)
    this.reset();

//-----------------------------------------------------------------------------
method addClient(client) 
    this.clientList.add(client)
    
method addTarget(target) 
    this.targetList.add(target)

method getTarget(channel)
    return this.targetList.get(channel)
    
method removeClient(channel) 
    this.clientList.remove(channel)
    
method removeTarget(channel) 
    this.targetList.remove(channel)

method setCurrentClient(channel) 
    this.clientList.setCurrent(channel)
    
method setCurrentTarget(channel) 
    this.targetList.setCurrent(channel)

method setClientState(channel, state) 
    this.clientList.setState(channel, state)
    
method setTargetState(channel, state) 
    this.targetList.setState(channel, state)

//-----------------------------------------------------------------------------
method getNewestTargetChannel(ignoring)
    return this.targetList.getNewestConnectorChannel(ignoring)

//-----------------------------------------------------------------------------
method afterInitialConnection
    this.clientList.afterInitialConnection()

//-----------------------------------------------------------------------------
method reset
    this.clientList.removeAll()
    this.targetList.removeAll()
    
    Weinre.WeinreClientCommands.getTargets(Binding(this, "cb_getTargets"))
    Weinre.WeinreClientCommands.getClients(Binding(this, "cb_getClients"))

//-----------------------------------------------------------------------------
method connectionClosed
    this.clientList.removeAll()
    this.targetList.removeAll()

//-----------------------------------------------------------------------------
method cb_getTargets(targets)
    targets.forEach(function(target) {
        this.addTarget(target)
    }, this)
   
    if (!Weinre.client.autoConnect()) return
    
    var newestTargetChannel = this.getNewestTargetChannel()
    if (!newestTargetChannel) return
    if (!Weinre.messageDispatcher) return

    Weinre.WeinreClientCommands.connectTarget(Weinre.messageDispatcher.channel, newestTargetChannel)
    
    
//-----------------------------------------------------------------------------
method cb_getClients(clients)
    clients.forEach(function(client) {
        this.addClient(client)
    }, this)

//-----------------------------------------------------------------------------
getter toolbarItemClass
    return "remote"

//-----------------------------------------------------------------------------
getter toolbarItemLabel
    return "Remote"

//-----------------------------------------------------------------------------
getter statusBarItems
    return []

//-----------------------------------------------------------------------------
getter defaultFocusedElement
    return this.contentElement

//-----------------------------------------------------------------------------
method show
    super()

//-----------------------------------------------------------------------------
method hide()
    super()

//-----------------------------------------------------------------------------
method setServerProperties(properties)
    var table = "<table>"
    var keys = []
    for (var key in properties) {
        keys.push(key)
    }
    
    keys = keys.sort()
    keys.forEach(function(key) {
        val = properties[key]
        if (typeof val == "string") {
            val = val.escapeHTML()
        }
        else {
            var finalVal = ""
            val.forEach(function(aVal){
                finalVal += "<li>" + aVal.escapeHTML()
            })
            val = "<ul>" + finalVal + "</ul>"
        }
        table += "<tr class='weinre-normal-text-size'><td valign='top'>" + key.escapeHTML() + ": <td>" + val
    })
    table += "</table>"
    this.serverProperties.innerHTML = table

//=============================================================================
//=============================================================================
    
//-----------------------------------------------------------------------------
class TargetList < ConnectorList
    super("Targets")

//-----------------------------------------------------------------------------
method getListItem(target)
    var self = this
    var text = target.hostName + " [channel: " + target.channel + " id: " + target.id + "]" + " - " + target.url 

    var item = dt.LI(
        { $connectorChannel: target.channel },
        text
    )
    
    item.addStyleClass("weinre-connector-item")
    item.addStyleClass("target")
    
    item.addEventListener("click", function(e) {self.connectToTarget(target.channel, e)}, false)

    target.element = item

    return item

//-----------------------------------------------------------------------------
method connectToTarget(targetChannel, event)
    if (event) {
        event.preventDefault()
        event.stopPropagation()
    }
    
    var target = this.connectors[targetChannel]
    if (!target) return false
    if (target.closed) return false
    
    Weinre.WeinreClientCommands.connectTarget(Weinre.messageDispatcher.channel, targetChannel)
    
    return false

//=============================================================================
//=============================================================================

//-----------------------------------------------------------------------------
class ClientList < ConnectorList
    super("Clients")

    this.noneItem.innerHTML = "Waiting for connection..."

//-----------------------------------------------------------------------------
method afterInitialConnection()
    this.noneItem.innerHTML = "Connection lost, reload this page to reconnect."
    this.noneItem.addStyleClass("error")

//-----------------------------------------------------------------------------
method getListItem(client)
    var text = client.hostName + " [channel: " + client.channel + " id: " + client.id  + "]"
    
    var item = dt.LI(
        { $connectorChannel: client.channel },
        text
    )

    item.addStyleClass("weinre-connector-item")
    item.addStyleClass("client")
    
    if (Weinre.messageDispatcher) {
        if (client.channel == Weinre.messageDispatcher.channel) {
            item.addStyleClass("current")
        }
    }

    client.element = item
    
    return item
