package org.asteriskjava.manager.internal.backwardsCompatibility.bridge;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.asteriskjava.manager.event.BridgeEnterEvent;
import org.asteriskjava.manager.event.BridgeEvent;
import org.asteriskjava.manager.event.BridgeLeaveEvent;
import org.asteriskjava.manager.event.ManagerEvent;
import org.asteriskjava.util.Log;
import org.asteriskjava.util.LogFactory;

/**
 * Track the current members of a bridge, emmitting BridgeEvents when 2 members
 * join or breakup
 *
 * @author rsutton
 */
class BridgeState
{
    private final Log logger = LogFactory.getLog(getClass());

    private static final BridgeEnterEventComparator BRIDGE_ENTER_EVENT_COMPARATOR = new BridgeEnterEventComparator();

    private final Map<String, BridgeEnterEvent> members = new HashMap<>();

    ManagerEvent destroy()
    {
        synchronized (members) {
            members.clear();
        }
        return null;
    }

    /**
     * if there are exactly 2 members in the bridge, return a BridgeEvent
     *
     * @param event
     * @return
     */
    ManagerEvent addMember(BridgeEnterEvent event)
    {
        List<BridgeEnterEvent> remaining = null;

        synchronized (members)
        {
            if (members.put(event.getChannel(), event) == null
                    && members.size() == 2)
            {
                remaining = new ArrayList<>(members.values());
            }
        }

        if (remaining == null)
        {
            return null;
        }

        logger.info("Members size " + remaining.size() + " " + event);

        BridgeEvent bridgeEvent = buildBridgeEvent(
                BridgeEvent.BRIDGE_STATE_LINK,
                remaining);

        logger.info("Bridge " + bridgeEvent.getChannel1() + " " + bridgeEvent.getChannel2());

        return bridgeEvent;
    }

    /**
     * If there are exactly 2 members in the bridge, return a BridgeEvent
     *
     * @param event
     * @return
     */

    ManagerEvent removeMember(BridgeLeaveEvent event)
    {
        List<BridgeEnterEvent> remaining = null;

        synchronized (members)
        {
            if (members.remove(event.getChannel()) != null
                    && members.size() == 2)
            {
                remaining = new ArrayList<>(members.values());
            }
        }

        // If we didn't remove anything, or we aren't at exactly 2 members,
        // there's nothing else for us to do
        if (remaining == null)
        {
            return null;
        }

        return buildBridgeEvent(
                BridgeEvent.BRIDGE_STATE_UNLINK,
                remaining);
    }

    private BridgeEvent buildBridgeEvent(String bridgeState, List<BridgeEnterEvent> members) {
        Collections.sort(members, BRIDGE_ENTER_EVENT_COMPARATOR);

        BridgeEvent bridgeEvent = new BridgeEvent(this);

        bridgeEvent.setCallerId1(members.get(0).getCallerIdNum());
        bridgeEvent.setUniqueId1(members.get(0).getUniqueId());
        bridgeEvent.setChannel1(members.get(0).getChannel());

        bridgeEvent.setCallerId2(members.get(1).getCallerIdNum());
        bridgeEvent.setUniqueId2(members.get(1).getUniqueId());
        bridgeEvent.setChannel2(members.get(1).getChannel());

        bridgeEvent.setBridgeState(bridgeState);
        bridgeEvent.setDateReceived(new Date());

        return bridgeEvent;
    }
}

@@ -174,16 +174,45 @@
 ashMap;%0A
+import java.util.LinkedList;%0A
 import j
@@ -1002,32 +1002,40 @@
 onized (members)
+%0A       
  %7B%0A            m
@@ -1430,36 +1430,16 @@
  == null
-%0A                   
  && memb
@@ -1757,33 +1757,16 @@
 geEvent(
-%0A                
 BridgeEv
@@ -1787,32 +1787,16 @@
 TE_LINK,
-%0A               
  remaini
@@ -2160,35 +2160,49 @@
 t%3E remaining = n
-ull
+ew LinkedList%3C%3E()
 ;%0A%0A        synch
@@ -2221,32 +2221,81 @@
 bers)%0A        %7B%0A
+            remaining.addAll(members.values());%0A%0A
             if (
@@ -2336,16 +2336,17 @@
  != null
+)
 %0A       
@@ -2350,24 +2350,26 @@
         
+%7B%0A
         
 && membe
@@ -2360,26 +2360,37 @@
         
-&& members
+        if (remaining
 .size() 
@@ -2387,32 +2387,36 @@
 ng.size() == 2)%0A
+    
             %7B%0A  
@@ -2433,54 +2433,98 @@
     
-remaining = new ArrayList%3C%3E(members.values());
+    return buildBridgeEvent(BridgeEvent.BRIDGE_STATE_UNLINK, remaining);%0A                %7D
 %0A   
@@ -2670,194 +2670,30 @@
  do%0A
-        if (remaining == null)%0A        %7B%0A            return null;%0A        %7D%0A%0A        return buildBridgeEvent(%0A                BridgeEvent.BRIDGE_STATE_UNLINK,%0A                remaining);
+%0A        return null;%0A
 %0A   
@@ -2788,16 +2788,20 @@
 members)
+%0A   
  %7B%0A     

fix for BridgeEvent