/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.vpls;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.TestApplicationId;
import org.onosproject.app.ApplicationService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceListener;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.intentsync.IntentSynchronizationService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.HostServiceAdapter;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentServiceAdapter;
import org.onosproject.net.intent.IntentUtils;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.vpls.config.VplsConfigService;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static org.easymock.EasyMock.anyObject;
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.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.onosproject.net.EncapsulationType.NONE;
import static org.onosproject.net.EncapsulationType.VLAN;
import static org.onosproject.net.EncapsulationType.valueOf;
import static org.onosproject.vpls.IntentInstaller.PARTIAL_FAILURE_CONSTRAINT;
import static org.onosproject.vpls.IntentInstaller.PREFIX_BROADCAST;
import static org.onosproject.vpls.IntentInstaller.PREFIX_UNICAST;
import static org.onosproject.vpls.IntentInstaller.setEncap;

/**
 * Tests for the {@link Vpls} class.
 */
public class VplsTest {
    private static final String APP_NAME = "org.onosproject.vpls";
    private static final ApplicationId APPID = TestApplicationId.create(APP_NAME);
    private static final String DASH = "-";
    private static final int PRIORITY_OFFSET = 1000;
    private static final String VPLS1 = "vpls1";
    private static final String VPLS2 = "vpls2";
    private static final String VPLS3 = "vpls3";
    private static final String VPLS4 = "vpls4";

    private static final PortNumber P1 = PortNumber.portNumber(1);
    private static final PortNumber P2 = PortNumber.portNumber(2);

    private static final DeviceId DID1 = getDeviceId(1);
    private static final DeviceId DID2 = getDeviceId(2);
    private static final DeviceId DID3 = getDeviceId(3);
    private static final DeviceId DID4 = getDeviceId(4);
    private static final DeviceId DID5 = getDeviceId(5);
    private static final DeviceId DID6 = getDeviceId(6);

    private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
    private static final ConnectPoint CP2 = new ConnectPoint(DID2, P1);
    private static final ConnectPoint CP3 = new ConnectPoint(DID3, P1);
    private static final ConnectPoint CP4 = new ConnectPoint(DID4, P1);
    private static final ConnectPoint CP5 = new ConnectPoint(DID5, P1);
    private static final ConnectPoint CP6 = new ConnectPoint(DID6, P1);
    private static final ConnectPoint CP7 = new ConnectPoint(DID4, P2);
    private static final ConnectPoint CP8 = new ConnectPoint(DID3, P2);
    private static final ConnectPoint CP9 = new ConnectPoint(DID5, P1);
    private static final ConnectPoint CP10 = new ConnectPoint(DID5, P2);

    private static final VlanId VLAN100 = VlanId.vlanId((short) 100);
    private static final VlanId VLAN200 = VlanId.vlanId((short) 200);
    private static final VlanId VLAN300 = VlanId.vlanId((short) 300);
    private static final VlanId VLAN400 = VlanId.vlanId((short) 400);
    private static final VlanId VLAN_NONE = VlanId.NONE;

    private static final MacAddress MAC1 = getMac(1);
    private static final MacAddress MAC2 = getMac(2);
    private static final MacAddress MAC3 = getMac(3);
    private static final MacAddress MAC4 = getMac(4);
    private static final MacAddress MAC5 = getMac(5);
    private static final MacAddress MAC6 = getMac(6);
    private static final MacAddress MAC7 = getMac(7);
    private static final MacAddress MAC8 = getMac(8);
    private static final MacAddress MAC9 = getMac(9);
    private static final MacAddress MAC10 = getMac(10);
    private static final MacAddress MAC11 = getMac(11);

    private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
    private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");

