package net.onrc.onos.core.intent.runtime;

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.replay;
import static org.easymock.EasyMock.verify;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.restserver.IRestApiService;
import net.onrc.onos.core.datagrid.IDatagridService;
import net.onrc.onos.core.datagrid.IEventChannel;
import net.onrc.onos.core.datagrid.IEventChannelListener;
import net.onrc.onos.core.intent.IntentOperationList;
import net.onrc.onos.core.intent.runtime.web.IntentWebRoutable;
import net.onrc.onos.core.registry.IControllerRegistryService;
import net.onrc.onos.core.topology.ITopologyListener;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.MockTopology;

import org.powermock.api.easymock.PowerMock;

/**
 * This class contains all of the mocked code required to run a test that uses
 * the Intent framework.  The normal lifecycle of an object of this class is to
 * create the object and call setUpIntentMocks() in the @Before (setUp()) part of
 * the test, then call tearDownIntentMocks() in the @After (tearDown()) part
 * of the test.  The intention of this class is to hide the mocking mechanics
 * and the unchecked suppressions in one place, and to make the Intent testing
 * reusable.
 *
 * This code is largely refactored from
 * net.onrc.onos.core.intent.runtime.UseCaseTest
 */
public class IntentTestMocks {

    private FloodlightModuleContext moduleContext;
    private IDatagridService datagridService;
    private ITopologyService topologyService;
    private IControllerRegistryService controllerRegistryService;
    private PersistIntent persistIntent;
    private IRestApiService restApi;
    private MockTopology topology;

    /**
     * Default constructor.  Doesn't do anything interesting.
     */
    public IntentTestMocks() { }

    /**
     * Create whatever mocks are required to access the Intents framework.
     * This method is intended to be called during @Before processing (setUp())
     * of the JUnit test.
     */
    @SuppressWarnings("unchecked")
    public void setUpIntentMocks() {
        try {
            topology = new MockTopology();
            topology.createSampleTopology1();

            datagridService = createMock(IDatagridService.class);
            topologyService = createMock(ITopologyService.class);
            controllerRegistryService = createMock(IControllerRegistryService.class);
            moduleContext = createMock(FloodlightModuleContext.class);
            final IEventChannel<Long, IntentOperationList> intentOperationChannel =
                    createMock(IEventChannel.class);
            final IEventChannel<Long, IntentStateList> intentStateChannel =
                    createMock(IEventChannel.class);
            persistIntent = PowerMock.createMock(PersistIntent.class);
            restApi = createMock(IRestApiService.class);

            PowerMock.expectNew(PersistIntent.class,
                    anyObject(IControllerRegistryService.class)).andReturn(persistIntent);

            expect(moduleContext.getServiceImpl(IDatagridService.class))
                    .andReturn(datagridService).once();
            expect(moduleContext.getServiceImpl(ITopologyService.class))
                    .andReturn(topologyService).once();
            expect(moduleContext.getServiceImpl(IControllerRegistryService.class))
                    .andReturn(controllerRegistryService).once();
            expect(persistIntent.getKey()).andReturn(1L).anyTimes();
            expect(persistIntent.persistIfLeader(eq(1L),
                    anyObject(IntentOperationList.class))).andReturn(true)
                    .anyTimes();
            expect(moduleContext.getServiceImpl(IRestApiService.class))
                    .andReturn(restApi).once();

            expect(topologyService.getTopology()).andReturn(topology)
                    .anyTimes();
            topologyService.registerTopologyListener(
                    anyObject(ITopologyListener.class));
            expectLastCall();

            expect(datagridService.createChannel("onos.pathintent",
                    Long.class, IntentOperationList.class))
                    .andReturn(intentOperationChannel).once();

            expect(datagridService.addListener(
                    eq("onos.pathintent_state"),
                    anyObject(IEventChannelListener.class),
                    eq(Long.class),
                    eq(IntentStateList.class)))
                    .andReturn(intentStateChannel).once();
            restApi.addRestletRoutable(anyObject(IntentWebRoutable.class));

            replay(datagridService);
            replay(topologyService);
            replay(moduleContext);
            replay(controllerRegistryService);
            PowerMock.replay(persistIntent, PersistIntent.class);
            replay(restApi);
        } catch (Exception ex) {
            // Convert the checked exception into an unchecked exception to
            // abort the test that called.
            throw new IllegalStateException(ex);
        }
    }

    /**
     * Remove whatever mocks were put in place.  This method is intended to be
     * called as part of @After processing (tearDown()) of the JUnit test.
     */
    public void tearDownIntentMocks() {
        verify(datagridService);
        verify(topologyService);
        verify(moduleContext);
        verify(controllerRegistryService);
        PowerMock.verify(persistIntent, PersistIntent.class);
        verify(restApi);
    }

    /**
     * Fetch the Floodlight module context being used by the mock.  Some tests
     * will need to add items to the Context to allow communications with
     * downstream classes.
     *
     * @return the FloodlightModuleCOntext used by the mock.
     */
    public FloodlightModuleContext getModuleContext() {
        return moduleContext;
    }

    /**
     * Fetch the mocked topology.
     *
     * @return mocked topology
     */
    public MockTopology getTopology() {
        return topology;
    }

    /**
     * Fetch the mocked topology service.
     *
     * @return mocked topology service
     */
    public ITopologyService getTopologyService() {
        return topologyService;
    }
}
