package net.floodlightcontroller.core.internal;

import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;

import net.floodlightcontroller.core.IFloodlightProviderService.Role;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.internal.OFSwitchImpl.PendingRoleRequestEntry;
import net.floodlightcontroller.core.test.MockFloodlightProvider;
import net.floodlightcontroller.test.FloodlightTestCase;

import org.easymock.Capture;
import org.jboss.netty.channel.Channel;
import org.junit.Before;
import org.junit.Test;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFType;
import org.openflow.protocol.OFVendor;
import org.openflow.protocol.vendor.OFVendorData;
import org.openflow.vendor.nicira.OFNiciraVendorData;
import org.openflow.vendor.nicira.OFRoleRequestVendorData;
import org.openflow.vendor.nicira.OFRoleVendorData;

public class OFSwitchImplTest extends FloodlightTestCase {
    protected OFSwitchImpl sw;


    @Before
    public void setUp() throws Exception {
        sw = new OFSwitchImpl();
        Channel ch = createMock(Channel.class);
        SocketAddress sa = new InetSocketAddress(42);
        expect(ch.getRemoteAddress()).andReturn(sa).anyTimes();
        sw.setChannel(ch);
        MockFloodlightProvider floodlightProvider = new MockFloodlightProvider();
        sw.setFloodlightProvider(floodlightProvider);
    }


    public void doSendNxRoleRequest(Role role, int nx_role) throws Exception {
        long cookie = System.nanoTime();

        // verify that the correct OFMessage is sent
        Capture<List<OFMessage>> msgCapture = new Capture<List<OFMessage>>();
        expect(sw.channel.write(capture(msgCapture))).andReturn(null);
        replay(sw.channel);
        int xid = sw.sendNxRoleRequest(role, cookie);
        verify(sw.channel);
        List<OFMessage> msgList = msgCapture.getValue();
        assertEquals(1, msgList.size());
        OFMessage msg = msgList.get(0);
        assertEquals("Transaction Ids must match", xid, msg.getXid());
        assertTrue("Message must be an OFVendor type", msg instanceof OFVendor);
        assertEquals(OFType.VENDOR, msg.getType());
        OFVendor vendorMsg = (OFVendor) msg;
        assertEquals("Vendor message must be vendor Nicira",
                OFNiciraVendorData.NX_VENDOR_ID, vendorMsg.getVendor());
        OFVendorData vendorData = vendorMsg.getVendorData();
        assertTrue("Vendor Data must be an OFRoleRequestVendorData",
                vendorData instanceof OFRoleRequestVendorData);
        OFRoleRequestVendorData roleRequest = (OFRoleRequestVendorData) vendorData;
        assertEquals(nx_role, roleRequest.getRole());

        // Now verify that we've added the pending request correctly
        // to the pending queue
        assertEquals(1, sw.pendingRoleRequests.size());
        PendingRoleRequestEntry pendingRoleRequest = sw.pendingRoleRequests.poll();
        assertEquals(msg.getXid(), pendingRoleRequest.xid);
        assertEquals(role, pendingRoleRequest.role);
        assertEquals(cookie, pendingRoleRequest.cookie);
        reset(sw.channel);
    }

    @Test
    public void testSendNxRoleRequest() throws Exception {
        doSendNxRoleRequest(Role.MASTER, OFRoleVendorData.NX_ROLE_MASTER);
        doSendNxRoleRequest(Role.SLAVE, OFRoleVendorData.NX_ROLE_SLAVE);
        doSendNxRoleRequest(Role.EQUAL, OFRoleVendorData.NX_ROLE_OTHER);
    }


