package org.onlab.onos.sdnip;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.easymock.IAnswer;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.onlab.junit.IntegrationTest;
import org.onlab.junit.TestUtils;
import org.onlab.junit.TestUtils.TestUtilsException;
import org.onlab.onos.core.ApplicationId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.host.InterfaceIpAddress;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
import org.onlab.onos.sdnip.config.BgpPeer;
import org.onlab.onos.sdnip.config.Interface;
import org.onlab.onos.sdnip.config.SdnIpConfigService;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;

import com.google.common.collect.Sets;

/**
 * Integration tests for the SDN-IP application.
 * <p/>
 * The tests are very coarse-grained. They feed route updates in to
 * {@link Router} (simulating routes learnt from iBGP module inside SDN-IP
 * application), then they check that the correct intents are created and
 * submitted to the intent service. The entire route processing logic of
 * Router class is tested.
 */
@Category(IntegrationTest.class)
public class SdnIpTest {
    private static final int MAC_ADDRESS_LENGTH = 6;
    private static final int MIN_PREFIX_LENGTH = 1;
    private static final int MAX_PREFIX_LENGTH = 32;

    private IntentSynchronizer intentSynchronizer;
    static Router router;

    private SdnIpConfigService sdnIpConfigService;
    private InterfaceService interfaceService;
    private HostService hostService;
    private IntentService intentService;

    private Map<IpAddress, BgpPeer> bgpPeers;

    private Random random;

