package net.onrc.onos.ofcontroller.flowprogrammer;

import static org.junit.Assert.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;

import io.netty.util.concurrent.Future;
import net.floodlightcontroller.core.IOFSwitch;
import net.onrc.onos.graph.GraphDBOperation;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.flowmanager.FlowDatabaseOperation;
import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.FlowEntryId;

import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFStatisticsRequest;
import org.openflow.protocol.OFType;
import org.openflow.protocol.statistics.OFFlowStatisticsReply;
import org.openflow.protocol.statistics.OFStatistics;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;


@RunWith(PowerMockRunner.class)
@PrepareForTest({FlowSynchronizer.class, GraphDBOperation.class, FlowDatabaseOperation.class})
public class FlowSynchronizerTest {
	private FlowPusher pusher;
	private FlowSynchronizer sync;
	private List<Long> idAdded;
	private List<Long> idRemoved;

	@Before
	public void setUp() throws Exception {
		idAdded = new ArrayList<Long>();
		idRemoved = new ArrayList<Long>();
		
		pusher = EasyMock.createMock(FlowPusher.class);
		EasyMock.expect(pusher.add(EasyMock.anyObject(IOFSwitch.class), EasyMock.anyObject(OFMessage.class)))
			.andAnswer(new IAnswer<Boolean>() {
				@Override
				public Boolean answer() throws Throwable {
					OFMessage msg = (OFMessage)EasyMock.getCurrentArguments()[1];
					if (msg.getType().equals(OFType.FLOW_MOD)) {
						OFFlowMod fm = (OFFlowMod)msg;
						if (fm.getCommand() == OFFlowMod.OFPFC_DELETE_STRICT) {
							idRemoved.add(fm.getCookie());
						}
					}
					return null;
				}
			}).anyTimes();
		EasyMock.expect(pusher.add(EasyMock.anyObject(IOFSwitch.class), EasyMock.anyObject(FlowEntry.class)))
		.andAnswer(new IAnswer<Boolean>() {
			@Override
			public Boolean answer() throws Throwable {
				FlowEntry flow = (FlowEntry)EasyMock.getCurrentArguments()[1];
				idAdded.add(flow.flowEntryId().value());
				return null;
			}
		}).anyTimes();
		EasyMock.replay(pusher);
	}

	@After
	public void tearDown() throws Exception {
	}

	/**
	 * Test that synchronization doesn't affect anything in case either DB and
	 * flow table has the same entries.
	 */
	@Test
	public void testStable() {
		// Create mock of flow table : flow 1
		IOFSwitch sw = createMockSwitch(new long[] {1});
		
		// Create mock of flow entries : flow 1
		initMockGraph(new long[] {1});
		
		// synchronize
		doSynchronization(sw,100);
		
		// check if flow is not changed
		assertEquals(0, idAdded.size());
		assertEquals(0, idRemoved.size());
	}

	/**
	 * Test that an flow is added in case DB has an extra FlowEntry.
	 */
	@Test
	public void testSingleAdd() {
		// Create mock of flow table : null
		IOFSwitch sw = createMockSwitch(new long[] {});
		
		// Create mock of flow entries : flow 1
		initMockGraph(new long[] {1});
		
		// synchronize
		doSynchronization(sw,100);
		
		// check if single flow is installed
		assertEquals(1, idAdded.size());
		assertTrue(idAdded.contains((long)1));
		assertEquals(0, idRemoved.size());
	}

	/**
	 * Test that an flow is deleted in case switch has an extra FlowEntry.
	 */
	@Test
	public void testSingleDelete() {
		// Create mock of flow table : flow 1
		IOFSwitch sw = createMockSwitch(new long[] {1});
		
		// Create mock of flow entries : null
		initMockGraph(new long[] {});
		
		// synchronize
		doSynchronization(sw,100);
		
		// check if single flow is deleted
		assertEquals(0, idAdded.size());
		assertEquals(1, idRemoved.size());
		assertTrue(idRemoved.contains((long)1));
	}
	
	/**
	 * Test that appropriate flows are added and other appropriate flows are deleted
	 * in case flows in DB are overlapping flows in switch.
	 */
	@Test
	public void testMixed() {
		// Create mock of flow table : flow 1,2,3
		IOFSwitch sw = createMockSwitch(new long[] {1,2,3});
		
		// Create mock of flow entries : flow 2,3,4,5
		initMockGraph(new long[] {2,3,4,5});
		
		// synchronize
		doSynchronization(sw,100);
		
		// check if two flows {4,5} is installed and one flow {1} is deleted
		assertEquals(2, idAdded.size());
		assertTrue(idAdded.contains((long)4));
		assertTrue(idAdded.contains((long)5));
		assertEquals(1, idRemoved.size());
		assertTrue(idRemoved.contains((long)1));
	}
	