    private static final HostId HID1 = HostId.hostId(MAC1, VLAN100);
    private static final HostId HID2 = HostId.hostId(MAC2, VLAN100);
    private static final HostId HID3 = HostId.hostId(MAC3, VLAN200);
    private static final HostId HID4 = HostId.hostId(MAC4, VLAN200);
    private static final HostId HID5 = HostId.hostId(MAC5, VLAN300);
    private static final HostId HID6 = HostId.hostId(MAC6, VLAN300);
    private static final HostId HID7 = HostId.hostId(MAC7, VLAN300);
    private static final HostId HID8 = HostId.hostId(MAC8, VLAN400);
    private static final HostId HID9 = HostId.hostId(MAC9);
    private static final HostId HID10 = HostId.hostId(MAC10);
    private static final HostId HID11 = HostId.hostId(MAC11);

    private static final ProviderId PID = new ProviderId("of", "foo");

    private static IdGenerator idGenerator;

    private static final Interface V100H1 =
            new Interface("v100h1", CP1, null, null, VLAN100);
    private static final Interface V100H2 =
            new Interface("v100h2", CP2, null, null, VLAN100);
    private static final Interface V200H1 =
            new Interface("v200h1", CP3, null, null, VLAN200);
    private static final Interface V200H2 =
            new Interface("v200h2", CP4, null, null, VLAN200);
    private static final Interface V300H1 =
            new Interface("v300h1", CP5, null, null, VLAN300);
    private static final Interface V300H2 =
            new Interface("v300h2", CP6, null, null, VLAN300);
    private static final Interface V400H1 =
            new Interface("v400h1", CP7, null, null, VLAN400);

    private static final Interface VNONEH1 =
            new Interface("vNoneh1", CP8, null, null, VLAN_NONE);
    private static final Interface VNONEH2 =
            new Interface("vNoneh2", CP9, null, null, VLAN_NONE);
    private static final Interface VNONEH3 =
            new Interface("vNoneh3", CP10, null, null, VLAN_NONE);

    private static final Host V100HOST1 =
            new DefaultHost(PID, HID1, MAC1, VLAN100,
                            getLocation(1), Collections.singleton(IP1));
    private static final Host V100HOST2 =
            new DefaultHost(PID, HID2, MAC2, VLAN100,
                            getLocation(2), Sets.newHashSet());
    private static final Host V200HOST1 =
            new DefaultHost(PID, HID3, MAC3, VLAN200,
                            getLocation(3), Collections.singleton(IP2));
    private static final Host V200HOST2 =
            new DefaultHost(PID, HID4, MAC4, VLAN200,
                            getLocation(4), Sets.newHashSet());
    private static final Host V300HOST1 =
            new DefaultHost(PID, HID5, MAC5, VLAN300,
                            getLocation(5), Sets.newHashSet());
    private static final Host V300HOST2 =
            new DefaultHost(PID, HID6, MAC6, VLAN300,
                            getLocation(6), Sets.newHashSet());
    private static final Host V300HOST3 =
            new DefaultHost(PID, HID7, MAC7, VLAN300,
                            getLocation(7), Sets.newHashSet());
    private static final Host V400HOST1 =
            new DefaultHost(PID, HID8, MAC8, VLAN400,
                            getLocation(4, 2), Sets.newHashSet());

    private static final Host VNONEHOST1 =
            new DefaultHost(PID, HID9, MAC9, VlanId.NONE,
                            getLocation(3, 2), Sets.newHashSet());
    private static final Host VNONEHOST2 =
            new DefaultHost(PID, HID10, MAC10, VlanId.NONE,
                            getLocation(5, 1), Sets.newHashSet());
    private static final Host VNONEHOST3 =
            new DefaultHost(PID, HID11, MAC11, VlanId.NONE,
                            getLocation(5, 2), Sets.newHashSet());

    private static final Set<Interface> AVAILABLE_INTERFACES =
            ImmutableSet.of(V100H1, V100H2, V200H1, V200H2, V300H1, V300H2,
                            V400H1, VNONEH1, VNONEH2);

    private static final Set<Host> AVAILABLE_HOSTS =
            ImmutableSet.of(V100HOST1, V100HOST2, V200HOST1,
                            V200HOST2, V300HOST1, V300HOST2, V300HOST3,
                            VNONEHOST1, VNONEHOST2,
                            V400HOST1, VNONEHOST3);

    private SetMultimap<String, Interface> interfacesByVpls = HashMultimap.create();

