package net.onrc.onos.core.intent.runtime;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.onrc.onos.core.datagrid.IDatagridService;
import net.onrc.onos.core.datagrid.IEventChannel;
import net.onrc.onos.core.datagrid.IEventChannelListener;
import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
import net.onrc.onos.core.intent.FlowEntry;
import net.onrc.onos.core.intent.Intent;
import net.onrc.onos.core.intent.Intent.IntentState;
import net.onrc.onos.core.intent.IntentOperation.Operator;
import net.onrc.onos.core.intent.IntentOperationList;
import net.onrc.onos.core.intent.MockNetworkGraph;
import net.onrc.onos.core.intent.PathIntent;
import net.onrc.onos.core.intent.PathIntentMap;
import net.onrc.onos.core.intent.ShortestPathIntent;
import net.onrc.onos.core.registry.IControllerRegistryService;
import net.onrc.onos.core.topology.DeviceEvent;
import net.onrc.onos.core.topology.INetworkGraphListener;
import net.onrc.onos.core.topology.INetworkGraphService;
import net.onrc.onos.core.topology.LinkEvent;
import net.onrc.onos.core.topology.NetworkGraph;
import net.onrc.onos.core.topology.PortEvent;
import net.onrc.onos.core.topology.SwitchEvent;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

/**
 * @author Toshio Koide (t-koide@onlab.us)
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest(PathCalcRuntimeModule.class)
public class UseCaseTest {
	private NetworkGraph g;
	private FloodlightModuleContext modContext;
	private IDatagridService datagridService;
	private INetworkGraphService networkGraphService;
	private IControllerRegistryService controllerRegistryService;
	private PersistIntent persistIntent;
	@SuppressWarnings("rawtypes")
	private IEventChannel eventChannel;

	private static Long LOCAL_PORT = 0xFFFEL;

	@SuppressWarnings("unchecked")
	@Before
	public void setUp() throws Exception {
		MockNetworkGraph graph = new MockNetworkGraph();
		graph.createSampleTopology1();
		g = graph;

		datagridService = createMock(IDatagridService.class);
		networkGraphService = createMock(INetworkGraphService.class);
		controllerRegistryService = createMock(IControllerRegistryService.class);
		modContext = createMock(FloodlightModuleContext.class);
		eventChannel = createMock(IEventChannel.class);
		persistIntent = PowerMock.createMock(PersistIntent.class);

		PowerMock.expectNew(PersistIntent.class,
				anyObject(IControllerRegistryService.class),
				anyObject(INetworkGraphService.class)).andReturn(persistIntent);

		expect(modContext.getServiceImpl(IDatagridService.class))
		.andReturn(datagridService).once();
		expect(modContext.getServiceImpl(INetworkGraphService.class))
		.andReturn(networkGraphService).once();
		expect(modContext.getServiceImpl(IControllerRegistryService.class))
		.andReturn(controllerRegistryService).once();
		expect(persistIntent.getKey()).andReturn(1L).anyTimes();
		expect(persistIntent.persistIfLeader(eq(1L),
				anyObject(IntentOperationList.class))).andReturn(true).anyTimes();

		expect(networkGraphService.getNetworkGraph()).andReturn(g).anyTimes();
		networkGraphService.registerNetworkGraphListener(anyObject(INetworkGraphListener.class));
		expectLastCall();

		expect(datagridService.createChannel("onos.pathintent", Long.class, IntentOperationList.class))
		.andReturn(eventChannel).once();

		expect(datagridService.addListener(
				eq("onos.pathintent_state"),
				anyObject(IEventChannelListener.class),
				eq(Long.class),
				eq(IntentStateList.class)))
		.andReturn(eventChannel).once();

		replay(datagridService);
		replay(networkGraphService);
		replay(modContext);
		replay(controllerRegistryService);
		PowerMock.replay(persistIntent, PersistIntent.class);
	}

	@After
	public void tearDown() {
		verify(datagridService);
		verify(networkGraphService);
		verify(modContext);
		verify(controllerRegistryService);
		PowerMock.verify(persistIntent, PersistIntent.class);
	}

	private void showResult(PathIntentMap intents) {
		for (Intent intent: intents.getAllIntents()) {
			PathIntent pathIntent = (PathIntent)intent;
			System.out.println("Path intent:" + pathIntent);
			System.out.println("Parent intent: " + pathIntent.getParentIntent().toString());
		}
	}

	@Test
	public void createShortestPaths() throws FloodlightModuleException {
		// create shortest path intents
		IntentOperationList opList = new IntentOperationList();
		opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT));
		opList.add(Operator.ADD, new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT));
		opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));

		// compile high-level intent operations into low-level intent operations (calculate paths)
		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
		runtime1.init(modContext);
		runtime1.startUp(modContext);
		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);

		// compile low-level intents into flow entry installation plan
		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);

		// show results
		showResult((PathIntentMap) runtime1.getPathIntents());
		System.out.println(plan);
	}

	@Test
	public void createConstrainedShortestPaths() throws FloodlightModuleException {
		// create constrained shortest path intents
		IntentOperationList opList = new IntentOperationList();
		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT, 400.0));
		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT, 400.0));
		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("3", 2L, 24L, LOCAL_PORT, 4L, 42L, LOCAL_PORT, 400.0));
		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("4", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT, 400.0));
		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("5", 3L, 34L, LOCAL_PORT, 4L, 43L, LOCAL_PORT, 400.0));

		// compile high-level intent operations into low-level intent operations (calculate paths)
		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
		runtime1.init(modContext);
		runtime1.startUp(modContext);
		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);

		// compile low-level intents into flow entry installation plan
		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);

		// show results
		showResult((PathIntentMap) runtime1.getPathIntents());
		System.out.println(plan);
	}

	@Test
	public void createMixedShortestPaths() throws FloodlightModuleException {
		// create constrained & best effort shortest path intents
		IntentOperationList opList = new IntentOperationList();
		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT, 400.0));
		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT, 400.0));
		opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 24L, LOCAL_PORT, 4L, 42L, LOCAL_PORT));
		opList.add(Operator.ADD, new ShortestPathIntent("4", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));
		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("5", 3L, 34L, LOCAL_PORT, 4L, 43L, LOCAL_PORT, 400.0));

		// compile high-level intent operations into low-level intent operations (calculate paths)
		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
		runtime1.init(modContext);
		runtime1.startUp(modContext);
		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);

		// compile low-level intents into flow entry installation plan
		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);

		// show results
		showResult((PathIntentMap) runtime1.getPathIntents());
		System.out.println(plan);
	}

	@Test
	public void rerouteShortestPaths() throws FloodlightModuleException {
		List<SwitchEvent> addedSwitchEvents = new LinkedList<>();
		List<SwitchEvent> removedSwitchEvents = new LinkedList<>();
		List<PortEvent> addedPortEvents = new LinkedList<>();
		List<PortEvent> removedPortEvents = new LinkedList<>();
		List<LinkEvent> addedLinkEvents = new LinkedList<>();
		List<LinkEvent> removedLinkEvents = new LinkedList<>();
		List<DeviceEvent> addedDeviceEvents = new LinkedList<>();
		List<DeviceEvent> removedDeviceEvents = new LinkedList<>();

		// create shortest path intents
		IntentOperationList opList = new IntentOperationList();
		opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT));
		opList.add(Operator.ADD, new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT));
		opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));

		// compile high-level intent operations into low-level intent operations (calculate paths)
		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
		runtime1.init(modContext);
		runtime1.startUp(modContext);
		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);

		// compile low-level intents into flow entry installation plan
		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);

		// show results step1
		showResult((PathIntentMap) runtime1.getPathIntents());
		System.out.println(plan);

		// TODO this state changes should be triggered by notification of plan module
		IntentStateList states = new IntentStateList();
		states.put("1", IntentState.INST_ACK);
		states.put("2", IntentState.INST_ACK);
		states.put("3", IntentState.INST_ACK);
		runtime1.getHighLevelIntents().changeStates(states);
		states.clear();
		states.put("1___0", IntentState.INST_ACK);
		states.put("2___0", IntentState.INST_ACK);
		states.put("3___0", IntentState.INST_ACK);
		runtime1.getPathIntents().changeStates(states);

		// link down
		((MockNetworkGraph)g).removeLink(1L, 12L, 2L, 21L); // This link is used by the intent "1"
		((MockNetworkGraph)g).removeLink(2L, 21L, 1L, 12L);
		LinkEvent linkEvent1 = new LinkEvent(1L, 12L, 2L, 21L);
		LinkEvent linkEvent2 = new LinkEvent(2L, 21L, 1L, 12L);
		removedLinkEvents.clear();
		removedLinkEvents.add(linkEvent1);
		removedLinkEvents.add(linkEvent2);
		runtime1.networkGraphEvents(
				addedSwitchEvents,
				removedSwitchEvents,
				addedPortEvents,
				removedPortEvents,
				addedLinkEvents,
				removedLinkEvents,
				addedDeviceEvents,
				removedDeviceEvents);
		System.out.println("Link goes down.");

		// show results step2
		showResult((PathIntentMap) runtime1.getPathIntents());
		// TODO: show results of plan computation
	}


	@Test
	public void createAndRemoveShortestPaths() throws FloodlightModuleException {
		// create shortest path intents
		IntentOperationList opList = new IntentOperationList();
		opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT));
		opList.add(Operator.ADD, new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT));
		opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));

		// compile high-level intent operations into low-level intent operations (calculate paths)
		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
		runtime1.init(modContext);
		runtime1.startUp(modContext);
		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);

		// compile low-level intents into flow entry installation plan
		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);

		// show results
		showResult((PathIntentMap) runtime1.getPathIntents());
		System.out.println(plan);

		// create remove operations
		opList.clear();
		opList.add(Operator.REMOVE, new Intent("1"));
		opList.add(Operator.REMOVE, new Intent("2"));

		// compile
		runtime1.executeIntentOperations(opList);

		// show results
		showResult((PathIntentMap) runtime1.getPathIntents());
		System.out.println(plan);
	}

}
