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 net.onrc.onos.core.util.OnosInstanceId;

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

/**
 * Unit test for {@link StandaloneRegistry}.
 */
public class StandaloneRegistryTest {

    private static final Logger log = LoggerFactory.getLogger(StandaloneRegistryTest.class);

    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.
     */
    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
            log.debug("Exception thrown as expected", e);
        }
    }

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

        // try before controller is registered
        OnosInstanceId onosInstanceId = registry.getOnosInstanceId();
        assertNull(onosInstanceId);

        // register
        registry.registerController(controllerIdToRegister);

        // call getOnosInstanceId and verify
        onosInstanceId = registry.getOnosInstanceId();
        assertNotNull(onosInstanceId);
        assertEquals(controllerIdToRegister, onosInstanceId.toString());
    }

    /**
     * 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 (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 numBlocks = 100;
        ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(numBlocks);

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

        for (int i = 0; i < numBlocks; ++i) {
            IdBlock block1 = blocks.get(i);
            for (int j = i + 1; j < numBlocks; ++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());
            }
        }
    }
}
