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()");
        }
    }
}
