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