/*
 * Jicofo, the Jitsi Conference Focus.
 *
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jitsi.jicofo.event;

import org.jitsi.eventadmin.*;
import org.jitsi.jicofo.*;
import org.jxmpp.jid.*;

import java.util.*;

/**
 * Class for JVB related events.
 *
 * @author Pawel Domas
 */
public class BridgeEvent
    extends Event
{
    /**
     * The event is triggered by {@link BridgeSelector} whenever new functional
     * bridge has been discovered.
     */
    public static final String BRIDGE_UP = "org/jitsi/jicofo/JVB/UP";

    /**
     * The event is triggered by {@link BridgeSelector} whenever a bridge goes
     * down(stops working or disconnects).
     */
    public static final String BRIDGE_DOWN = "org/jitsi/jicofo/JVB/DOWN";

    /**
     * The event is fired by {@link JvbDoctor} when the JVB health check fails.
     * It should be followed by {@link #BRIDGE_DOWN} event generated by
     * {@link BridgeSelector}.
     */
    public static final String HEALTH_CHECK_FAILED
        = "org/jitsi/jicofo/JVB/UNHEALTHY";

    /**
     * The event is emitted by
     * {@link org.jitsi.impl.protocol.xmpp.colibri.ColibriConferenceImpl}
     * when new video channels are being allocated/expired which results in
     * video stream count change. It is consumed by {@link BridgeSelector}
     * to estimate the current video stream count for each JVB.
     */
    public static final String VIDEOSTREAMS_CHANGED
        = "org/jitsi/jicofo/JVB/VIDEOSTREAMS_CHANGE";

    /**
     * The key for event property
     */
    private final static String JVB_JID_KEY = "bridge.jid";

    /**
     * The key for video stream count property
     */
    private final static String STREAMS_VIDEO_KEY = "bridge.streams.video";

    /**
     * Used to init the properties passed to the constructor.
     * @param bridgeJid
     */
    static private Dictionary<String, Object> initDictionary(Jid bridgeJid)
    {
        Dictionary<String, Object> props = new Hashtable<>();
        props.put(JVB_JID_KEY, bridgeJid);
        return props;
    }

    /**
     * Creates {@link #BRIDGE_UP} <tt>BridgeEvent</tt>.
     * @param bridgeJid the JID of the bridge for which the event will be
     *                  created.
     * @return {@link #BRIDGE_UP} <tt>BridgeEvent</tt> for given
     *         <tt>bridgeJid</tt>.
     */
    static public BridgeEvent createBridgeUp(Jid bridgeJid)
    {
        return new BridgeEvent(BRIDGE_UP, bridgeJid);
    }

    /**
     * Creates {@link #BRIDGE_DOWN} <tt>BridgeEvent</tt>.
     * @param bridgeJid the JID of the bridge for which the event will be
     *                  created.
     * @return {@link #BRIDGE_DOWN} <tt>BridgeEvent</tt> for given
     *         <tt>bridgeJid</tt>.
     */
    static public BridgeEvent createBridgeDown(Jid bridgeJid)
    {
        return new BridgeEvent(BRIDGE_DOWN, bridgeJid);
    }

    /**
     * Creates {@link #HEALTH_CHECK_FAILED} <tt>BridgeEvent</tt>.
     * @param bridgeJid the JID of the bridge for which the event will be
     *                  created.
     * @return {@link #HEALTH_CHECK_FAILED} <tt>BridgeEvent</tt> for given
     *         <tt>bridgeJid</tt>.
     */
    static public BridgeEvent createHealthFailed(Jid bridgeJid)
    {
        return new BridgeEvent(HEALTH_CHECK_FAILED, bridgeJid);
    }

    /**
     * Creates {@link #VIDEOSTREAMS_CHANGED} <tt>BridgeEvent</tt>.
     *
     * @param bridgeJid the JID of the bridge for which the event will be
     *        created.
     * @param videoStreamCount how many video streams are being added/removed.
     *
     * @return {@link #VIDEOSTREAMS_CHANGED} <tt>BridgeEvent</tt> for given
     *         <tt>bridgeJid</tt>.
     */
    static public BridgeEvent createVideoStreamsChanged(Jid    bridgeJid,
                                                        int    videoStreamCount)
    {
        Dictionary<String, Object> dict = initDictionary(bridgeJid);
        dict.put(STREAMS_VIDEO_KEY, videoStreamCount);
        return new BridgeEvent(VIDEOSTREAMS_CHANGED, dict);
    }

    /**
     * Checks whether or not given <tt>Event</tt> is a <tt>BridgeEvent</tt>.
     *
     * @param event the <tt>Event</tt> instance to be checked.
     *
     * @return <tt>true</tt> if given <tt>Event</tt> instance is one of bridge
     *         events or <tt>false</tt> otherwise.
     */
    static public boolean isBridgeEvent(Event event)
    {
        switch (event.getTopic())
        {
        case BRIDGE_DOWN:
        case BRIDGE_UP:
        case HEALTH_CHECK_FAILED:
        case VIDEOSTREAMS_CHANGED:
            return true;
        default:
            return false;
        }
    }

    private BridgeEvent(String topic, Dictionary<String, Object> dict)
    {
        super(topic, dict);
    }

    private BridgeEvent(String topic, Jid bridgeJid)
    {
        super(topic, initDictionary(bridgeJid));
    }

    /**
     * Gets bridge JID associated with this <tt>BridgeEvent</tt> instance.
     *
     * @return The JID of the jitsi-videobridge instance for this event.
     *         instance has been created.
     */
    public Jid getBridgeJid()
    {
        return (Jid) getProperty(JVB_JID_KEY);
    }

    /**
     * Obtains the value of video stream count associated with the current
     * <tt>BridgeEvent</tt>.
     * @return <tt>Integer</tt> or <tt>null</tt> if attribute not present for
     * given event.
     */
    public Integer getVideoStreamCount()
    {
        return (Integer) getProperty(STREAMS_VIDEO_KEY);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj)
    {
        if (!(obj instanceof BridgeEvent))
        {
            return false;
        }

        BridgeEvent other = (BridgeEvent) obj;
        // Verify topic and JID
        boolean sameTopicAndJid
            = getTopic().equals(other.getTopic()) &&
                    getBridgeJid().equals(other.getBridgeJid());
        if (!sameTopicAndJid)
        {
            return false;
        }
        // Compare streams added/remove
        Integer streamCount = this.getVideoStreamCount();
        Integer otherStreamCount = other.getVideoStreamCount();
        return Objects.equals(streamCount, otherStreamCount);
    }
}

@@ -5606,50 +5606,8 @@
 nt.%0A
-     *         instance has been created.%0A
     

Update JSDoc