
/*
 * 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 ./DOMTemplates as dt

//-----------------------------------------------------------------------------
class ConnectorList(title)
    this.connectors   = {}
    this.noneItem     = dt.LI("none")
    this.ulConnectors = dt.UL(this.noneItem)
    this.div          = dt.DIV(dt.H1(title), this.ulConnectors)
    
    this.noneItem.addStyleClass("weinre-connector-item")

//-----------------------------------------------------------------------------
method getElement
    return this.div

//-----------------------------------------------------------------------------
method add(connector)
    if (this.connectors[connector.channel]) return
    
    this.connectors[connector.channel] = connector
    
    var li = this.getListItem(connector)

    if (this.noneItem.style.display != "none") {
        this.noneItem.style.display = "none"
    }
    
    li.addStyleClass("weinre-fadeable")
    
    var insertionPoint = this.getConnectorInsertionPoint(connector)
    if (!insertionPoint) {
        this.ulConnectors.appendChild(li)
    }
    else {
        this.ulConnectors.insertBefore(li, insertionPoint)
    }

//-----------------------------------------------------------------------------
method get(channel)
    return this.connectors[channel]

//-----------------------------------------------------------------------------
method getNewestConnectorChannel(ignoring)
    var newest = 0
    
    for (var connectorChannel in this.connectors) {
        if (connectorChannel == ignoring) continue
        if (connectorChannel > newest) newest = connectorChannel
    }
    
    if (newest == 0) return null
    return newest

//-----------------------------------------------------------------------------
method getConnectorInsertionPoint(connector)
    for (var i=0; i<this.ulConnectors.childNodes.length; i++) {
        var childNode = this.ulConnectors.childNodes[i]
        if (null == childNode.connectorChannel) continue
        if (childNode.connectorChannel < connector.channel) {
            return childNode
        }
    }
    
    return null

//-----------------------------------------------------------------------------
method remove(channel, fast)
    var self = this
    var element = this.getConnectorElement(channel)
    if (!element) return

    var connector = this.connectors[channel]
    if (connector) {
        connector.closed = true
    }
    
    delete this.connectors[channel]
    
    if (fast) {
        this._remove(element)
    }

    else {
        this.setState(element, "closed")
        element.addStyleClass("weinre-fade")

        window.setTimeout(function() {
            self._remove(element)
        }, 5000)
    }

//-----------------------------------------------------------------------------
method _remove(element)
    this.ulConnectors.removeChild(element)
    if (this.getConnectors().length == 0) {
        this.noneItem.style.display = "list-item"
    }

//-----------------------------------------------------------------------------
method removeAll()
    this.getConnectors().forEach(function(connector) {
        this.remove(connector.channel, true)
    }, this)

//-----------------------------------------------------------------------------
method getConnectors()
    var result = []
    for (var channel in this.connectors) {
        if (!this.connectors.hasOwnProperty(channel)) continue
        
        result.push(this.connectors[channel])
    }
    
    return result

//-----------------------------------------------------------------------------
method getConnectorElement(channel)
    var connector = this.connectors[channel]
    if (!connector) return null
    
    return connector.element

//-----------------------------------------------------------------------------
method setCurrent(channel)
    this.getConnectors().forEach(function(connector) {
        connector.element.removeStyleClass("current")
    })
    
    var element = this.getConnectorElement(channel)
    if (null == element) return
    
    element.addStyleClass("current")

//-----------------------------------------------------------------------------
method setState(channel, state)
    if (typeof channel == "string") {
        var element = this.getConnectorElement(channel)
    }
    else {
        element = channel
    }
    
    if (!element) return
    
    element.removeStyleClass("error")
    element.removeStyleClass("closed")
    element.removeStyleClass("connected")
    element.removeStyleClass("not-connected")
    element.addStyleClass(state)
