package net.onrc.onos.core.flowprogrammer;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import net.floodlightcontroller.core.IOFSwitch;
import net.onrc.onos.core.flowprogrammer.IFlowPusherService.MsgPriority;
import net.onrc.onos.core.flowprogrammer.IFlowSyncService.SyncResult;
import net.onrc.onos.core.util.FlowEntry;

import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFStatisticsRequest;
import org.openflow.protocol.OFType;
import org.openflow.protocol.statistics.OFFlowStatisticsReply;
import org.openflow.protocol.statistics.OFStatistics;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

// Test should be fixed to fit RAMCloud basis
@Ignore
@RunWith(PowerMockRunner.class)
@PrepareForTest({FlowSynchronizer.class})
public class FlowSynchronizerTest {
    private FlowPusher pusher;
    private FlowSynchronizer sync;
    private List<Long> idAdded;
    private List<Long> idRemoved;

    @Before
    public void setUp() throws Exception {
        idAdded = new ArrayList<Long>();
        idRemoved = new ArrayList<Long>();

        pusher = EasyMock.createMock(FlowPusher.class);
        EasyMock.expect(pusher.suspend(EasyMock.anyObject(IOFSwitch.class))).andReturn(true).anyTimes();
        EasyMock.expect(pusher.resume(EasyMock.anyObject(IOFSwitch.class))).andReturn(true).anyTimes();
        pusher.add(EasyMock.anyObject(IOFSwitch.class), EasyMock.anyObject(OFMessage.class),
                EasyMock.eq(MsgPriority.HIGH));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
            @Override
            public Object answer() throws Throwable {
                OFMessage msg = (OFMessage) EasyMock.getCurrentArguments()[1];
                if (msg.getType().equals(OFType.FLOW_MOD)) {
                    OFFlowMod fm = (OFFlowMod) msg;
                    if (fm.getCommand() == OFFlowMod.OFPFC_DELETE_STRICT) {
                        idRemoved.add(fm.getCookie());
                    }
                }
                return null;
            }
        }).anyTimes();
        pusher.pushFlowEntry(EasyMock.anyObject(IOFSwitch.class), EasyMock.anyObject(FlowEntry.class),
                EasyMock.eq(MsgPriority.HIGH));
        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
            @Override
            public Object answer() throws Throwable {
                FlowEntry flow = (FlowEntry) EasyMock.getCurrentArguments()[1];
                idAdded.add(flow.flowEntryId().value());
                return null;
            }
        }).anyTimes();
        EasyMock.replay(pusher);
    }

    @After
    public void tearDown() throws Exception {
    }

    /**
     * Test that synchronization doesn't affect anything in case either DB and
     * flow table has the same entries.
     */
    @Test
    public void testStable() {
        // Create mock of flow table : flow 1
        IOFSwitch sw = createMockSwitch(new long[]{1});

        // Create mock of flow entries : flow 1
        initMockGraph(new long[]{1});

        // synchronize
        doSynchronization(sw);

        // check if flow is not changed
        assertEquals(0, idAdded.size());
        assertEquals(0, idRemoved.size());
    }

    /**
     * Test that an flow is added in case DB has an extra FlowEntry.
     */
    @Test
    public void testSingleAdd() {
        // Create mock of flow table : null
        IOFSwitch sw = createMockSwitch(new long[]{});

        // Create mock of flow entries : flow 1
        initMockGraph(new long[]{1});

        // synchronize
        doSynchronization(sw);

        // check if single flow is installed
        assertEquals(1, idAdded.size());
        assertTrue(idAdded.contains((long) 1));
        assertEquals(0, idRemoved.size());
    }

    /**
     * Test that an flow is deleted in case switch has an extra FlowEntry.
     */
    @Test
    public void testSingleDelete() {
        // Create mock of flow table : flow 1
        IOFSwitch sw = createMockSwitch(new long[]{1});

        // Create mock of flow entries : null
        initMockGraph(new long[]{});

        // synchronize
        doSynchronization(sw);

        // check if single flow is deleted
        assertEquals(0, idAdded.size());
        assertEquals(1, idRemoved.size());
        assertTrue(idRemoved.contains((long) 1));
    }

    /**
     * Test that appropriate flows are added and other appropriate flows are deleted
     * in case flows in DB are overlapping flows in switch.
     */
    @Test
    public void testMixed() {
        // Create mock of flow table : flow 1,2,3
        IOFSwitch sw = createMockSwitch(new long[]{1, 2, 3});

        // Create mock of flow entries : flow 2,3,4,5
        initMockGraph(new long[]{2, 3, 4, 5});

        // synchronize
        doSynchronization(sw);

        // check if two flows {4,5} is installed and one flow {1} is deleted
        assertEquals(2, idAdded.size());
        assertTrue(idAdded.contains((long) 4));
        assertTrue(idAdded.contains((long) 5));
        assertEquals(1, idRemoved.size());
        assertTrue(idRemoved.contains((long) 1));
    }


    @Test
    public void testMassive() {
        // Create mock of flow table : flow 0-1999
        long[] swIdList = new long[2000];
        for (long i = 0; i < 2000; ++i) {
            swIdList[(int) i] = i;
        }
        IOFSwitch sw = createMockSwitch(swIdList);

        // Create mock of flow entries : flow 1500-3499
        long[] dbIdList = new long[2000];
        for (long i = 0; i < 2000; ++i) {
            dbIdList[(int) i] = 1500 + i;
        }
        initMockGraph(dbIdList);

        // synchronize
        doSynchronization(sw);

        // check if 1500 flows {2000-3499} is installed and 1500 flows {0,...,1499} is deleted
        assertEquals(1500, idAdded.size());
        for (long i = 2000; i < 3500; ++i) {
            assertTrue(idAdded.contains(i));
        }
        assertEquals(1500, idRemoved.size());
        for (long i = 0; i < 1500; ++i) {
            assertTrue(idRemoved.contains(i));
        }
    }

    /**
     * Create mock IOFSwitch with flow table which has arbitrary flows.
     *
     * @param cookieList List of FlowEntry IDs switch has.
     * @return Mock object.
     */
    private IOFSwitch createMockSwitch(long[] cookieList) {
        IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
        EasyMock.expect(sw.getId()).andReturn((long) 1).anyTimes();

        List<OFStatistics> stats = new ArrayList<OFStatistics>();
        for (long cookie : cookieList) {
            stats.add(createReply(cookie));
        }

        @SuppressWarnings("unchecked")
        Future<List<OFStatistics>> future = EasyMock.createMock(Future.class);
        try {
            EasyMock.expect(future.get()).andReturn(stats).once();
        } catch (InterruptedException e1) {
            fail("Failed in Future#get()");
        } catch (ExecutionException e1) {
            fail("Failed in Future#get()");
        }
        EasyMock.replay(future);

        try {
            EasyMock.expect(sw.getStatistics(EasyMock.anyObject(OFStatisticsRequest.class)))
                    .andReturn(future).once();
        } catch (IOException e) {
            fail("Failed in IOFSwitch#getStatistics()");
        }

        EasyMock.replay(sw);
        return sw;
    }

    /**
     * Create single OFFlowStatisticsReply object which is actually obtained from switch.
     *
     * @param cookie Cookie value, which indicates ID of FlowEntry installed to switch.
     * @return Created object.
     */
    private OFFlowStatisticsReply createReply(long cookie) {
        OFFlowStatisticsReply stat = new OFFlowStatisticsReply();
        OFMatch match = new OFMatch();

        stat.setCookie(cookie);
        stat.setMatch(match);
        stat.setPriority((short) 1);

        return stat;
    }

    /**
     * Create mock FlowDatabaseOperation to mock DB.
     *
     * @param idList List of FlowEntry IDs stored in DB.
     */
    private void initMockGraph(long[] idList) {
        /*
             * TODO: The old FlowDatabaseOperation class is gone, so the method
             * below needs to be rewritten.
             */
            /*
                List<IFlowEntry> flowEntryList = new ArrayList<IFlowEntry>();
                
                for (long id : idList) {
                        IFlowEntry entry = EasyMock.createMock(IFlowEntry.class);
                        EasyMock.expect(entry.getFlowEntryId()).andReturn(String.valueOf(id)).anyTimes();
                        EasyMock.replay(entry);
                        flowEntryList.add(entry);
                }
                
                ISwitchObject swObj = EasyMock.createMock(ISwitchObject.class);
                EasyMock.expect(swObj.getFlowEntries()).andReturn(flowEntryList).once();
                EasyMock.replay(swObj);
                
                DBOperation mockOp = PowerMock.createMock(DBOperation.class);
                EasyMock.expect(mockOp.searchSwitch(EasyMock.anyObject(String.class))).andReturn(swObj).once();
                
                PowerMock.mockStatic(FlowDatabaseOperation.class);
                for (IFlowEntry entry : flowEntryList) {
                        EasyMock.expect(FlowDatabaseOperation.extractFlowEntry(EasyMock.eq(entry)))
                                .andAnswer(new IAnswer<FlowEntry>() {
                                        @Override
                                        public FlowEntry answer() throws Throwable {
                                                IFlowEntry iflow = (IFlowEntry)EasyMock.getCurrentArguments()[0];
                                                long flowEntryId = Long.valueOf(iflow.getFlowEntryId());
                                                
                                                FlowEntry flow = EasyMock.createMock(FlowEntry.class);
                                                EasyMock.expect(flow.flowEntryId()).andReturn(new FlowEntryId(flowEntryId)).anyTimes();
                                                EasyMock.replay(flow);
                                                return flow;
                                        }
                                        
                                }).anyTimes();
                        EasyMock.expect(mockOp.searchFlowEntry(EasyMock.eq(new FlowEntryId(entry.getFlowEntryId()))))
                                .andReturn(entry);
                }
                PowerMock.replay(FlowDatabaseOperation.class);
                EasyMock.replay(mockOp);
                
                try {
                        PowerMock.expectNew(DBOperation.class).andReturn(mockOp);
                } catch (Exception e) {
                        fail("Failed to create DBOperation");
                }
                PowerMock.replay(DBOperation.class);
            */
    }

    /**
     * Instantiate FlowSynchronizer and sync flows.
     *
     * @param sw Target IOFSwitch object
     */
    private void doSynchronization(IOFSwitch sw) {
        sync = new FlowSynchronizer();
        sync.init(pusher);
        Future<SyncResult> future = sync.synchronize(sw);
        try {
            future.get();
        } catch (Exception e) {
            fail("Failed to Future#get()");
        }
    }
}
