package net.floodlightcontroller.core.internal;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;

import net.floodlightcontroller.core.IFloodlightProviderService.Role;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.internal.RoleChanger.RoleChangeTask;

import org.easymock.EasyMock;
import org.jboss.netty.channel.Channel;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

public class RoleChangerTest {
    public RoleChanger roleChanger;
    
    @Before
    public void setUp() throws Exception {
        roleChanger = new RoleChanger();
    }
    
    /**
     * Send a role request for SLAVE to a switch that doesn't support it. 
     * The connection should be closed.
     */
    @Test
    public void testSendRoleRequestSlaveNotSupported() {
        LinkedList<OFSwitchImpl> switches = new LinkedList<OFSwitchImpl>();
        
        // a switch that doesn't support role requests
        OFSwitchImpl sw1 = EasyMock.createMock(OFSwitchImpl.class);
        Channel channel1 = createMock(Channel.class);
        expect(sw1.getChannel()).andReturn(channel1);
        // No support for NX_ROLE
        expect(sw1.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
                        .andReturn(false); 
        expect(channel1.close()).andReturn(null);
        switches.add(sw1);
        
        replay(sw1, channel1);
        roleChanger.sendRoleRequest(switches, Role.SLAVE, 123456);
        verify(sw1, channel1);
        
        // sendRoleRequest needs to remove the switch from the list since
        // it closed its connection
        assertTrue(switches.isEmpty());
    }
    
    /**
     * Send a role request for MASTER to a switch that doesn't support it. 
     * The connection should be closed.
     */
    @Test
    @Ignore // FIXME: ONOS modified the behavior here to intentionally trigger OFS error.
    public void testSendRoleRequestMasterNotSupported() {
        LinkedList<OFSwitchImpl> switches = new LinkedList<OFSwitchImpl>();
        
        // a switch that doesn't support role requests
        OFSwitchImpl sw1 = EasyMock.createMock(OFSwitchImpl.class);
        // No support for NX_ROLE
        expect(sw1.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
                        .andReturn(false); 
        switches.add(sw1);
        
        replay(sw1);
        roleChanger.sendRoleRequest(switches, Role.MASTER, 123456);
        verify(sw1);
        
        assertEquals(1, switches.size());
    }
    
    /**
     * Send a role request a switch that supports it and one that 
     * hasn't had a role request send to it yet
     */
    @Test
    public void testSendRoleRequestErrorHandling () throws Exception {
        LinkedList<OFSwitchImpl> switches = new LinkedList<OFSwitchImpl>();
        
        // a switch that supports role requests
        OFSwitchImpl sw1 = EasyMock.createMock(OFSwitchImpl.class);
        // No support for NX_ROLE
        expect(sw1.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
                        .andReturn(true); 
        expect(sw1.sendNxRoleRequest(Role.MASTER, 123456))
                    .andThrow(new IOException()).once();
        Channel channel1 = createMock(Channel.class);
        expect(sw1.getChannel()).andReturn(channel1);
        expect(channel1.close()).andReturn(null);
        switches.add(sw1);
        
        replay(sw1);
        roleChanger.sendRoleRequest(switches, Role.MASTER, 123456);
        verify(sw1);
        
        assertTrue(switches.isEmpty());
    }
    
    /**
     * Check error handling 
     * hasn't had a role request send to it yet
     */
    @Test
    public void testSendRoleRequestSupported() throws Exception {
        LinkedList<OFSwitchImpl> switches = new LinkedList<OFSwitchImpl>();
        
        // a switch that supports role requests
        OFSwitchImpl sw1 = EasyMock.createMock(OFSwitchImpl.class);
        // No support for NX_ROLE
        expect(sw1.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
                        .andReturn(true); 
        expect(sw1.sendNxRoleRequest(Role.MASTER, 123456)).andReturn(1).once();
        switches.add(sw1);
        
        // a switch for which we don't have SUPPORTS_NX_ROLE yet
        OFSwitchImpl sw2 = EasyMock.createMock(OFSwitchImpl.class);
        // No support for NX_ROLE
        expect(sw2.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
                        .andReturn(null); 
        expect(sw2.sendNxRoleRequest(Role.MASTER, 123456)).andReturn(1).once();
        switches.add(sw2);
        
        
        replay(sw1, sw2);
        roleChanger.sendRoleRequest(switches, Role.MASTER, 123456);
        verify(sw1, sw2);
        
        assertEquals(2, switches.size());
    }
    
    @Test
    public void testVerifyRoleReplyReceived() {
        LinkedList<OFSwitchImpl> switches = new LinkedList<OFSwitchImpl>();
        
        // Add a switch that has received a role reply
        OFSwitchImpl sw1 = EasyMock.createMock(OFSwitchImpl.class);
        expect(sw1.checkFirstPendingRoleRequestCookie(123456))
                        .andReturn(false).once();
        switches.add(sw1);
        
        // Add a switch that has not yet received a role reply
        OFSwitchImpl sw2 = EasyMock.createMock(OFSwitchImpl.class);
        expect(sw2.checkFirstPendingRoleRequestCookie(123456))
                        .andReturn(true).once();
        Channel channel2 = createMock(Channel.class);
        expect(sw2.getChannel()).andReturn(channel2);
        expect(channel2.close()).andReturn(null);
        switches.add(sw2);
        
        
        replay(sw1, sw2);
        roleChanger.verifyRoleReplyReceived(switches, 123456);
        verify(sw1, sw2);
        
        assertEquals(2, switches.size());
    }
    
    @Test
    public void testRoleChangeTask() {
        @SuppressWarnings("unchecked")
        Collection<OFSwitchImpl> switches = 
                EasyMock.createMock(Collection.class);
        long now = System.nanoTime();
        long dt1 = 10 * 1000*1000*1000L;
        long dt2 = 20 * 1000*1000*1000L;
        long dt3 = 15 * 1000*1000*1000L;
        RoleChangeTask t1 = new RoleChangeTask(switches, null, now+dt1);
        RoleChangeTask t2 = new RoleChangeTask(switches, null, now+dt2);
        RoleChangeTask t3 = new RoleChangeTask(switches, null, now+dt3);
        
        // FIXME: cannot test comparison against self. grrr
        //assertTrue( t1.compareTo(t1) <= 0 );
        assertTrue( t1.compareTo(t2) < 0 );
        assertTrue( t1.compareTo(t3) < 0 );
        
        assertTrue( t2.compareTo(t1) > 0 );
        //assertTrue( t2.compareTo(t2) <= 0 );
        assertTrue( t2.compareTo(t3) > 0 );
    }
    
    @Test
    public void testSubmitRequest() throws Exception {
        LinkedList<OFSwitchImpl> switches = new LinkedList<OFSwitchImpl>();
        roleChanger.timeout = 500*1000*1000; // 500 ms
        
        // a switch that supports role requests
        OFSwitchImpl sw1 = EasyMock.createStrictMock(OFSwitchImpl.class);
        // No support for NX_ROLE
        expect(sw1.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
                        .andReturn(true); 
        expect(sw1.sendNxRoleRequest(EasyMock.same(Role.MASTER), EasyMock.anyLong()))
                       .andReturn(1);
        expect(sw1.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
                        .andReturn(true); 
        expect(sw1.sendNxRoleRequest(EasyMock.same(Role.SLAVE), EasyMock.anyLong()))
                       .andReturn(1);
        // The following calls happen for timeout handling:
        expect(sw1.checkFirstPendingRoleRequestCookie(EasyMock.anyLong()))
                        .andReturn(false);
        expect(sw1.checkFirstPendingRoleRequestCookie(EasyMock.anyLong()))
                        .andReturn(false);
        switches.add(sw1);
        
        
        replay(sw1);
        roleChanger.submitRequest(switches, Role.MASTER);
        roleChanger.submitRequest(switches, Role.SLAVE);
        // Wait until role request has been sent. 
        // TODO: need to get rid of this sleep somehow
        Thread.sleep(100);
        // Now there should be exactly one timeout task pending
        assertEquals(2, roleChanger.pendingTasks.size());
        // Make sure it's indeed a timeout task
        assertSame(RoleChanger.RoleChangeTask.Type.TIMEOUT, 
                     roleChanger.pendingTasks.peek().type);
        // Check that RoleChanger indeed made a copy of switches collection
        assertNotSame(switches, roleChanger.pendingTasks.peek().switches);
        
        // Wait until the timeout triggers 
        // TODO: get rid of this sleep too.
        Thread.sleep(500);
        assertEquals(0, roleChanger.pendingTasks.size());
        verify(sw1);
        
    }
    
}
