package net.onrc.onos.core.hostmanager;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
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 java.util.Date;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IListener.Command;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IUpdate;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.test.FloodlightTestCase;
import net.floodlightcontroller.util.MACAddress;
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.packet.ARP;
import net.onrc.onos.core.packet.DHCP;
import net.onrc.onos.core.packet.Data;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.IPacket;
import net.onrc.onos.core.packet.IPv4;
import net.onrc.onos.core.packet.UDP;
import net.onrc.onos.core.registry.IControllerRegistryService;
import net.onrc.onos.core.topology.ITopologyListener;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.MockTopology;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.PortNumber;

import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFPacketIn;
import org.projectfloodlight.openflow.protocol.OFPacketInReason;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.OFPort;

/**
 * Unit tests for the Host Manager module (HostManger).
 * These test cases check the result of add/delete host and
 * verify the result of processPacketIn by injecting fake packets.
 * floodlightProvider, datagridService, topologyService,
 * controllerRegistryService, eventChannel are mocked out.
 */
public class HostManagerTest extends FloodlightTestCase {
    private IPacket pkt0, pkt1, pkt2, pkt3, pkt4;
    private IOFSwitch sw1;
    private long sw1Dpid;
    private long sw1DevPort, sw1DevPort2;
    private HostManager hostManager;
    private OFPacketIn pktIn, pktIn2;
    private FloodlightModuleContext modContext;
    private ITopologyService networkGraphService;
    private IEventChannel<Long, Host> eventChannel;
    private IFloodlightProviderService floodlightProvider;
    private Date lastSeenTimestamp;
    private OFFactory ofact;

    @Override
    @Before
    @SuppressWarnings("unchecked")
    public void setUp() throws Exception {
        super.setUp();
        MockTopology topology = new MockTopology();
        IDatagridService datagridService;
        IControllerRegistryService controllerRegistryService;

        topology.createSampleTopology2();
        modContext = new FloodlightModuleContext();

        floodlightProvider = createMock(IFloodlightProviderService.class);
        datagridService = createMock(IDatagridService.class);
        networkGraphService = createMock(ITopologyService.class);
        controllerRegistryService = createMock(IControllerRegistryService.class);
        eventChannel = createMock(IEventChannel.class);
        expect(networkGraphService.getTopology()).andReturn(topology).anyTimes();
        networkGraphService.registerTopologyListener(anyObject(ITopologyListener.class));
        expectLastCall();

        expect(datagridService.createChannel("onos.host", Long.class, Host.class))
        .andReturn(eventChannel).once();
        expect(topology.getOutgoingLink(new Dpid(1L), new PortNumber((short) 100))).andReturn(null).anyTimes();
        expect(datagridService.addListener(
                eq("onos.host"),
                anyObject(IEventChannelListener.class),
                eq(Long.class),
                eq(Host.class)))
                .andReturn(eventChannel).once();

        replay(datagridService);
        replay(networkGraphService);
        replay(controllerRegistryService);

        modContext.addService(IDatagridService.class, datagridService);
        modContext.addService(ITopologyService.class, networkGraphService);
        modContext.addService(IFloodlightProviderService.class, floodlightProvider);
        modContext.getServiceImpl(IFloodlightProviderService.class);
        sw1Dpid = 1L;
        ofact = OFFactories.getFactory(OFVersion.OF_10);

        sw1 = createMockSwitch(sw1Dpid);
        replay(sw1);

        sw1DevPort = 100;
        sw1DevPort2 = 12L;

        hostManager = new HostManager();
        /*
         * Broadcast source address
         */
        this.pkt0 = new Ethernet()
        .setDestinationMACAddress("00:44:33:22:11:33")
        .setSourceMACAddress("FF:FF:FF:FF:FF:FF")
        .setEtherType(Ethernet.TYPE_IPV4)
        .setPayload(
                new IPv4()
                .setTtl((byte) 128)
                .setSourceAddress("192.168.10.1")
                .setDestinationAddress("192.168.255.255")
                .setPayload(getUDP(new Data(new byte[]{0x01}))));

        /*
         * Normal IPv4 packet
         */
        this.pkt1 = new Ethernet()
        .setDestinationMACAddress("00:11:22:33:44:55")
        .setSourceMACAddress("00:44:33:22:11:00")
        .setEtherType(Ethernet.TYPE_IPV4)
        .setPayload(
                new IPv4()
                .setTtl((byte) 128)
                .setSourceAddress("192.168.1.1")
                .setDestinationAddress("192.168.1.2")
                .setPayload(getUDP(new Data(new byte[]{0x01}))));

        /*
         * Same MAC header as pkt1,but not IP address set
         */
        this.pkt2 = new Ethernet()
        .setSourceMACAddress("00:44:33:22:11:01")
        .setDestinationMACAddress("00:11:22:33:44:55")
        .setEtherType(Ethernet.TYPE_IPV4)
        .setPayload(
                new IPv4()
                .setTtl((byte) 128)
                .setPayload(getUDP(new Data(new byte[]{0x01}))));

        /*
         * DHCP packet
         */
        this.pkt3 = new Ethernet()
        .setSourceMACAddress("00:44:33:22:11:01")
        .setDestinationMACAddress("00:11:22:33:44:55")
        .setEtherType(Ethernet.TYPE_IPV4)
        .setPayload(
                new IPv4()
                .setTtl((byte) 128)
                .setSourceAddress("192.168.1.1")
                .setDestinationAddress("192.168.1.2")
                .setPayload(getUDP(
                        new DHCP()
                        .setOpCode(DHCP.OPCODE_REPLY)
                        .setHardwareType(DHCP.HWTYPE_ETHERNET)
                        .setHardwareAddressLength((byte) 6)
                        .setHops((byte) 0)
                        .setTransactionId(0x00003d1d)
                        .setSeconds((short) 0)
                        .setFlags((short) 0)
                        .setClientIPAddress(0)
                        .setYourIPAddress(0)
                        .setServerIPAddress(0)
                        .setGatewayIPAddress(0))));
        /*
         * ARP packet
         */
        this.pkt4 = new Ethernet()
        .setSourceMACAddress("00:44:33:22:11:01")
        .setDestinationMACAddress("00:11:22:33:44:55")
        .setEtherType(Ethernet.TYPE_ARP)
        .setPayload(
                new ARP()
                .setHardwareType(ARP.HW_TYPE_ETHERNET)
                .setProtocolType(ARP.PROTO_TYPE_IP)
                .setHardwareAddressLength((byte) 6)
                .setProtocolAddressLength((byte) 4)
                .setOpCode(ARP.OP_REPLY)
                .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:01"))
                .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1"))
                .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55"))
                .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));


