package net.onrc.onos.core.registry;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.openflow.util.HexString;

/**
 * Unit test for {@link StandaloneRegistry}.
 *
 * @author Naoki Shiota
 */
public class StandaloneRegistryTest {
    protected static final long TIMEOUT_MSEC = 1000;

    protected StandaloneRegistry registry;

    /**
     * Implementation of {@link ControlChangeCallback} which defines callback interfaces called by Registry.
     * This class remembers past callback parameters and provides methods to access them.
     * This class also provides CountDownLatch so one can wait until the callback be called
     * specific times (specified by constructor parameter). Particularly, the first time callback
     * called is supposed for registration, this class has an independent latch to wait for
     * the first callback.
     *
     * @author Naoki Shiota
     */
    public static class LoggingCallback implements ControlChangeCallback {
        private LinkedList<Long> dpidsCalledback = new LinkedList<Long>();
        private LinkedList<Boolean> controlsCalledback = new LinkedList<Boolean>();
        private CountDownLatch lock = null, registerLock = null;
        ;

        /**
         * Constructor with number of times callback to be called.
         *
         * @param numberToCall Number of times expected callback to be called
         */
        public LoggingCallback(int numberToCall) {
            lock = new CountDownLatch(numberToCall);
            registerLock = new CountDownLatch(1);
        }

        /**
         * Wait until registration is finished (callback is called for the first time).
         *
         * @throws InterruptedException
         */
        public void waitForRegistration() throws InterruptedException {
            registerLock.await();
        }

        /**
         * Wait for registration specifying timeout.
         *
         * @param msec Milliseconds to timeout
         * @throws InterruptedException
         */
        public void waitForRegistration(long msec) throws InterruptedException {
            registerLock.await(msec, TimeUnit.MILLISECONDS);
        }

        /**
         * Wait until callback is called specific times.
         *
         * @throws InterruptedException
         */
        public void waitUntilCalled() throws InterruptedException {
            lock.await();
        }

        /**
         * Wait until callback is called specific times, specifying timeout.
         *
         * @param msec Milliseconds to timeout
         * @throws InterruptedException
         */
        public void waitUntilCalled(long msec) throws InterruptedException {
            lock.await(msec, TimeUnit.MILLISECONDS);
        }

        /**
         * Get DPID parameter given by specific callback time.
         *
         * @param index Specify which time to get parameter
         * @return DPID value by number.
         */
        public Long getDpid(int index) {
            return dpidsCalledback.get(index);
        }

        /**
         * Get hasControl parameter given by specific callback time.
         *
         * @param index Specify which time to get parameter
         * @return hasControl value
         */
        public Boolean getControl(int index) {
            return controlsCalledback.get(index);
        }

        /**
         * Get DPID parameter given by latest call.
         *
         * @return DPID value by number
         */
        public Long getLatestDpid() {
            return dpidsCalledback.peekLast();
        }

        /**
         * Get hasControl parameter given by latest call
         *
         * @return hasControl value
         */
        public Boolean getLatestControl() {
            return controlsCalledback.peekLast();
        }

        @Override
        public void controlChanged(long dpid, boolean hasControl) {
            dpidsCalledback.addLast(dpid);
            controlsCalledback.addLast(hasControl);

            lock.countDown();
            registerLock.countDown();
        }
    }

    ;

    @Before
    public void setUp() throws Exception {
        FloodlightModuleContext fmc = new FloodlightModuleContext();
        registry = new StandaloneRegistry();
        registry.init(fmc);
    }

    @After
    public void tearDown() {
    }

    /**
     * Test if {@link StandaloneRegistry#registerController(String)} can run without error.
     */
    @Test
    public void testRegisterController() {
        String controllerIdToRegister = "test";
        try {
            registry.registerController(controllerIdToRegister);
        } catch (RegistryException e) {
            e.printStackTrace();
            fail(e.getMessage());
        }

        // Register Controller ID doubly
        try {
            registry.registerController(controllerIdToRegister);
            fail("Double registration goes through without exception");
        } catch (RegistryException e) {
            // expected behavior
        }
    }