	@Test
	public void testMassive() {
		// Create mock of flow table : flow 0-1999
		long [] swIdList = new long [2000];
		for (long i = 0; i < 2000; ++i) {
			swIdList[(int)i] = i;
		}
		IOFSwitch sw = createMockSwitch(swIdList);
		
		// Create mock of flow entries : flow 1500-3499
		long [] dbIdList = new long [2000];
		for (long i = 0; i < 2000; ++i) {
			dbIdList[(int)i] = 1500 + i;
		}
		initMockGraph(dbIdList);

		// synchronize
		doSynchronization(sw, 3000);
		
		// check if 1500 flows {2000-3499} is installed and 1500 flows {0,...,1499} is deleted
		assertEquals(1500, idAdded.size());
		for (long i = 2000; i < 3500; ++i) {
			assertTrue(idAdded.contains(i));
		}
		assertEquals(1500, idRemoved.size());
		for (long i = 0; i < 1500; ++i) {
			assertTrue(idRemoved.contains(i));
		}
	}

	/**
	 * Create mock IOFSwitch with flow table which has arbitrary flows.
	 * @param cookieList List of FlowEntry IDs switch has.
	 * @return Mock object.
	 */
	private IOFSwitch createMockSwitch(long[] cookieList) {
		IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
		EasyMock.expect(sw.getId()).andReturn((long)1).anyTimes();
		
		List<OFStatistics> stats = new ArrayList<OFStatistics>();
		for (long cookie : cookieList) {
			stats.add(createReply(cookie));
		}
		
		@SuppressWarnings("unchecked")
		Future<List<OFStatistics>> future = EasyMock.createMock(Future.class);
		try {
			EasyMock.expect(future.get()).andReturn(stats).once();
		} catch (InterruptedException e1) {
			fail("Failed in Future#get()");
		} catch (ExecutionException e1) {
			fail("Failed in Future#get()");
		}
		EasyMock.replay(future);
		
		try {
			EasyMock.expect(sw.getStatistics(EasyMock.anyObject(OFStatisticsRequest.class)))
				.andReturn(future).once();
		} catch (IOException e) {
			fail("Failed in IOFSwitch#getStatistics()");
		}
		
		EasyMock.replay(sw);
		return sw;
	}
	
	/**
	 * Create single OFFlowStatisticsReply object which is actually obtained from switch.
	 * @param cookie Cookie value, which indicates ID of FlowEntry installed to switch.
	 * @return Created object.
	 */
	private OFFlowStatisticsReply createReply(long cookie) {
		OFFlowStatisticsReply stat = new OFFlowStatisticsReply();
		OFMatch match = new OFMatch();
		
		stat.setCookie(cookie);
		stat.setMatch(match);
		stat.setPriority((short)1);

		return stat;
	}
	
	/**
	 * Create mock GraphDBOperation and FlowDatabaseOperation to mock DB.
	 * @param idList List of FlowEntry IDs stored in DB.
	 */
	private void initMockGraph(long[] idList) {
		List<IFlowEntry> flowEntryList = new ArrayList<IFlowEntry>();
		
		for (long id : idList) {
			IFlowEntry entry = EasyMock.createMock(IFlowEntry.class);
			EasyMock.expect(entry.getFlowEntryId()).andReturn(String.valueOf(id)).anyTimes();
			EasyMock.replay(entry);
			flowEntryList.add(entry);
		}
		
		ISwitchObject swObj = EasyMock.createMock(ISwitchObject.class);
		EasyMock.expect(swObj.getFlowEntries()).andReturn(flowEntryList).once();
		EasyMock.replay(swObj);
		
		GraphDBOperation mockOp = PowerMock.createMock(GraphDBOperation.class);
		EasyMock.expect(mockOp.searchSwitch(EasyMock.anyObject(String.class))).andReturn(swObj).once();
		
		PowerMock.mockStatic(FlowDatabaseOperation.class);
		for (IFlowEntry entry : flowEntryList) {
			EasyMock.expect(FlowDatabaseOperation.extractFlowEntry(EasyMock.eq(entry)))
				.andAnswer(new IAnswer<FlowEntry>() {
					@Override
					public FlowEntry answer() throws Throwable {
						IFlowEntry iflow = (IFlowEntry)EasyMock.getCurrentArguments()[0];
						long flowEntryId = Long.valueOf(iflow.getFlowEntryId());
						
						FlowEntry flow = EasyMock.createMock(FlowEntry.class);
						EasyMock.expect(flow.flowEntryId()).andReturn(new FlowEntryId(flowEntryId)).anyTimes();
						EasyMock.replay(flow);
						return flow;
					}
					
				}).anyTimes();
			EasyMock.expect(mockOp.searchFlowEntry(EasyMock.eq(new FlowEntryId(entry.getFlowEntryId()))))
				.andReturn(entry);
		}
		PowerMock.replay(FlowDatabaseOperation.class);
		EasyMock.replay(mockOp);
		
		try {
			PowerMock.expectNew(GraphDBOperation.class, "").andReturn(mockOp);
		} catch (Exception e) {
			fail("Failed to create GraphDBOperation");
		}
		PowerMock.replay(GraphDBOperation.class);
	}
	
	/**
	 * Instantiate FlowSynchronizer and sync flows.
	 * @param sw Target IOFSwitch object
	 */
	private void doSynchronization(IOFSwitch sw, long wait) {
		sync = new FlowSynchronizer();
		sync.init(pusher);
		sync.synchronize(sw);
		
		try {
			Thread.sleep(wait);
		} catch (InterruptedException e) {
			fail("Failed to sleep");
		}
	}
}