    static final ConnectPoint SW1_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000001"),
            PortNumber.portNumber(1));

    static final ConnectPoint SW2_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000002"),
            PortNumber.portNumber(1));

    static final ConnectPoint SW3_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000003"),
            PortNumber.portNumber(1));

    private static final ApplicationId APPID = new ApplicationId() {
        @Override
        public short id() {
            return 1;
        }

        @Override
        public String name() {
            return "SDNIP";
        }
    };

    @Before
    public void setUp() throws Exception {

        setUpInterfaceService();
        setUpSdnIpConfigService();

        hostService = new TestHostService();
        intentService = createMock(IntentService.class);
        random = new Random();

        intentSynchronizer = new IntentSynchronizer(APPID, intentService);
        router = new Router(APPID, intentSynchronizer, sdnIpConfigService,
                            interfaceService, hostService);
    }

    /**
     * Sets up InterfaceService and virtual {@link Interface}s.
     */
    private void setUpInterfaceService() {

        interfaceService = createMock(InterfaceService.class);

        Set<Interface> interfaces = Sets.newHashSet();

        Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
        interfaceIpAddresses1.add(new InterfaceIpAddress(
                IpAddress.valueOf("192.168.10.101"),
                IpPrefix.valueOf("192.168.10.0/24")));
        Interface sw1Eth1 = new Interface(SW1_ETH1,
                interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"));
        interfaces.add(sw1Eth1);

        Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
        interfaceIpAddresses2.add(new InterfaceIpAddress(
                IpAddress.valueOf("192.168.20.101"),
                IpPrefix.valueOf("192.168.20.0/24")));
        Interface sw2Eth1 = new Interface(SW2_ETH1,
                interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"));
        interfaces.add(sw2Eth1);

        Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
        interfaceIpAddresses3.add(new InterfaceIpAddress(
                IpAddress.valueOf("192.168.30.101"),
                IpPrefix.valueOf("192.168.30.0/24")));
        Interface sw3Eth1 = new Interface(SW3_ETH1,
                interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"));
        interfaces.add(sw3Eth1);

        expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
                sw1Eth1).anyTimes();
        expect(interfaceService.getInterface(SW2_ETH1)).andReturn(
                sw2Eth1).anyTimes();
        expect(interfaceService.getInterface(SW3_ETH1)).andReturn(
                sw3Eth1).anyTimes();

        expect(interfaceService.getInterfaces()).andReturn(
                interfaces).anyTimes();
        replay(interfaceService);
    }

    /**
     * Sets up SdnIpConfigService and BGP peers in external networks.
     */
    private void setUpSdnIpConfigService() {

        sdnIpConfigService = createMock(SdnIpConfigService.class);

        bgpPeers = new HashMap<>();

        String peerSw1Eth1 = "192.168.10.1";
        bgpPeers.put(IpAddress.valueOf(peerSw1Eth1),
                new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));

        String peer1Sw2Eth1 = "192.168.20.1";
        bgpPeers.put(IpAddress.valueOf(peer1Sw2Eth1),
                new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));

        String peer2Sw2Eth1 = "192.168.30.1";
        bgpPeers.put(IpAddress.valueOf(peer2Sw2Eth1),
                new BgpPeer("00:00:00:00:00:00:00:03", 1, peer2Sw2Eth1));

        expect(sdnIpConfigService.getBgpPeers()).andReturn(bgpPeers).anyTimes();
        replay(sdnIpConfigService);
    }

    /**
     * Tests adding a set of routes into {@link Router}.
     * <p/>
     * Random routes are generated and fed in to the route processing
     * logic (via processRouteAdd in Router class). We check that the correct
     * intents are generated and submitted to our mock intent service.
     *
     * @throws InterruptedException if interrupted while waiting on a latch
     * @throws TestUtilsException if exceptions when using TestUtils
     */
    @Test
    public void testAddRoutes() throws InterruptedException, TestUtilsException {
        int numRoutes = 100;

        final CountDownLatch latch = new CountDownLatch(numRoutes);

        List<RouteUpdate> routeUpdates = generateRouteUpdates(numRoutes);

        // Set up expectation
        reset(intentService);

        for (RouteUpdate update : routeUpdates) {
            Ip4Address nextHopAddress = update.routeEntry().nextHop();

            // Find out the egress ConnectPoint
            ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress);

            MultiPointToSinglePointIntent intent = getIntentForUpdate(update,
                    generateMacAddress(nextHopAddress),
                    egressConnectPoint);
            intentService.submit(intent);

            expectLastCall().andAnswer(new IAnswer<Object>() {
                @Override
                public Object answer() throws Throwable {
                    latch.countDown();
                    return null;
                }
            }).once();
        }

        replay(intentService);

        intentSynchronizer.leaderChanged(true);
        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);

        // Add route updates
        for (RouteUpdate update : routeUpdates) {
            router.processRouteAdd(update.routeEntry());
        }

        latch.await(5000, TimeUnit.MILLISECONDS);

        assertEquals(router.getRoutes().size(), numRoutes);
        assertEquals(intentSynchronizer.getRouteIntents().size(),
                     numRoutes);

        verify(intentService);
    }

    /**
     * Tests adding then deleting a set of routes from {@link Router}.
     * <p/>
     * Random routes are generated and fed in to the route processing
     * logic (via processRouteAdd in Router class), and we check that the
     * correct intents are generated. We then delete the entire set of routes
     * (by feeding updates to processRouteDelete), and check that the correct
     * intents are withdrawn from the intent service.
     *
     * @throws InterruptedException if interrupted while waiting on a latch
     * @throws TestUtilsException exceptions when using TestUtils
     */
    @Test
    public void testDeleteRoutes() throws InterruptedException, TestUtilsException {
        int numRoutes = 100;
        List<RouteUpdate> routeUpdates = generateRouteUpdates(numRoutes);

        final CountDownLatch installCount = new CountDownLatch(numRoutes);
        final CountDownLatch deleteCount = new CountDownLatch(numRoutes);

        // Set up expectation
        reset(intentService);

        for (RouteUpdate update : routeUpdates) {
            Ip4Address nextHopAddress = update.routeEntry().nextHop();

            // Find out the egress ConnectPoint
            ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress);
            MultiPointToSinglePointIntent intent = getIntentForUpdate(update,
                    generateMacAddress(nextHopAddress),
                    egressConnectPoint);
            intentService.submit(intent);
            expectLastCall().andAnswer(new IAnswer<Object>() {
                @Override
                public Object answer() throws Throwable {
                    installCount.countDown();
                    return null;
                }
            }).once();
            intentService.withdraw(intent);
            expectLastCall().andAnswer(new IAnswer<Object>() {
                @Override
                public Object answer() throws Throwable {
                    deleteCount.countDown();
                    return null;
                }
            }).once();
        }

        replay(intentService);

        intentSynchronizer.leaderChanged(true);
        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);

        // Send the add updates first
        for (RouteUpdate update : routeUpdates) {
            router.processRouteAdd(update.routeEntry());
        }

        // Give some time to let the intents be submitted
        installCount.await(5000, TimeUnit.MILLISECONDS);

        // Send the DELETE updates
        for (RouteUpdate update : routeUpdates) {
            router.processRouteDelete(update.routeEntry());
        }

        deleteCount.await(5000, TimeUnit.MILLISECONDS);

        assertEquals(0, router.getRoutes().size());
        assertEquals(0, intentSynchronizer.getRouteIntents().size());
        verify(intentService);
    }

    /**
     * This methods generates random route updates.
     *
     * @param numRoutes the number of route updates to generate
     * @return a list of route update
     */
    private List<RouteUpdate> generateRouteUpdates(int numRoutes) {
        List<RouteUpdate> routeUpdates = new ArrayList<>(numRoutes);

        Set<Ip4Prefix> prefixes = new HashSet<>();

        for (int i = 0; i < numRoutes; i++) {
            Ip4Prefix prefix;
            do {
                // Generate a random prefix length between MIN_PREFIX_LENGTH
                // and MAX_PREFIX_LENGTH
                int prefixLength = random.nextInt(
                        (MAX_PREFIX_LENGTH - MIN_PREFIX_LENGTH) + 1)
                        + MIN_PREFIX_LENGTH;
                prefix =
                    Ip4Prefix.valueOf(Ip4Address.valueOf(random.nextInt()),
                                      prefixLength);
                // We have to ensure we don't generate the same prefix twice
                // (this is quite easy to happen with small prefix lengths).
            } while (prefixes.contains(prefix));

            prefixes.add(prefix);

            // Randomly select a peer to use as the next hop
            BgpPeer nextHop = null;
            int peerNumber = random.nextInt(sdnIpConfigService.getBgpPeers()
                    .size());
            int j = 0;
            for (BgpPeer peer : sdnIpConfigService.getBgpPeers().values()) {
                if (j++ == peerNumber) {
                    nextHop = peer;
                    break;
                }
            }

            assertNotNull(nextHop);

            RouteUpdate update =
                new RouteUpdate(RouteUpdate.Type.UPDATE,
                        new RouteEntry(prefix,
                                       nextHop.ipAddress().getIp4Address()));

            routeUpdates.add(update);
        }

        return routeUpdates;
    }

    /**
     * Generates the MultiPointToSinglePointIntent that should be
     * submitted/withdrawn for a particular RouteUpdate.
     *
     * @param update the RouteUpdate to generate an intent for
     * @param nextHopMac a MAC address to use as the dst-mac for the intent
     * @param egressConnectPoint the outgoing ConnectPoint for the intent
     * @return the generated intent
     */
    private MultiPointToSinglePointIntent getIntentForUpdate(RouteUpdate update,
            MacAddress nextHopMac, ConnectPoint egressConnectPoint) {
        IpPrefix ip4Prefix = update.routeEntry().prefix();

        TrafficSelector.Builder selectorBuilder =
                DefaultTrafficSelector.builder();

        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ip4Prefix);

        TrafficTreatment.Builder treatmentBuilder =
                DefaultTrafficTreatment.builder();
        treatmentBuilder.setEthDst(nextHopMac);

        Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
        for (Interface intf : interfaceService.getInterfaces()) {
            if (!intf.connectPoint().equals(egressConnectPoint)) {
                ConnectPoint srcPort = intf.connectPoint();
                ingressPoints.add(srcPort);
            }
        }

        MultiPointToSinglePointIntent intent =
                new MultiPointToSinglePointIntent(APPID,
                selectorBuilder.build(), treatmentBuilder.build(),
                ingressPoints, egressConnectPoint);

        return intent;
    }

    /**
     * Generates a MAC address based on an IP address.
     * For the test we need MAC addresses but the actual values don't have any
     * meaning, so we'll just generate them based on the IP address. This means
     * we have a deterministic mapping from IP address to MAC address.
     *
     * @param ipAddress IP address used to generate a MAC address
     * @return generated MAC address
     */
    static MacAddress generateMacAddress(IpAddress ipAddress) {
        byte[] macAddress = new byte[MAC_ADDRESS_LENGTH];
        ByteBuffer bb = ByteBuffer.wrap(macAddress);

        // Put the IP address bytes into the lower four bytes of the MAC
        // address. Leave the first two bytes set to 0.
        bb.position(2);
        bb.put(ipAddress.toOctets());

        return MacAddress.valueOf(bb.array());
    }

    /**
     * Finds out the ConnectPoint for a BGP peer address.
     *
     * @param bgpPeerAddress the BGP peer address.
     */
    private ConnectPoint getConnectPoint(IpAddress bgpPeerAddress) {
        ConnectPoint connectPoint = null;

        for (BgpPeer bgpPeer: bgpPeers.values()) {
            if (bgpPeer.ipAddress().equals(bgpPeerAddress)) {
                connectPoint = bgpPeer.connectPoint();
                break;
            }
        }
        return connectPoint;
    }
}
