package net.onrc.onos.ofcontroller.core;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.HashMap;

import net.onrc.onos.graph.GraphDBConnection;
import net.onrc.onos.graph.GraphDBOperation;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
import net.onrc.onos.ofcontroller.core.internal.TestDatabaseManager;
import org.easymock.EasyMock;
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.slf4j.LoggerFactory;
import org.powermock.modules.junit4.PowerMockRunner;

import com.thinkaurelius.titan.core.TitanFactory;
import com.thinkaurelius.titan.core.TitanGraph;

//Add Powermock preparation
@RunWith(PowerMockRunner.class)
@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
public class INetMapTopologyObjectsIFlowPathTest {
	
	//The test network is ./titan/schema/test-network.xml

	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);

	String conf;
    private GraphDBConnection conn = null;
    private GraphDBOperation ope = null;
    private TitanGraph titanGraph = null;
	private IFlowPath flowPath = null;
	private IFlowEntry flowEntry = null;
	
	@Before
	public void setUp() throws Exception {
		conf = "/dummy/path/to/db";
		
		// Make mock cassandra DB
		// Replace TitanFactory.open() to return mock DB
		TestDatabaseManager.deleteTestDatabase();
		titanGraph = TestDatabaseManager.getTestDatabase();
		//TestDatabaseManager.populateTestData(titanGraph);
		PowerMock.mockStatic(TitanFactory.class);
		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
		PowerMock.replay(TitanFactory.class);
		
		conn = GraphDBConnection.getInstance(conf);
		ope = new GraphDBOperation(conn);
		
		flowPath = ope.newFlowPath();
		flowEntry = ope.newFlowEntry();
		flowEntry.setState("zz");
	}

	@After
	public void tearDown() throws Exception {
		titanGraph.shutdown();
		TestDatabaseManager.deleteTestDatabase();
	}
	
	/**
	 * Desc:
	 *  Test method for get and set FlowId method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the flow id.
	 * 2. Should get the flow id.
	 */
	@Test
	public void testSetGetFlowId() {
		String flowId = "xx";
		flowPath.setFlowId(flowId);
		assertEquals(flowPath.getFlowId(), flowId);
	}
	
	/**
	 * Desc:
	 *  Test method for get and set InstallerId method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the installer id.
	 * 2. Should get the installer id.
	 */
	@Test
	public void testSetGetInstallerId() {
		String flowId = "xx";
		String installerId = "yy";
		flowPath.setFlowId(flowId);
		flowPath.setInstallerId(installerId);
		assertEquals(flowPath.getInstallerId(), installerId);
	}

	/**
	 * Desc:
	 *  Test method for get and set FlowPathType method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the Flow Path Type.
	 * 2. Should get the Flow Path Type.
	 */
	@Test
	public void testSetGetFlowPathType() {
		String flowId = "xx";
		String flowPathType = "FP_TYPE_SHORTEST_PATH";
		flowPath.setFlowId(flowId);
		flowPath.setFlowPathType(flowPathType);
		assertEquals(flowPath.getFlowPathType(), flowPathType);
	}

	/**
	 * Desc:
	 *  Test method for get and set FlowPathUserState method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the Flow Path User State.
	 * 2. Should get the Flow Path User State.
	 */
	@Test
	public void testSetGetFlowPathUserState() {
		String flowId = "xx";
		String flowPathUserState = "FP_USER_ADD";
		flowPath.setFlowId(flowId);
		flowPath.setFlowPathUserState(flowPathUserState);
		assertEquals(flowPath.getFlowPathUserState(), flowPathUserState);
	}

	/**
	 * Desc:
	 *  Test method for get and set FlowPathFlags method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the Flow Path Flags.
	 * 2. Should get the Flow Path Flags.
	 */
	@Test
	public void testSetGetFlowPathFlags() {
		String flowId = "xx";
		Long flowPathFlags = new Long(0x3);
		flowPath.setFlowId(flowId);
		flowPath.setFlowPathFlags(flowPathFlags);
		assertEquals(flowPath.getFlowPathFlags(), flowPathFlags);
	}

	/**
	 * Desc:
	 *  Test method for get and set Idle Timeout method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the Idle Timeout.
	 * 2. Should get the Idle Timeout.
	 */
	@Test
	public void testSetGetIdleTimeout() {
		String flowId = "xx";
		Integer idleTimeout = 5;
		flowPath.setFlowId(flowId);
		flowPath.setIdleTimeout(idleTimeout);
		assertEquals(flowPath.getIdleTimeout(), idleTimeout);
	}

	/**
	 * Desc:
	 *  Test method for get and set Hard Timeout method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the Hard Timeout.
	 * 2. Should get the Hard Timeout.
	 */
	@Test
	public void testSetGetHardTimeout() {
		String flowId = "xx";
		Integer hardTimeout = 5;
		flowPath.setFlowId(flowId);
		flowPath.setHardTimeout(hardTimeout);
		assertEquals(flowPath.getHardTimeout(), hardTimeout);
	}

	/**
	 * Desc:
	 *  Test method for get and set SourceSwitch method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the source switch.
	 * 2. Should get the source switch.
	 */
	@Test
	public void testSetGetSourceSwitch() {
		String flowId = "xx";
		String sourceSwitch = "aa";
		flowPath.setFlowId(flowId);
		flowPath.setSrcSwitch(sourceSwitch);
		assertEquals(flowPath.getSrcSwitch(), sourceSwitch);
	}
	
	/**
	 * Desc:
	 *  Test method for get and set SourcePort method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the source port.
	 * 2. Should get the source port.
	 */
	@Test
	public void testSetGetSourcePort() {
		String flowId = "xx";
		Short sourcePort = 1;
		flowPath.setFlowId(flowId);
		flowPath.setSrcPort(sourcePort);
		assertEquals(flowPath.getSrcPort(), sourcePort);
	}
	
	/**
	 * Desc:
	 *  Test method for get and set DestSwitch method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the dest switch.
	 * 2. Should get the dest switch.
	 */
	@Test
	public void testSetGetDestSwitch() {
		String flowId = "xx";
		String destSwitch = "bb";
		flowPath.setFlowId(flowId);
		flowPath.setDstSwitch(destSwitch);
		assertEquals(flowPath.getDstSwitch(), destSwitch);
	}
	
	/**
	 * Desc:
	 *  Test method for get and set DestPort method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the source dest port.
	 * 2. Should get the source dest port.
	 */
	@Test
	public void testSetGetDstPort() {
		String flowId = "xx";
		Short dstPort = 2;
		flowPath.setFlowId(flowId);
		flowPath.setDstPort(dstPort);
		assertEquals(flowPath.getDstPort(), dstPort);
	}
	
	/**
	 * Desc:
	 *  Test method for get and set DataPathSummary method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set the data path summary.
	 * 2. Should get the data path summary.
	 */
	@Test
	public void testSetGetDataPathSummary() {
		String flowId = "xx";
		String dataPathSummary = "yy";
		flowPath.setFlowId(flowId);
		flowPath.setInstallerId(dataPathSummary);
		assertEquals(flowPath.getInstallerId(), dataPathSummary);
	}
	
	public boolean testIFlowEntry(IFlowPath fp, IFlowEntry fe)
	{
		ArrayList<IFlowEntry> flowEntryList = new ArrayList<IFlowEntry>();
		for(IFlowEntry inFlowEntry : fp.getFlowEntries())
		{
			flowEntryList.add(inFlowEntry);
		}
		return flowEntryList.contains(fe);
	}
	
	/**
	 * Desc:
	 *  Test method for addFlowEntry and getFlorEntries method.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should add the FlowEntry.
	 * 2. Should get the FlowEntries. It is tested in the testIFlowEntry method.
	 */
	@Test
	public void testAddFlowEntryAndGetFlowEntries() {
		String flowId = "xx";
		flowPath.setFlowId(flowId);
		flowPath.addFlowEntry(flowEntry);
		IFlowEntry flowEntry2 = ope.newFlowEntry();
		flowPath.addFlowEntry(flowEntry2);
		assertTrue(testIFlowEntry(flowPath, flowEntry));
		assertTrue(testIFlowEntry(flowPath, flowEntry2));
	}
	
	/**
	 * Desc:
	 *  Test method for remove FlowEntry.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should remove FlowEntry.
	 */
	@Test
	public void testRemoveFlowEntry() {
		String flowId = "xx";
		flowPath.setFlowId(flowId);
		flowPath.addFlowEntry(flowEntry);
		flowPath.removeFlowEntry(flowEntry);
		assertTrue(!testIFlowEntry(flowPath, flowEntry));
	}
	
	/**
	 * Desc:
	 *  Test method for set and get MatchSrcMac
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchSrcMac.
	 * 2. Should get MatchSrcMac.
	 */
	@Test
	public void testSetGetMatchSrcMac() {
		String flowId = "xx";
		String matchSrcMac = "00:00:00:00:00:11";
		flowPath.setFlowId(flowId);
		flowPath.setMatchSrcMac(matchSrcMac);
		assertEquals(flowPath.getMatchSrcMac(), matchSrcMac);
	}
	
	/**
	 * Desc:
	 *  Test method for set and get MatchDstMac.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchDstMac.
	 * 2. Should get MatchDstMac.
	 */
	@Test
	public void testSetGetMatchDstMac() {
		String flowId = "xx";
		String matchDstMac = "00:00:00:00:00:11";
		flowPath.setFlowId(flowId);
		flowPath.setMatchDstMac(matchDstMac);
		assertEquals(flowPath.getMatchDstMac(), matchDstMac);
	}

	/**
	 * Desc:
	 *  Test method for set and get MatchEthernetFrameType
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchEthernetFrameType.
	 * 2. Should get MatchEthernetFrameType.
	 */
	@Test
	public void testSetGetMatchEthernetFrameType() {
		String flowId = "xx";
		Short matchEthernetFrameType = 1;
		flowPath.setFlowId(flowId);
		flowPath.setMatchEthernetFrameType(matchEthernetFrameType);
		assertEquals(flowPath.getMatchEthernetFrameType(), matchEthernetFrameType);
	}

	/**
	 * Desc:
	 *  Test method for set and get MatchVlanId
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchVlanId.
	 * 2. Should get MatchVlanId.
	 */
	@Test
	public void testSetGetMatchVlanId() {
		String flowId = "xx";
		Short matchVlanId = 10;
		flowPath.setFlowId(flowId);
		flowPath.setMatchVlanId(matchVlanId);
		assertEquals(flowPath.getMatchVlanId(), matchVlanId);
	}

	/**
	 * Desc:
	 *  Test method for set and get MatchVlanPriority
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchVlanPriority.
	 * 2. Should get MatchVlanPriority.
	 */
	@Test
	public void testSetGetMatchVlanPriority() {
		String flowId = "xx";
		Byte matchVlanPriority = 20;
		flowPath.setFlowId(flowId);
		flowPath.setMatchVlanPriority(matchVlanPriority);
		assertEquals(flowPath.getMatchVlanPriority(), matchVlanPriority);
	}
	
	/**
	 * Desc:
	 *  Test method for set and get MatchSrcIPv4Net.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchSrcIPv4Net.
	 * 2. Should get MatchSrcIPv4Net.
	 */
	@Test
	public void testSetGetMatchSrcIPv4Net() {
		String flowId = "xx";
		String ip = "192.168.0.1";
		flowPath.setFlowId(flowId);
		flowPath.setMatchSrcIPv4Net(ip);
		assertEquals(flowPath.getMatchSrcIPv4Net(), ip);
	}
	
	/**
	 * Desc:
	 *  Test method for set and get MatchDstIPv4Net.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchDstIPv4Net.
	 * 2. Should get MatchDstIPv4Net.
	 */
	@Test
	public void testSetGetMatchDstIPv4Net() {
		String flowId = "xx";
		String ip = "192.168.0.1";
		flowPath.setFlowId(flowId);
		flowPath.setMatchDstIPv4Net(ip);
		assertEquals(flowPath.getMatchDstIPv4Net(), ip);
	}

	/**
	 * Desc:
	 *  Test method for set and get MatchIpProto
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchIpProto.
	 * 2. Should get MatchIpProto.
	 */
	@Test
	public void testSetGetMatchIpProto() {
		String flowId = "xx";
		Byte matchIpProto = 20;
		flowPath.setFlowId(flowId);
		flowPath.setMatchIpProto(matchIpProto);
		assertEquals(flowPath.getMatchIpProto(), matchIpProto);
	}

	/**
	 * Desc:
	 *  Test method for set and get MatchIpToS
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchIpToS.
	 * 2. Should get MatchIpToS.
	 */
	@Test
	public void testSetGetMatchIpToS() {
		String flowId = "xx";
		Byte matchIpToS = 20;
		flowPath.setFlowId(flowId);
		flowPath.setMatchIpToS(matchIpToS);
		assertEquals(flowPath.getMatchIpToS(), matchIpToS);
	}

	/**
	 * Desc:
	 *  Test method for set and get MatchSrcTcpUdpPort.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchSrcTcpUdpPort.
	 * 2. Should get MatchSrcTcpUdpPort.
	 */
	@Test
	public void testSetGetMatchSrcTcpUdpPort() {
		String flowId = "xx";
		Short srcTcpUdpPort = (short)65535;
		flowPath.setFlowId(flowId);
		flowPath.setMatchSrcTcpUdpPort(srcTcpUdpPort);
		assertEquals(flowPath.getMatchSrcTcpUdpPort(), srcTcpUdpPort);
	}

	/**
	 * Desc:
	 *  Test method for set and get MatchDstTcpUdpPort.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should set MatchDstTcpUdpPort.
	 * 2. Should get MatchDstTcpUdpPort.
	 */
	@Test
	public void testSetGetMatchDstTcpUdpPort() {
		String flowId = "xx";
		Short dstTcpUdpPort = (short)65535;
		flowPath.setFlowId(flowId);
		flowPath.setMatchDstTcpUdpPort(dstTcpUdpPort);
		assertEquals(flowPath.getMatchDstTcpUdpPort(), dstTcpUdpPort);
	}

	/**
	 * Desc:
	 *  Test method for get Switches.
	 * Condition:
	 *  N/A
	 * Expect:
	 * 1. Should get switches.
	 */
	@Test
	public void testGetSwitches() {
		String flowId = "xx";
		String dpid = "1";
		flowPath.setFlowId(flowId);
		ISwitchObject sw = ope.newSwitch(dpid);
		flowEntry.setSwitch(sw);
		flowPath.addFlowEntry(flowEntry);
		
		HashMap<String, ISwitchObject> swList = new HashMap<String, ISwitchObject>();
		for(ISwitchObject insw : flowPath.getSwitches()){
			swList.put(sw.getDPID(), insw);
		}
		
		assertTrue(swList.containsKey(dpid));
	}
	
	//TODO Dont know how to set the state property.
	@Test
	public void testGetState() {
		String status = null;
		assertEquals(flowPath.getState(), status);
	}
	
	
}
