
#---------------------------------------------------------------------------------
# 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
#---------------------------------------------------------------------------------

dt = require('./DOMTemplates')

#-------------------------------------------------------------------------------
module.exports = class ConnectorList

    constructor: (title) ->
        @connectors = {}

        @noneItem     = dt.LI("none")
        @ulConnectors = dt.UL(@noneItem)
        @div          = dt.DIV(dt.H1(title), @ulConnectors)

        @noneItem.addStyleClass "weinre-connector-item"

    #---------------------------------------------------------------------------
    getElement: ->
        @div

    #---------------------------------------------------------------------------
    add: (connector) ->
        return if @connectors[connector.channel]

        @connectors[connector.channel] = connector

        li = @getListItem(connector)
        li.addStyleClass "weinre-fadeable"

        @noneItem.style.display = "none"

        insertionPoint = @getConnectorInsertionPoint(connector)
        unless insertionPoint
            @ulConnectors.appendChild li
        else
            @ulConnectors.insertBefore li, insertionPoint

    #---------------------------------------------------------------------------
    get: (channel) ->
        @connectors[channel]

    #---------------------------------------------------------------------------
    getNewestConnectorChannel: (ignoring) ->
        newest = 0
        for connectorChannel of @connectors
            continue if connectorChannel == ignoring
            newest = connectorChannel if connectorChannel > newest

        return null if newest == 0
        newest

    #---------------------------------------------------------------------------
    getConnectorInsertionPoint: (connector) ->
        i = 0

        for childNode in @ulConnectors.childNodes
            continue if null == childNode.connectorChannel
            return childNode if childNode.connectorChannel < connector.channel

        null

    #---------------------------------------------------------------------------
    remove: (channel, fast) ->
        self = this

        element = @getConnectorElement(channel)
        return unless element

        connector = @connectors[channel]
        connector.closed = true if connector
        delete @connectors[channel]

        if fast
            @_remove element
        else
            @setState element, "closed"
            element.addStyleClass "weinre-fade"

            window.setTimeout (->
                self._remove element
            ), 5000

    #---------------------------------------------------------------------------
    _remove: (element) ->
        @ulConnectors.removeChild element
        @noneItem.style.display = "list-item" if @getConnectors().length == 0

    #---------------------------------------------------------------------------
    removeAll: () ->
        for connector in @getConnectors()
            @remove connector.channel, true

    #---------------------------------------------------------------------------
    getConnectors: () ->
        result = []

        for channel of @connectors
            continue unless @connectors.hasOwnProperty(channel)
            result.push @connectors[channel]

        result

    #---------------------------------------------------------------------------
    getConnectorElement: (channel) ->
        connector = @connectors[channel]
        return null unless connector
        connector.element

    #---------------------------------------------------------------------------
    setCurrent: (channel) ->
        for connector in @getConnectors()
            connector.element.removeStyleClass "current"

        element = @getConnectorElement(channel)
        return if null == element
        element.addStyleClass "current"

    #---------------------------------------------------------------------------
    setState: (channel, state) ->
        if typeof channel == "string"
            element = @getConnectorElement(channel)
        else
            element = channel

        return unless element
        element.removeStyleClass "error"
        element.removeStyleClass "closed"
        element.removeStyleClass "connected"
        element.removeStyleClass "not-connected"
        element.addStyleClass state

#-------------------------------------------------------------------------------
require("../common/MethodNamer").setNamesForClass(module.exports)