    /**
     * Test if {@link StandaloneRegistry#getControllerId()} can return correct ID.
     *
     * @throws RegistryException
     */
    @Test
    public void testGetControllerId() throws RegistryException {
        String controllerIdToRegister = "test";

        // try before controller is registered
        String controllerId = registry.getControllerId();
        assertNull(controllerId);

        // register
        registry.registerController(controllerIdToRegister);

        // call getControllerId and verify
        controllerId = registry.getControllerId();
        assertNotNull(controllerId);
        assertEquals(controllerIdToRegister, controllerId);
    }

    /**
     * Test if {@link StandaloneRegistry#getAllControllers()} can return correct list of controllers.
     *
     * @throws RegistryException
     */
    @Test
    public void testGetAllControllers() throws RegistryException {
        String controllerIdToRegister = "test";

        // Test before register controller
        try {
            Collection<String> ctrls = registry.getAllControllers();
            assertFalse(ctrls.contains(controllerIdToRegister));
        } catch (RegistryException e) {
            e.printStackTrace();
            fail(e.getMessage());
        }

        // register
        registry.registerController(controllerIdToRegister);

        // Test after register controller
        try {
            Collection<String> ctrls = registry.getAllControllers();
            assertTrue(ctrls.contains(controllerIdToRegister));
        } catch (RegistryException e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    }

    /**
     * Test if {@link StandaloneRegistry#requestControl(long, ControlChangeCallback)} can correctly take control for switch so that callback is called.
     *
     * @throws RegistryException
     * @throws InterruptedException
     */
    @Test
    public void testRequestControl() throws InterruptedException, RegistryException {
        String controllerId = "test";
        registry.registerController(controllerId);

        LoggingCallback callback = new LoggingCallback(1);
        long dpidToRequest = 1000L;

        try {
            registry.requestControl(dpidToRequest, callback);
        } catch (RegistryException e) {
            e.printStackTrace();
            fail(e.getMessage());
        }

        callback.waitForRegistration();

        long dpidCallback = callback.getLatestDpid();
        boolean controlCallback = callback.getLatestControl();

        assertEquals(dpidToRequest, dpidCallback);
        assertTrue(controlCallback);
    }

    /**
     * Test if {@link StandaloneRegistry#releaseControl(long)} can correctly release the control so that callback is called.
     *
     * @throws InterruptedException
     * @throws RegistryException
     */
    @Test
    public void testReleaseControl() throws InterruptedException, RegistryException {
        String controllerId = "test";
        registry.registerController(controllerId);

        long dpidToRequest = 1000L;
        LoggingCallback callback = new LoggingCallback(2);

        // to request and wait to take control
        registry.requestControl(dpidToRequest, callback);
        callback.waitForRegistration();

        registry.releaseControl(dpidToRequest);

        // verify
        callback.waitUntilCalled();
        assertEquals(dpidToRequest, (long) callback.getLatestDpid());
        assertFalse(callback.getLatestControl());
    }

    /**
     * Test if {@link StandaloneRegistry#hasControl(long)} returns correct status.
     *
     * @throws InterruptedException
     * @throws RegistryException
     */
    @Test
    public void testHasControl() throws InterruptedException, RegistryException {
        String controllerId = "test";
        registry.registerController(controllerId);

        long dpidToRequest = 1000L;
        LoggingCallback callback = new LoggingCallback(2);

        // Test before request control
        assertFalse(registry.hasControl(dpidToRequest));

        registry.requestControl(dpidToRequest, callback);
        callback.waitForRegistration();

        // Test after take control
        assertTrue(registry.hasControl(dpidToRequest));

        registry.releaseControl(dpidToRequest);

        callback.waitUntilCalled();

        // Test after release control
        assertFalse(registry.hasControl(dpidToRequest));
    }

    /**
     * Test if {@link StandaloneRegistry#getControllerForSwitch(long)} returns correct controller ID.
     *
     * @throws InterruptedException
     * @throws RegistryException
     */
    @Test
    public void testGetControllerForSwitch() throws InterruptedException, RegistryException {
        String controllerId = "test";
        registry.registerController(controllerId);

        long dpidToRequest = 1000L;
        LoggingCallback callback = new LoggingCallback(2);

        // Test before request control
        try {
            String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
            assertNotEquals(controllerId, controllerForSw);
        } catch (RegistryException e) {
            fail("Failed before request control : " + e.getMessage());
            e.printStackTrace();
        }

        registry.requestControl(dpidToRequest, callback);
        callback.waitForRegistration();

        // Test after take control
        try {
            String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
            assertEquals(controllerId, controllerForSw);
        } catch (RegistryException e) {
            fail("Failed after take control : " + e.getMessage());
            e.printStackTrace();
        }

        registry.releaseControl(dpidToRequest);
        callback.waitUntilCalled();

        // Test after release control
        try {
            String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
            assertNotEquals(controllerId, controllerForSw);
        } catch (RegistryException e) {
            fail("Failed after release control : " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * Test if {@link StandaloneRegistry#getAllSwitches()} returns correct list of switches.
     *
     * @throws InterruptedException
     * @throws RegistryException
     */
    @Test
    public void testGetAllSwitches() throws InterruptedException, RegistryException {
        String controllerId = "test";
        registry.registerController(controllerId);

        long dpidToRequest = 1000L;
        String dpidToRequestStr = HexString.toHexString(dpidToRequest);
        LoggingCallback callback = new LoggingCallback(2);

        // Test before request control
        Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
        assertNotNull(switches);
        assertFalse(switches.keySet().contains(dpidToRequestStr));

        registry.requestControl(dpidToRequest, callback);
        callback.waitForRegistration();

        // Test after take control
        switches = registry.getAllSwitches();
        assertNotNull(switches);
        assertTrue(switches.keySet().contains(dpidToRequestStr));
        int count = 0;
        for (ControllerRegistryEntry ctrl : switches.get(dpidToRequestStr)) {
            if (ctrl.getControllerId().equals(controllerId)) {
                ++count;
            }
        }
        assertEquals(1, count);

        registry.releaseControl(dpidToRequest);
        callback.waitUntilCalled();

        // Test after release control
        switches = registry.getAllSwitches();
        assertNotNull(switches);
        assertFalse(switches.keySet().contains(dpidToRequestStr));
    }

    /**
     * Test if {@link StandaloneRegistry#getSwitchesControlledByController(String)} returns correct list of switches.
     *
     * @throws InterruptedException
     * @throws RegistryException
     */
    // TODO: remove @Ignore after implement StandaloneRegistry#getSwitchesControlledByController
    @Ignore
    @Test
    public void testGetSwitchesControlledByController() throws InterruptedException, RegistryException {
        String controllerId = "test";
        registry.registerController(controllerId);

        long dpidToRequest = 1000L;
        String dpidToRequestStr = HexString.toHexString(dpidToRequest);
        LoggingCallback callback = new LoggingCallback(2);

        // Test before request control
        Collection<Long> switches = registry.getSwitchesControlledByController(controllerId);
        assertNotNull(switches);
        assertFalse(switches.contains(dpidToRequestStr));

        registry.requestControl(dpidToRequest, callback);
        callback.waitForRegistration();

        // Test after take control
        switches = registry.getSwitchesControlledByController(controllerId);
        assertNotNull(switches);
        assertTrue(switches.contains(dpidToRequestStr));
        int count = 0;
        for (Long dpid : switches) {
            if ((long) dpid == dpidToRequest) {
                ++count;
            }
        }
        assertEquals(1, count);

        registry.releaseControl(dpidToRequest);
        callback.waitUntilCalled();

        // Test after release control
        switches = registry.getSwitchesControlledByController(controllerId);
        assertNotNull(switches);
        assertFalse(switches.contains(dpidToRequestStr));
    }

    /**
     * Test if {@link StandaloneRegistry#allocateUniqueIdBlock()} returns appropriate object.
     * Get bulk of IdBlocks and check if they do have unique range of IDs.
     */
    @Test
    public void testAllocateUniqueIdBlock() {
        // Number of blocks to be verified that any of them has unique block
        final int NUM_BLOCKS = 100;
        ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);

        for (int i = 0; i < NUM_BLOCKS; ++i) {
            blocks.add(registry.allocateUniqueIdBlock());
        }

        for (int i = 0; i < NUM_BLOCKS; ++i) {
            IdBlock block1 = blocks.get(i);
            for (int j = i + 1; j < NUM_BLOCKS; ++j) {
                IdBlock block2 = blocks.get(j);
                IdBlock lower, higher;

                if (block1.getStart() < block2.getStart()) {
                    lower = block1;
                    higher = block2;
                } else {
                    lower = block2;
                    higher = block1;
                }

                assertTrue(lower.getSize() > 0L);
                assertTrue(higher.getSize() > 0L);
                assertTrue(lower.getEnd() < higher.getStart());
            }
        }
    }
}
