package net.floodlightcontroller.core.internal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

// Extends Controller class to access protected inner class
public class RoleChangeCallbackTest extends Controller {
	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}

	/**
	 * Test if {@link RoleChangeCallback#controlChanged(long, boolean)} correctly calls {@link RoleChanger#submitRequest(Collection, net.floodlightcontroller.core.IFloodlightProviderService.Role)}
	 * when connectedSwitch is not empty.
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	@Test
	public void testNormalSwitches() throws Exception {
		Long [] dpids = new Long [] { 1000L, 1001L, 1002L, 1003L };
		final long dpidExist = 1000L;
		final long dpidNotExist = 2000L;
		
		roleChanger = EasyMock.createMock(RoleChanger.class);
		
		// First call will be called with (dpidExist,true)
		roleChanger.submitRequest(EasyMock.anyObject(Collection.class), EasyMock.anyObject(Role.class));
		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
			@Override
			public Object answer() throws Throwable {
				Collection<OFSwitchImpl> switches = (Collection<OFSwitchImpl>)EasyMock.getCurrentArguments()[0];
				Role role = (Role)EasyMock.getCurrentArguments()[1];

				List<Long> dpids = new ArrayList<Long>();
				
				for(OFSwitchImpl sw : switches) {
					dpids.add(sw.getId());
				}
				assertTrue(dpids.contains(dpidExist));
				assertEquals(role, Role.MASTER);
				
				return null;
			}
		}).once();

		// Second call will be called with (dpidExist,false)
		roleChanger.submitRequest(EasyMock.anyObject(Collection.class), EasyMock.anyObject(Role.class));
		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
			@Override
			public Object answer() throws Throwable {
				Collection<OFSwitchImpl> switches = (Collection<OFSwitchImpl>)EasyMock.getCurrentArguments()[0];
				Role role = (Role)EasyMock.getCurrentArguments()[1];

				List<Long> dpids = new ArrayList<Long>();
				
				for(OFSwitchImpl sw : switches) {
					dpids.add(sw.getId());
				}
				assertTrue(dpids.contains(dpidExist));
				assertEquals(role, Role.SLAVE);
				
				return null;
			}
		}).once();

		EasyMock.replay(roleChanger);
		
		initNetwork(roleChanger, dpids);
		
		RoleChangeCallback callback = new RoleChangeCallback();
		callback.controlChanged(dpidExist, true);
		callback.controlChanged(dpidExist, false);
		callback.controlChanged(dpidNotExist, true);
		callback.controlChanged(dpidNotExist, false);
		
		EasyMock.verify(roleChanger);
	}

	/**
	 * Test if {@link RoleChangeCallback#controlChanged(long, boolean)} doesn't call RoleChanger methods
	 * when connectedSwitch is empty.
	 * @throws Exception
	 */
	@Test
	public void testEmptySwitches() throws Exception {
		Long [] dpids = new Long [] {};
		final long dpidToTest = 1000L;
		
		roleChanger = EasyMock.createMock(RoleChanger.class);
		// roleChanger methods must not be used
		EasyMock.replay(roleChanger);
		
		initNetwork(roleChanger, dpids);
		
		RoleChangeCallback callback = new RoleChangeCallback();
		callback.controlChanged(dpidToTest, true);
		callback.controlChanged(dpidToTest, false);
		
		EasyMock.verify(roleChanger);
	}
	
	/**
	 * Create mock OFSwitchImpl object.
	 * @param id
	 * @return
	 */
	private OFSwitchImpl createOFSwitchImplMock(Long id) {
		OFSwitchImpl sw = EasyMock.createMock(OFSwitchImpl.class);

		EasyMock.expect(sw.getId()).andReturn(id).anyTimes();
		EasyMock.replay(sw);
		
		return sw;
	}
	
	/**
	 * Setup connectedSwitches
	 * @param changer
	 * @param ids
	 * @throws Exception
	 */
	private void initNetwork(RoleChanger changer, Long [] ids) throws Exception {
		connectedSwitches = new HashSet<OFSwitchImpl>();
		
		for(Long id : ids) {
			connectedSwitches.add(createOFSwitchImplMock(id));
		}
	}
}