    private ApplicationService applicationService;
    private CoreService coreService;
    private HostListener hostListener;
    private NetworkConfigService configService;
    private Set<Host> hostsAvailable;
    private HostService hostService;
    private IntentService intentService;
    private InterfaceService interfaceService;
    private VplsConfigService vplsConfigService;
    private Vpls vpls;

    @Before
    public void setUp() throws Exception {
        idGenerator = new TestIdGenerator();
        Intent.unbindIdGenerator(idGenerator);
        Intent.bindIdGenerator(idGenerator);

        applicationService = createMock(ApplicationService.class);

        configService = createMock(NetworkConfigService.class);

        coreService = createMock(CoreService.class);
        expect(coreService.registerApplication(APP_NAME))
                .andReturn(APPID);
        replay(coreService);

        hostsAvailable = Sets.newHashSet();
        hostService = new TestHostService(hostsAvailable);

        intentService = new TestIntentService();

        TestIntentSynchronizer intentSynchronizer =
                new TestIntentSynchronizer(intentService);

        interfaceService = createMock(InterfaceService.class);
        interfaceService.addListener(anyObject(InterfaceListener.class));
        expectLastCall().anyTimes();
        addIfaceConfig();

        interfacesByVpls.put(VPLS1, V100H1);
        interfacesByVpls.put(VPLS1, V200H1);
        interfacesByVpls.put(VPLS1, V300H1);
        interfacesByVpls.put(VPLS2, V100H2);
        interfacesByVpls.put(VPLS2, V200H2);
        interfacesByVpls.put(VPLS2, V300H2);
        interfacesByVpls.put(VPLS3, VNONEH1);
        interfacesByVpls.put(VPLS3, VNONEH2);
        interfacesByVpls.put(VPLS4, V400H1);
        interfacesByVpls.put(VPLS4, VNONEH3);

        Map<String, EncapsulationType> encapByVpls = new HashMap<>();
        encapByVpls.put(VPLS1, VLAN);
        encapByVpls.put(VPLS2, NONE);
        encapByVpls.put(VPLS3, NONE);
        encapByVpls.put(VPLS4, NONE);

        vplsConfigService = new TestVplsConfigService(interfacesByVpls, encapByVpls);

        vpls = new Vpls();
        vpls.applicationService = applicationService;
        vpls.coreService = coreService;
        vpls.hostService = hostService;
        vpls.vplsConfigService = vplsConfigService;
        vpls.intentService = intentService;
        vpls.interfaceService = interfaceService;
        vpls.configService = configService;
        vpls.intentSynchronizer = intentSynchronizer;

    }

    @After
    public void tearDown() {
        Intent.unbindIdGenerator(idGenerator);
    }

    /**
     * Creates the interface configuration:
     *  On devices 1 and 2 is configured an interface on port 1 with vlan 100.
     *  On device 3 is configured an interface on port 3 with no vlan.
     *  On devices 3 and 4 is configured an interface on port 1 with vlan 200.
     *  On device 4 is an interface configured on port 2 with vlan 400.
     *  On device 5 are configured two interfaces on port 1 and 2 with no vlan.
     *  On device 5 and 6 is configured an interface on port 1 with vlan 300.
     */
    private void addIfaceConfig() {
        Set<Interface> interfaces = ImmutableSet.copyOf(AVAILABLE_INTERFACES);
        Set<Interface> vlanOneSet = ImmutableSet.of(V100H1, V100H2);
        Set<Interface> vlanTwoSet = ImmutableSet.of(V200H1, V200H2);
        Set<Interface> vlanThreeSet = ImmutableSet.of(VNONEH1, VNONEH2);
        Set<Interface> vlanFourSet = ImmutableSet.of(V400H1, VNONEH3);

        AVAILABLE_INTERFACES.forEach(intf -> {
            expect(interfaceService.getInterfacesByPort(intf.connectPoint()))
                    .andReturn(Sets.newHashSet(intf)).anyTimes();
        });
        expect(interfaceService.getInterfacesByVlan(VLAN100))
                .andReturn(vlanOneSet).anyTimes();
        expect(interfaceService.getInterfacesByVlan(VLAN200))
                .andReturn(vlanTwoSet).anyTimes();
        expect(interfaceService.getInterfacesByVlan(VLAN300))
                .andReturn(vlanThreeSet).anyTimes();
        expect(interfaceService.getInterfacesByVlan(VLAN400))
                .andReturn(vlanFourSet).anyTimes();
        expect(interfaceService.getInterfacesByVlan(VlanId.NONE))
                .andReturn(vlanFourSet).anyTimes();
        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();

        replay(interfaceService);
    }

