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

import java.util.ArrayList;
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
{
    final Log logger = LogFactory.getLog(getClass());

    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)
    {
        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;
    }
}

@@ -2766,24 +2766,113 @@
 ent(this);%0A%0A
+%0A        if (new Integer(2).equals(members.get(0).getBridgeNumChannels()))%0A        %7B%0A    
         brid
@@ -2926,32 +2926,36 @@
 Num());%0A        
+  
+  
 bridgeEvent.setU
@@ -2994,32 +2994,36 @@
 eId());%0A        
+  
+  
 bridgeEvent.setC
@@ -3053,32 +3053,253 @@
 getChannel());%0A%0A
+%09    bridgeEvent.setCallerId2(members.get(1).getCallerIdNum());%0A%09    bridgeEvent.setUniqueId2(members.get(1).getUniqueId());%0A%09    bridgeEvent.setChannel2(members.get(1).getChannel());%0A        %7D%0A        else%0A        %7B%0A    
         bridgeEv
@@ -3305,33 +3305,33 @@
 vent.setCallerId
-2
+1
 (members.get(1).
@@ -3349,32 +3349,36 @@
 Num());%0A        
+  
+  
 bridgeEvent.setU
@@ -3376,33 +3376,33 @@
 vent.setUniqueId
-2
+1
 (members.get(1).
@@ -3409,32 +3409,36 @@
 getUniqueId());%0A
+    
         bridgeEv
@@ -3447,39 +3447,224 @@
 t.setChannel
-2(members.get(1
+1(members.get(1).getChannel());%0A%0A%09    bridgeEvent.setCallerId2(members.get(0).getCallerIdNum());%0A%09    bridgeEvent.setUniqueId2(members.get(0).getUniqueId());%0A%09    bridgeEvent.setChannel2(members.get(0
 ).getChannel
@@ -3663,24 +3663,34 @@
 tChannel());
+%0A        %7D
 %0A%0A        br

Fix order of Channel1/Channel2/UniqueId1/UniqueId2/CallerId1/CallerId2