        this.pktIn = getPacketIn((short) sw1DevPort);
        this.pktIn2 = getPacketIn((short) sw1DevPort2);

        lastSeenTimestamp = new Date(1);
    }

    @Override
    @After
    public void tearDown() throws Exception {
    }

    public IOFSwitch createMockSwitch(Long id) {
        IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class);
        expect(mockSwitch.getId()).andReturn(id).anyTimes();
        return mockSwitch;
    }

    /**
     * Test set operation on lastSeenTimstamp field in Host.
     */
    @Test
    public void testSetLastSeenTimestamp() {
        Ethernet eth = (Ethernet) pkt1;
        Host srcHost = hostManager.getSourceHostFromPacket(eth, sw1Dpid, sw1DevPort);

        floodlightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN),
                EasyMock.isA(HostManager.class));
        srcHost.setLastSeenTimestamp(lastSeenTimestamp);
        assertEquals(lastSeenTimestamp, srcHost.getLastSeenTimestamp());
    }
    /**
     * test the functionality to get the source host from Packet header
     * information.
     */
    @Test
    public void testGetSourceHostFromPacket() {
        byte[] address = new byte[] {0x00, 0x44, 0x33, 0x22, 0x11, 0x01};
        MACAddress srcMac = new MACAddress(address);
        Host host1 = new Host(srcMac,
                null,
                sw1Dpid,
                sw1DevPort,
                null);

        /*
         * test DHCP packet case
         */
        Ethernet eth = (Ethernet) pkt3;
        Host host2 = hostManager.getSourceHostFromPacket(eth, sw1Dpid, sw1DevPort);
        assertEquals(host1, host2);

        /*
         * test ARP packet case
         */
        eth = (Ethernet) pkt4;
        host2 = hostManager.getSourceHostFromPacket(eth, sw1Dpid, sw1DevPort);
        assertEquals(host1, host2);
    }

    /**
     * This test will invoke addHost to add a new host through Packet pkt1.
     * @throws FloodlightModuleException
     */
    @Test
    public void testProcessPacketInAddNewHost() throws FloodlightModuleException {
        floodlightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN),
                EasyMock.isA(HostManager.class));
        EasyMock.expectLastCall();
        floodlightProvider.publishUpdate(EasyMock.isA(IUpdate.class));
        EasyMock.expectLastCall();
        replay(floodlightProvider);

        hostManager.init(modContext);
        hostManager.startUp(modContext);
        Command cmd = hostManager.processPacketIn(
                sw1, pktIn, (Ethernet) pkt1, (short) sw1DevPort);
        assertEquals(Command.CONTINUE, cmd);

        EasyMock.verify(floodlightProvider);
    }

    /**
     * Test ProcessPacket function.
     * @throws FloodlightModuleException
     */
    @Test
    public void testProcessPacketInHasLink() throws FloodlightModuleException {
        floodlightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN),
                EasyMock.isA(HostManager.class));
        EasyMock.expectLastCall();
        replay(floodlightProvider);

        hostManager.init(modContext);
        hostManager.startUp(modContext);
        Command cmd = hostManager.processPacketIn(
                sw1, pktIn2, (Ethernet) pkt1, (short) sw1DevPort2);
        assertEquals(Command.CONTINUE, cmd);

        EasyMock.verify(floodlightProvider);
    }

    /**
     * Test return Command.STOP path in processPacketIn method by injecting a broadcast packet.
     */
    @Test
    public void testProcessPacketInStop() {
        Command cmd = hostManager.processPacketIn(
                sw1, pktIn, (Ethernet) pkt0, (short) sw1DevPort);
        assertEquals(Command.STOP, cmd);
    }

    /**
     * Test add a host from the information from packet.
     * @throws FloodlightModuleException
     */
    @Test
    public void testAddHost() throws FloodlightModuleException {
        Ethernet eth = (Ethernet) pkt1;
        Long longmac = eth.getSourceMAC().toLong();
        Host srcHost = hostManager.getSourceHostFromPacket(eth, sw1Dpid, sw1DevPort);

        floodlightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN),
                EasyMock.isA(HostManager.class));
        EasyMock.expectLastCall();
        floodlightProvider.publishUpdate(EasyMock.isA(IUpdate.class));
        EasyMock.expectLastCall();
        replay(floodlightProvider);

        hostManager.init(modContext);
        hostManager.startUp(modContext);
        hostManager.addHost(longmac, srcHost);

        EasyMock.verify(floodlightProvider);
    }

    /**
     * Test delete a host.
     * @throws FloodlightModuleException
     */
    @Test
    public void testDeleteHost() throws FloodlightModuleException {
        Ethernet eth = (Ethernet) pkt1;
        Host srcHost = hostManager.getSourceHostFromPacket(eth, sw1Dpid, sw1DevPort);

        floodlightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN),
                EasyMock.isA(HostManager.class));
        EasyMock.expectLastCall();
        floodlightProvider.publishUpdate(EasyMock.isA(IUpdate.class));
        EasyMock.expectLastCall();
        replay(floodlightProvider);

        hostManager.init(modContext);
        hostManager.startUp(modContext);
        hostManager.deleteHost(srcHost);

        EasyMock.verify(floodlightProvider);
    }

    /**
     * Test delete a host by using its source mac address.
     * @throws FloodlightModuleException
     */
    @Test
    public void testDeleteHostByMac() throws FloodlightModuleException {
        Ethernet eth = (Ethernet) pkt1;
        MACAddress mac = eth.getSourceMAC();

        floodlightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN),
                EasyMock.isA(HostManager.class));
        EasyMock.expectLastCall();
        floodlightProvider.publishUpdate(EasyMock.isA(IUpdate.class));
        EasyMock.expectLastCall();
        replay(floodlightProvider);

        hostManager.init(modContext);
        hostManager.startUp(modContext);
        hostManager.deleteHostByMac(mac);

        EasyMock.verify(floodlightProvider);
    }

    /**
     * Helper for building PacketIns. Defaults to a flowtable miss.
     * @param inport the inport field value
     * @return a PacketIn
     */
    private OFPacketIn getPacketIn(int inport) {
        return ofact.buildPacketIn()
                .setInPort(OFPort.of(inport))
                .setReason(OFPacketInReason.NO_MATCH)
                .build();
    }

    private UDP getUDP(IPacket payload) {
        return (UDP) new UDP()
        .setSourcePort((short) 5000)
        .setDestinationPort((short) 5001)
        .setPayload(payload);
    }
}