    /**
     * Seven ports are configured with VLANs, while three ports are not. No hosts are
     * registered by the HostService.
     *
     * The first three ports have an interface configured on VPLS 1,
     * the other three on VPLS 2. Two ports are defined for VPLS 3, while
     * the two remaining ports are configured on VPLS 4.
     *
     * The number of intents expected is 10: three for VPLS 1, three for VPLS 2,
     * two for VPLS 3, two for VPLS 4. Eight MP2SP intents.
     * Checks if the number of intents submitted to the intent framework is
     * equal to the number of intents expected and if all intents are equivalent.
     */
    @Test
    public void activateNoHosts() {
        vpls.activate();

        List<Intent> expectedIntents = Lists.newArrayList();
        Set<FilteredConnectPoint> fcPoints;

        fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1));
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN));

        fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2));
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE));

        fcPoints = buildFCPoints(ImmutableSet.of(VNONEH1, VNONEH2));
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS3, NONE));

        fcPoints = buildFCPoints(ImmutableSet.of(V400H1, VNONEH3));
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS4, NONE));

        checkIntents(expectedIntents);
    }

    /**
     * Ten ports are configured with VLANs and ten hosts are registered by the
     * HostService.
     *
     * The first three ports have an interface configured on VPLS 1,
     * the other three on VPLS 2, two on VPLS3 and two on VPLS4.
     *
     * The number of intents expected is twenty: six
     * for VPLS 1, six for VPLS 2. four for VPLS 3, four for VPLS 4.
     * That is ten sp2mp intents, ten mp2sp intents. For VPLS 1
     * IPs are added to demonstrate this doesn't influence the number of intents
     * created. Checks if the number of intents submitted to the intent
     * framework is equal to the number of intents expected and if all intents
     * are equivalent.
     */
    @Test
    public void tenInterfacesConfiguredHostsPresent() {
        hostsAvailable.addAll(AVAILABLE_HOSTS);

        vpls.activate();

        List<Intent> expectedIntents = Lists.newArrayList();
        Set<FilteredConnectPoint> fcPoints;
        Set<Host> hosts;

        fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1));
        hosts = ImmutableSet.of(V100HOST1, V200HOST1, V300HOST1);
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN));
        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS1, VLAN));

        fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2));
        hosts = ImmutableSet.of(V100HOST2, V200HOST2, V300HOST2);
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE));
        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS2, NONE));

        fcPoints = buildFCPoints(ImmutableSet.of(VNONEH1, VNONEH2));
        hosts = ImmutableSet.of(VNONEHOST1, VNONEHOST2);
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS3, NONE));
        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS3, NONE));

        fcPoints = buildFCPoints(ImmutableSet.of(V400H1, VNONEH3));
        hosts = ImmutableSet.of(V400HOST1, VNONEHOST3);
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS4, NONE));
        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS4, NONE));

        checkIntents(expectedIntents);
    }

    /**
     * Ten ports are configured; seven have VLANs and three do not.
     * Initially, no hosts are registered by the HostService.
     *
     * The first three ports have an interface configured on
     * VPLS 1, three have an interface configured on VPLS 2, two have an
     * interface configured on VPLS 3 and two have an interface configured
     * on VPLS 4, three have an interface configure. When the
     * module starts up, three hosts attached to device one, two and three -
     * port 1, are registered by the HostService and events are sent to the
     * application. sp2mp intents are created for all interfaces configured and
     * mp2sp intents are created only for the hosts attached.
     *
     * The number of intents expected is seventeen: six for VPLS 1,
     * three for VPLS 2, four for VPLS3 and four for VPLS4.
     * Ten sp2mp intents, seven mp2sp intents. IPs are added on the first two
     * hosts only to demonstrate this doesn't influence the number of intents
     * created.
     * An additional host is added on device seven - port 1, to demonstrate that
     * the application does not generate intents, even if the interface uses the
     * same VLAN Id of the other interfaces configured for the specifc VPLS.
     * Checks if the number of intents submitted to the intent framework is equal
     * to the number of intents expected and if all intents are equivalent.
     */
    @Test
    public void tenInterfacesThreeHostEventsSameVpls() {
        vpls.activate();

        List<Intent> expectedIntents = Lists.newArrayList();
        Set<FilteredConnectPoint> fcPoints;
        Set<Host> hosts;

        hostsAvailable.addAll(Sets.newHashSet(V100HOST1, V200HOST1,
                                              V300HOST1, V300HOST3,
                                              VNONEHOST1, VNONEHOST2,
                                              V400HOST1, VNONEHOST3));
        hostsAvailable.forEach(host ->
                                       hostListener.event(new HostEvent(HostEvent.Type.HOST_ADDED, host)));

        fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1));
        hosts = ImmutableSet.of(V100HOST1, V200HOST1, V300HOST1);
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN));
        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS1, VLAN));

        fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2));
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE));

        fcPoints = buildFCPoints(ImmutableSet.of(VNONEH1, VNONEH2));
        hosts = ImmutableSet.of(VNONEHOST1, VNONEHOST2);
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS3, NONE));
        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS3, NONE));

        fcPoints = buildFCPoints(ImmutableSet.of(V400H1, VNONEH3));
        hosts = ImmutableSet.of(V400HOST1, VNONEHOST3);
        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS4, NONE));
        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS4, NONE));

        checkIntents(expectedIntents);
    }

    /**
     * Generates a list of the expected sp2mp intents for a VPLS.
     *
     * @param fcPoints the filtered connect point
     * @param name the name of the VPLS
     * @param encap the encapsulation type
     * @return the list of expected sp2mp intents for the given VPLS
     */
    private List<SinglePointToMultiPointIntent>
    generateVplsBrc(Set<FilteredConnectPoint> fcPoints, String name, EncapsulationType encap) {
        List<SinglePointToMultiPointIntent> intents = Lists.newArrayList();

        fcPoints.forEach(point -> {
            Set<FilteredConnectPoint> otherPoints =
                    fcPoints.stream()
                            .filter(fcp -> !fcp.equals(point))
                            .collect(Collectors.toSet());

            Key brckey = buildKey(PREFIX_BROADCAST,
                                  point.connectPoint(),
                                  name,
                                  MacAddress.BROADCAST);

            intents.add(buildBrcIntent(brckey, point, otherPoints, encap));
        });

        return intents;
    }

    /**
     * Generates a list of expected mp2sp intents for a given VPLS.
     *
     * @param fcPoints the filtered connect point
     * @param hosts the hosts
     * @param name the name of the VPLS
     * @param encap the encapsulation type
     * @return the list of expected mp2sp intents for the given VPLS
     */
    private List<MultiPointToSinglePointIntent>
    generateVplsUni(Set<FilteredConnectPoint> fcPoints, Set<Host> hosts,
                    String name, EncapsulationType encap) {
        List<MultiPointToSinglePointIntent> intents = Lists.newArrayList();

        hosts.forEach(host -> {
            FilteredConnectPoint hostPoint = getHostPoint(host, fcPoints);

            Set<FilteredConnectPoint> otherPoints =
                    fcPoints.stream()
                            .filter(fcp -> !fcp.equals(hostPoint))
                            .collect(Collectors.toSet());

            Key uniKey = buildKey(PREFIX_UNICAST,
                                  host.location(), name, host.mac());

            intents.add(buildUniIntent(uniKey, otherPoints, hostPoint, host, encap));
        });

        return intents;
    }

    /**
     * Checks if the number of intents submitted to the intent framework is equal
     * to the number of intents expected and if all intents are equivalent.
     *
     * @param intents the list of intents expected
     */
    private void checkIntents(List<Intent> intents) {
        assertEquals("The number of intents submitted differs from the number" +
                             " of intents expected. ",
                     intents.size(), intentService.getIntentCount());

        for (Intent intentOne : intents) {
            boolean found = false;
            for (Intent intentTwo : intentService.getIntents()) {
                if (intentOne.key().equals(intentTwo.key())) {
                    found = true;
                    assertTrue(format("The intent submitted is different from" +
                                              " the intent expected. %s %s",
                                      intentOne, intentTwo),
                               IntentUtils.intentsAreEqual(intentOne, intentTwo));
                    break;
                }
            }
            assertTrue("The intent submitted is not equal to any of the expected" +
                               " intents. ", found);
        }
    }

    /**
     * Builds a broadcast intent.
     *
     * @param key the key to identify the intent
     * @param src the ingress connect point
     * @param dsts the egress connect points
     * @return the generated single-point to multi-point intent
     */
    private SinglePointToMultiPointIntent buildBrcIntent(Key key,
                                                         FilteredConnectPoint src,
                                                         Set<FilteredConnectPoint> dsts,
                                                         EncapsulationType encap) {
        SinglePointToMultiPointIntent.Builder intentBuilder;

        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthDst(MacAddress.BROADCAST)
                .build();

        intentBuilder = SinglePointToMultiPointIntent.builder()
                .appId(APPID)
                .key(key)
                .selector(selector)
                .filteredIngressPoint(src)
                .filteredEgressPoints(dsts)
                .constraints(PARTIAL_FAILURE_CONSTRAINT)
                .priority(PRIORITY_OFFSET);

        setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);

        return intentBuilder.build();
    }

    /**
     * Builds a unicast intent.
     *
     * @param key the key to identify the intent
     * @param srcs the ingress connect points
     * @param dst the egress connect point
     * @param host the destination Host
     * @return the generated multi-point to single-point intent
     */
    private MultiPointToSinglePointIntent buildUniIntent(Key key,
                                                         Set<FilteredConnectPoint> srcs,
                                                         FilteredConnectPoint dst,
                                                         Host host,
                                                         EncapsulationType encap) {
        MultiPointToSinglePointIntent.Builder intentBuilder;

        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthDst(host.mac())
                .build();

        intentBuilder = MultiPointToSinglePointIntent.builder()
                .appId(APPID)
                .key(key)
                .selector(selector)
                .filteredIngressPoints(srcs)
                .filteredEgressPoint(dst)
                .constraints(PARTIAL_FAILURE_CONSTRAINT)
                .priority(PRIORITY_OFFSET);

        setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);

        return intentBuilder.build();
    }

    /**
     * Returns the filtered connect point associated to a given host.
     *
     * @param host the target host
     * @param fcps the filtered connected points
     * @return the filtered connect point associated to the given host; null
     * otherwise
     */
    private FilteredConnectPoint getHostPoint(Host host,
                                              Set<FilteredConnectPoint> fcps) {
        return fcps.stream()
                .filter(fcp -> fcp.connectPoint().equals(host.location()))
                .filter(fcp -> {
                    VlanIdCriterion vlanCriterion =
                            (VlanIdCriterion) fcp.trafficSelector().
                                    getCriterion(Criterion.Type.VLAN_VID);
                    return vlanCriterion == null ||
                            vlanCriterion.vlanId().equals(host.vlan());
                })
                .findFirst()
                .orElse(null);
    }

    /**
     * Computes a set of filtered connect points from a list of given interfaces.
     *
     * @param interfaces the interfaces to compute
     * @return the set of filtered connect points
     */
    private Set<FilteredConnectPoint> buildFCPoints(Collection<Interface> interfaces) {
        // Build all filtered connected points in the VPLS
        return interfaces
                .stream()
                .map(intf -> {
                    TrafficSelector.Builder selectorBuilder =
                            DefaultTrafficSelector.builder();
                    if (!intf.vlan().equals(VlanId.NONE)) {
                        selectorBuilder.matchVlanId(intf.vlan());
                    }
                    return new FilteredConnectPoint(intf.connectPoint(),
                                                    selectorBuilder.build());
                })
                .collect(Collectors.toSet());
    }

    /**
     * Builds an intent Key either for a single-point to multi-point or
     * multi-point to single-point intent, based on a prefix that defines
     * the intent type, the connection point representing the source or the
     * destination and the VLAN Id representing the VPLS.
     *
     * @param prefix the key prefix
     * @param cPoint the ingress/egress connect point
     * @param vplsName the VPLS name
     * @param hostMac the ingress/egress MAC address
     * @return the key to identify the intent
     */
    private Key buildKey(String prefix,
                         ConnectPoint cPoint,
                         String vplsName,
                         MacAddress hostMac) {
        String keyString = vplsName +
                DASH +
                prefix +
                DASH +
                cPoint.deviceId() +
                DASH +
                cPoint.port() +
                DASH +
                hostMac;

        return Key.of(keyString, APPID);
    }

    /**
     * Returns the device Id of the ith device.
     *
     * @param i the device to get the Id of
     * @return the device Id
     */
    private static DeviceId getDeviceId(int i) {
        return DeviceId.deviceId("" + i);
    }

    private static MacAddress getMac(int n) {
        return MacAddress.valueOf(String.format("00:00:00:00:00:%s", n));
    }

    private static HostLocation getLocation(int i) {
        return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L);
    }

    private static HostLocation getLocation(int d, int p) {
        return new HostLocation(new ConnectPoint(getDeviceId(d),
                                                 PortNumber.portNumber(p)), 123L);
    }

    /**
     * Represents a fake IntentService class that allows to store and retrieve
     * intents without implementing the IntentService logic.
     */
    private class TestIntentService extends IntentServiceAdapter {

        private Map<Key, Intent> intents;

        public TestIntentService() {
            intents = Maps.newHashMap();
        }

        @Override
        public void submit(Intent intent) {
            intents.put(intent.key(), intent);
        }

        @Override
        public long getIntentCount() {
            return intents.size();
        }

        @Override
        public Iterable<Intent> getIntents() {
            return intents.values();
        }

        @Override
        public Intent getIntent(Key intentKey) {
            for (Intent intent : intents.values()) {
                if (intent.key().equals(intentKey)) {
                    return intent;
                }
            }
            return null;
        }
    }

    /**
     * Represents a fake HostService class which allows to add hosts manually
     * in each test, when needed.
     */
    private class TestHostService extends HostServiceAdapter {

        private Set<Host> hosts;

        public TestHostService(Set<Host> hosts) {
            this.hosts = hosts;
        }

        @Override
        public void addListener(HostListener listener) {
            VplsTest.this.hostListener = listener;
        }

        @Override
        public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
            return hosts.stream()
                    .filter(h -> h.location().equals(connectPoint))
                    .collect(Collectors.toSet());
        }

    }

    /**
     * Represents a fake IdGenerator class for intents.
     */
    private static class TestIdGenerator implements IdGenerator {

        private final AtomicLong id = new AtomicLong(0);

        @Override
        public long getNewId() {
            return id.getAndIncrement();
        }

    }

    /**
     * Test IntentSynchronizer that passes all intents straight through to the
     * intent service.
     */
    private class TestIntentSynchronizer implements IntentSynchronizationService {

        private final IntentService intentService;

        /**
         * Creates a new intent test synchronizer.
         *
         * @param intentService intent service
         */
        public TestIntentSynchronizer(IntentService intentService) {
            this.intentService = intentService;
        }

        @Override
        public void submit(Intent intent) {
            intentService.submit(intent);
        }

        @Override
        public void withdraw(Intent intent) {
            intentService.withdraw(intent);
        }

        @Override
        public void removeIntentsByAppId(ApplicationId applicationId) {
        }
    }

    /**
     * Represents a fake VplsConfigService class which is needed for testing.
     */
    private class TestVplsConfigService extends VplsConfigServiceAdapter {

        private final SetMultimap<String, Interface> ifacesByVplsName;
        private final Map<String, EncapsulationType> encapsByVplsName;

        private Set<String> vplsAffectByApi = new HashSet<>();

        TestVplsConfigService(SetMultimap<String, Interface> ifacesByVplsName,
                              Map<String, EncapsulationType> encapsByVplsName) {
            this.ifacesByVplsName = ifacesByVplsName;
            this.encapsByVplsName = encapsByVplsName;
        }

        @Override
        public void addVpls(String vplsName, Set<String> ifaceNames, String encap) {
            if (!ifacesByVplsName.containsKey(vplsName)) {
                ifaceNames.forEach(ifaceName -> {
                    AVAILABLE_INTERFACES.forEach(iface -> {
                        if (iface.name().equals(ifaceName)) {
                            ifacesByVplsName.put(vplsName, iface);
                        }
                    });
                });
            }
            if (!ifacesByVplsName.containsKey(vplsName)) {
                encapsByVplsName.put(vplsName, valueOf(encap));
            }
        }

        @Override
        public void removeVpls(String vplsName) {
            if (ifacesByVplsName.containsKey(vplsName)) {
                ifacesByVplsName.removeAll(vplsName);
            }
        }

        @Override
        public void addIface(String vplsName, String iface) {
            if (!ifacesByVplsName.containsKey(vplsName)) {
                AVAILABLE_INTERFACES.forEach(intf -> {
                    if (intf.name().equals(iface)) {
                        ifacesByVplsName.put(vplsName, intf);
                    }
                });
            }
        }

        @Override
        public void setEncap(String vplsName, String encap) {
            encapsByVplsName.put(vplsName, EncapsulationType.enumFromString(encap));
        }

        @Override
        public void removeIface(String iface) {
            SetMultimap<String, Interface> search = HashMultimap.create(ifacesByVplsName);
            search.entries().forEach(e -> {
                if (e.getValue().name().equals(iface)) {
                    ifacesByVplsName.remove(e.getKey(), iface);
                }
            });
        }

        @Override
        public void cleanVplsConfig() {
            ifacesByVplsName.clear();
        }

        @Override
        public EncapsulationType encap(String vplsName) {
            EncapsulationType encap = null;
            if (encapsByVplsName.containsKey(vplsName)) {
                encap = encapsByVplsName.get(vplsName);
            }
            return encap;
        }

        @Override
        public Set<String> vplsAffectedByApi() {
            Set<String> vplsNames = ImmutableSet.copyOf(vplsAffectByApi);

            vplsAffectByApi.clear();

            return vplsNames;
        }

        @Override
        public Set<Interface> allIfaces() {
            return ifacesByVplsName.values()
                    .stream()
                    .collect(Collectors.toSet());
        }

        @Override
        public Set<Interface> ifaces(String name) {
            return ifacesByVplsName.get(name)
                    .stream()
                    .collect(Collectors.toSet());
        }

        @Override
        public Set<String> vplsNames() {
            return ifacesByVplsName.keySet();
        }

        @Override
        public Set<String> vplsNamesOld() {
            return ifacesByVplsName.keySet();
        }

        public SetMultimap<String, Interface> ifacesByVplsName() {
            return ImmutableSetMultimap.copyOf(ifacesByVplsName);
        }

        @Override
        public SetMultimap<String, Interface> ifacesByVplsName(VlanId vlan,
                                                               ConnectPoint connectPoint) {
            String vplsName =
                    ifacesByVplsName.entries().stream()
                            .filter(e -> e.getValue().connectPoint().equals(connectPoint))
                            .filter(e -> e.getValue().vlan().equals(vlan))
                            .map(Map.Entry::getKey)
                            .findFirst()
                            .orElse(null);
            SetMultimap<String, Interface> result = HashMultimap.create();
            if (vplsName != null && ifacesByVplsName.containsKey(vplsName)) {
                ifacesByVplsName.get(vplsName)
                        .forEach(intf -> result.put(vplsName, intf));
                return result;
            }
            return null;
        }
    }
}
