package net.onrc.onos.core.flowprogrammer;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.getCurrentArguments;
import static org.easymock.EasyMock.replay;
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.Collections;
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.intent.FlowEntry;
import net.onrc.onos.core.util.Dpid;

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.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowModCommand;
import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.U64;

// 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;

    /*
     * OF1.0 Factory for now. Change when we move to
     * OF 1.3.
     */
    private static OFFactory factory10;

    @Before
    public void setUp() throws Exception {
        factory10 = OFFactories.getFactory(OFVersion.OF_10);
        idAdded = new ArrayList<Long>();
        idRemoved = new ArrayList<Long>();

        pusher = createMock(FlowPusher.class);
        expect(pusher.suspend(anyObject(Dpid.class))).andReturn(true).anyTimes();
        expect(pusher.resume(anyObject(Dpid.class))).andReturn(true).anyTimes();
        pusher.add(anyObject(Dpid.class), anyObject(OFMessage.class),
                eq(MsgPriority.HIGH));
        expectLastCall().andAnswer(new IAnswer<Object>() {
            @Override
            public Object answer() throws Throwable {
                OFMessage msg = (OFMessage) getCurrentArguments()[1];
                if (msg.getType().equals(OFType.FLOW_MOD)) {
                    OFFlowMod fm = (OFFlowMod) msg;
                    if (fm.getCommand() == OFFlowModCommand.DELETE_STRICT) {
                        idRemoved.add(fm.getCookie().getValue());
                    }
                }
                return null;
            }
        }).anyTimes();
        pusher.pushFlowEntry(anyObject(Dpid.class), anyObject(FlowEntry.class),
                eq(MsgPriority.HIGH));
        expectLastCall().andAnswer(new IAnswer<Object>() {
            @Override
            public Object answer() throws Throwable {
                FlowEntry flow = (FlowEntry) getCurrentArguments()[1];
                idAdded.add(flow.getFlowEntryId());
                return null;
            }
        }).anyTimes();
        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 = createMock(IOFSwitch.class);
        expect(sw.getId()).andReturn((long) 1).anyTimes();

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

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

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

        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 OFFlowStatsReply createReply(long cookie) {
        OFFlowStatsEntry entry = factory10.buildFlowStatsEntry()
                .setCookie(U64.of(cookie))
                .setPriority(1)
                .setMatch(factory10.buildMatch().build())
                .build();
        OFFlowStatsReply stat = factory10.buildFlowStatsReply()
                .setEntries(Collections.singletonList(entry)).build();

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