    @Test
    public void testDeliverRoleReplyOk() {
        // test normal case
        PendingRoleRequestEntry pending = new PendingRoleRequestEntry(
                (int) System.currentTimeMillis(),  // arbitrary xid
                Role.MASTER,
                System.nanoTime() // arbitrary cookie
        );
        sw.pendingRoleRequests.add(pending);
        replay(sw.channel);
        sw.deliverRoleReply(pending.xid, pending.role);
        verify(sw.channel);
        assertEquals(true, sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE));
        assertEquals(pending.role, sw.role);
        assertEquals(0, sw.pendingRoleRequests.size());
    }

    @Test
    public void testDeliverRoleReplyOkRepeated() {
        // test normal case. Not the first role reply
        PendingRoleRequestEntry pending = new PendingRoleRequestEntry(
                (int) System.currentTimeMillis(),  // arbitrary xid
                Role.MASTER,
                System.nanoTime() // arbitrary cookie
        );
        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
        sw.pendingRoleRequests.add(pending);
        replay(sw.channel);
        sw.deliverRoleReply(pending.xid, pending.role);
        verify(sw.channel);
        assertEquals(true, sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE));
        assertEquals(pending.role, sw.role);
        assertEquals(0, sw.pendingRoleRequests.size());
    }

    @Test
    public void testDeliverRoleReplyNonePending() {
        // nothing pending 
        expect(sw.channel.close()).andReturn(null);
        replay(sw.channel);
        sw.deliverRoleReply(1, Role.MASTER);
        verify(sw.channel);
        assertEquals(0, sw.pendingRoleRequests.size());
    }

    @Test
    public void testDeliverRoleReplyWrongXid() {
        // wrong xid received 
        PendingRoleRequestEntry pending = new PendingRoleRequestEntry(
                (int) System.currentTimeMillis(),  // arbitrary xid
                Role.MASTER,
                System.nanoTime() // arbitrary cookie
        );
        sw.pendingRoleRequests.add(pending);
        expect(sw.channel.close()).andReturn(null);
        replay(sw.channel);
        sw.deliverRoleReply(pending.xid + 1, pending.role);
        verify(sw.channel);
        assertEquals(null, sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE));
        assertEquals(0, sw.pendingRoleRequests.size());
    }

    @Test
    public void testDeliverRoleReplyWrongRole() {
        // correct xid but incorrect role received
        PendingRoleRequestEntry pending = new PendingRoleRequestEntry(
                (int) System.currentTimeMillis(),  // arbitrary xid
                Role.MASTER,
                System.nanoTime() // arbitrary cookie
        );
        sw.pendingRoleRequests.add(pending);
        expect(sw.channel.close()).andReturn(null);
        replay(sw.channel);
        sw.deliverRoleReply(pending.xid, Role.SLAVE);
        verify(sw.channel);
        assertEquals(null, sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE));
        assertEquals(0, sw.pendingRoleRequests.size());
    }

    @Test
    public void testCheckFirstPendingRoleRequestXid() {
        PendingRoleRequestEntry pending = new PendingRoleRequestEntry(
                54321, Role.MASTER, 232323);
        replay(sw.channel); // we don't expect any invocations 
        sw.pendingRoleRequests.add(pending);
        assertEquals(true, sw.checkFirstPendingRoleRequestXid(54321));
        assertEquals(false, sw.checkFirstPendingRoleRequestXid(0));
        sw.pendingRoleRequests.clear();
        assertEquals(false, sw.checkFirstPendingRoleRequestXid(54321));
        verify(sw.channel);
    }

    @Test
    public void testCheckFirstPendingRoleRequestCookie() {
        PendingRoleRequestEntry pending = new PendingRoleRequestEntry(
                54321, Role.MASTER, 232323);
        replay(sw.channel); // we don't expect any invocations 
        sw.pendingRoleRequests.add(pending);
        assertEquals(true, sw.checkFirstPendingRoleRequestCookie(232323));
        assertEquals(false, sw.checkFirstPendingRoleRequestCookie(0));
        sw.pendingRoleRequests.clear();
        assertEquals(false, sw.checkFirstPendingRoleRequestCookie(232323));
        verify(sw.channel);
    }

    @Test
    public void testDeliverRoleRequestNotSupported() {
        // normal case. xid is pending 
        PendingRoleRequestEntry pending = new PendingRoleRequestEntry(
                (int) System.currentTimeMillis(),  // arbitrary xid
                Role.MASTER,
                System.nanoTime() // arbitrary cookie
        );
        sw.role = Role.SLAVE;
        sw.pendingRoleRequests.add(pending);
        replay(sw.channel);
        sw.deliverRoleRequestNotSupportedEx(pending.xid);
        verify(sw.channel);
        assertEquals(false, sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE));
        assertEquals(null, sw.role);
        assertEquals(0, sw.pendingRoleRequests.size());
    }

    @Test
    public void testDeliverRoleRequestNotSupportedNonePending() {
        // nothing pending 
        sw.role = Role.SLAVE;
        expect(sw.channel.close()).andReturn(null);
        replay(sw.channel);
        sw.deliverRoleRequestNotSupportedEx(1);
        verify(sw.channel);
        assertEquals(null, sw.role);
        assertEquals(0, sw.pendingRoleRequests.size());
    }

    @Test
    public void testDeliverRoleRequestNotSupportedWrongXid() {
        // wrong xid received 
        PendingRoleRequestEntry pending = new PendingRoleRequestEntry(
                (int) System.currentTimeMillis(),  // arbitrary xid
                Role.MASTER,
                System.nanoTime() // arbitrary cookie
        );
        sw.role = Role.SLAVE;
        sw.pendingRoleRequests.add(pending);
        expect(sw.channel.close()).andReturn(null);
        replay(sw.channel);
        sw.deliverRoleRequestNotSupportedEx(pending.xid + 1);
        verify(sw.channel);
        assertEquals(null, sw.role);
        assertEquals(0, sw.pendingRoleRequests.size());
    }
}
