/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.SetMultimap;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.neighbour.NeighbourHandlerRegistration;
import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
import org.onosproject.incubator.net.neighbour.NeighbourMessageType;
import org.onosproject.incubator.net.neighbour.NeighbourProtocol;
import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.host.HostService;
import org.onosproject.vpls.api.VplsData;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;

/**
 * Tests the the {@link VplsNeighbourHandler}.
 */
public class VplsNeighbourHandlerTest extends VplsTest {

    private static final String IFACES_NOT_EXPECTED =
            "The interfaces reached by the packet are not equal to the " +
                    "interfaces expected.";
    private VplsNeighbourHandler vplsNeighbourHandler;
    private HostService hostService;

    /**
     * Sets up 4 VPLS.
     * VPLS 1 contains 3 hosts: v100h1, v200h1 and v300h1
     * VPLS 2 contains 2 hosts: v100h2, v200h2
     * VPLS 3 contains 2 hosts: vNoneh1, vNoneh2
     * VPLS 4 contains 2 hosts: v400h1, vNoneh3
     */
    @Before
    public void setUp() {
        vplsNeighbourHandler = new VplsNeighbourHandler();
        hostService = new TestHostService();
        vplsNeighbourHandler.vplsStore = new TestVplsStore();
        vplsNeighbourHandler.interfaceService = new TestInterfaceService();
        vplsNeighbourHandler.neighbourService = new TestNeighbourService();
        vplsNeighbourHandler.coreService = new TestCoreService();
        vplsNeighbourHandler.configService = new TestConfigService();

        // Init VPLS store
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V200H1, V300H1));
        vplsNeighbourHandler.vplsStore.addVpls(vplsData);

        vplsData = VplsData.of(VPLS2);
        vplsData.addInterfaces(ImmutableSet.of(V100H2, V200H2));
        vplsNeighbourHandler.vplsStore.addVpls(vplsData);

        vplsData = VplsData.of(VPLS3);
        vplsData.addInterfaces(ImmutableSet.of(VNONEH1, VNONEH2));
        vplsNeighbourHandler.vplsStore.addVpls(vplsData);

        vplsData = VplsData.of(VPLS4);
        vplsData.addInterfaces(ImmutableSet.of(V400H1, VNONEH3));
        vplsNeighbourHandler.vplsStore.addVpls(vplsData);

        vplsNeighbourHandler.activate();

    }

    @After
    public void tearDown() {
        vplsNeighbourHandler.deactivate();
    }

    /**
     * Registers neighbour handler to all available interfaces.
     */
    @Test
    public void testConfigNeighbourHandler() {
        vplsNeighbourHandler.configNeighbourHandler();
        assertEquals(9, vplsNeighbourHandler.neighbourService.getHandlerRegistrations().size());
    }

    /**
     * Sends request messages to all hosts in VPLS 1.
     * Request messages should be received from other hosts in VPLS 1.
     */
    @Test
    public void vpls1RequestMessage() {
        // Request messages from v100h1 (VPLS 1) should be received by v200h1 and v300h1
        TestMessageContext requestMessage =
                makeBroadcastRequestContext(V100HOST1);
        Set<Interface> expectInterfaces = ImmutableSet.of(V200H1, V300H1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);

        // Request messages from v200h1 (VPLS 1) should be received by v100h1 and v300h1
        requestMessage = makeBroadcastRequestContext(V200HOST1);
        expectInterfaces = ImmutableSet.of(V100H1, V300H1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);

        // Request from v300h1 (VPLS 1) should be received by v100h1 and v200h1
        requestMessage = makeBroadcastRequestContext(V300HOST1);
        expectInterfaces = ImmutableSet.of(V100H1, V200H1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
    }

    /**
     * Sends request messages to all hosts in VPLS 2.
     * Request messages should be received from other hosts in VPLS 2.
     */
    @Test
    public void vpls2RequestMessage() {
        // Request messages from v100h2 (VPLS 2) should be received by v200h2
        TestMessageContext requestMessage =
                makeBroadcastRequestContext(V100HOST2);
        Set<Interface> expectInterfaces = ImmutableSet.of(V200H2);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);

        // Request messages from v200h2 (VPLS 2) should be received by v100h2
        requestMessage = makeBroadcastRequestContext(V200HOST2);
        expectInterfaces = ImmutableSet.of(V100H2);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
    }

    /**
     * Tests correct connection between untagged interfaces.
     *
     * Sends request messages to all hosts in VPLS 3.
     * Request messages should be received from other hosts in VPLS 3.
     */
    @Test
    public void vpls3RequestMessage() {
        // Request messages from VNONEHOST1 (VPLS 3) should be received by VNONEHOST2
        TestMessageContext requestMessage =
                makeBroadcastRequestContext(VNONEHOST1);
        Set<Interface> expectInterfaces = ImmutableSet.of(VNONEH2);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);

        // Request messages from vNoneh2 (VPLS 3) should be received by vNoneh1
        requestMessage = makeBroadcastRequestContext(VNONEHOST2);
        expectInterfaces = ImmutableSet.of(VNONEH1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
    }

    /**
     * Tests correct connection between tagged and untagged interfaces.
     *
     * Sends request messages to all hosts in VPLS 4.
     * Request messages should be received from other hosts in VPLS 4.
     */
    @Test
    public void vpls4RequestMessage() {
        // Request messages from V400HOST1 (VPLS 4) should be received by VNONEHOST3
        TestMessageContext requestMessage =
                makeBroadcastRequestContext(V400HOST1);
        Set<Interface> expectInterfaces = ImmutableSet.of(VNONEH3);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);

        // Request messages from VNONEHOST3 (VPLS 4) should be received by V400HOST1
        requestMessage = makeBroadcastRequestContext(VNONEHOST3);
        expectInterfaces = ImmutableSet.of(V400H1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
    }

    /**
     * Sends reply messages to hosts in VPLS 1.
     * Reply messages should be received by the host with MAC address equal to
     * the dstMac of the message context.
     */
    @Test
    public void vpls1ReplyMessage() {
        // Reply messages from v100h1 (VPLS 1) should be received by v200h1
        TestMessageContext replyMessage =
                makeReplyContext(V100HOST1, V200HOST1);
        Set<Interface> expectInterfaces = ImmutableSet.of(V200H1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);

        // Reply messages from v200h1 (VPLS 1) should be received by v300h1
        replyMessage = makeReplyContext(V200HOST1, V300HOST1);
        expectInterfaces = ImmutableSet.of(V300H1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);

        // Reply messages from v300h1 (VPLS 1) should be received by v100h1
        replyMessage = makeReplyContext(V300HOST1, V100HOST1);
        expectInterfaces = ImmutableSet.of(V100H1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
    }

    /**
     * Sends reply messages to hosts in VPLS 2.
     * Reply messages should be received by the host with MAC address equal to
     * the dstMac of the message context.
     */
    @Test
    public void vpls2ReplyMessage() {
        // Reply messages from v100h2 (VPLS 2) should be received by v200h2
        TestMessageContext replyMessage =
                makeReplyContext(V100HOST2, V200HOST2);
        Set<Interface> expectInterfaces = ImmutableSet.of(V200H2);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);

        // Reply messages from v200h2 (VPLS 2) should be received by v100h2
        replyMessage = makeReplyContext(V200HOST2, V100HOST2);
        expectInterfaces = ImmutableSet.of(V100H2);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
    }

    /**
     * Sends reply messages to hosts in VPLS 3.
     * Reply messages should be received by the host with MAC address equal to
     * the dstMac of the message context.
     */
    @Test
    public void vpls3ReplyMessage() {
        // Reply messages from vNoneh1 (VPLS 3) should be received by vNoneh2
        TestMessageContext replyMessage =
                makeReplyContext(VNONEHOST1, VNONEHOST2);
        Set<Interface> expectInterfaces = ImmutableSet.of(VNONEH2);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);

        // Reply messages from vNoneh2 (VPLS 3) should be received by vNoneh1
        replyMessage = makeReplyContext(VNONEHOST2, VNONEHOST1);
        expectInterfaces = ImmutableSet.of(VNONEH1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
    }

    /**
     * Sends reply messages to hosts in VPLS 4.
     * Reply messages should be received by the host with MAC address equal to
     * the dstMac of the message context.
     */
    @Test
    public void vpls4ReplyMessage() {
        // Reply messages from v400h1 (VPLS 4) should be received by vNoneh3
        TestMessageContext replyMessage =
                makeReplyContext(V400HOST1, VNONEHOST3);
        Set<Interface> expectInterfaces = ImmutableSet.of(VNONEH3);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);

        // Reply messages from vNoneh3 (VPLS 4) should be received by v400h1
        replyMessage = makeReplyContext(VNONEHOST3, V400HOST1);
        expectInterfaces = ImmutableSet.of(V400H1);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
    }

    /**
     * Sends wrong reply messages to hosts.
     * The source and the destination MAC addresses are not set on any host of the VPLS.
     * The reply messages will not be received by any hosts.
     */
    @Test
    public void wrongReplyMessage() {
        // Reply message from v100h1 (VPLS 1) to v100h2 (VPLS 2).
        // Forward results should be empty
        TestMessageContext replyMessage = makeReplyContext(V100HOST1, V100HOST2);
        Set<Interface> expectInterfaces = ImmutableSet.of();
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);

        // Reply message from v200h2 (VPLS 2) to v300h1 (VPLS 1).
        // Forward results should be empty
        replyMessage = makeReplyContext(V200HOST2, V300HOST1);
        expectInterfaces = ImmutableSet.of();
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);

        // Reply message from vNoneh1 (VPLS 3) to v400h1 (VPLS 4).
        // Forward results should be empty
        replyMessage = makeReplyContext(VNONEHOST1, V400HOST1);
        expectInterfaces = ImmutableSet.of();
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);

        // Reply message from vNoneh3 (VPLS 4) to vNoneH2 (VPLS 3).
        // Forward results should be empty
        replyMessage = makeReplyContext(VNONEHOST3, VNONEHOST2);
        expectInterfaces = ImmutableSet.of();
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
    }

    /**
     * Sends reply and request message from a host which not related to any VPLS.
     */
    @Test
    public void testVplsNotfound() {
        TestMessageContext replyMessage = makeReplyContext(V300HOST2, V100HOST1);
        Set<Interface> expectInterfaces = ImmutableSet.of();
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(replyMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
        assertTrue(replyMessage.dropped());

        TestMessageContext requestMessage = makeBroadcastRequestContext(V300HOST2);
        ((TestNeighbourService) vplsNeighbourHandler.neighbourService).sendNeighourMessage(requestMessage);
        assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
        assertTrue(requestMessage.dropped());
    }

    /**
     * Generates broadcast request message context by given source host.
     *
     * @param host the source host
     * @return the request message context
     */
    private TestMessageContext makeBroadcastRequestContext(Host host) {
        return new TestMessageContext(host.location(),
                                      host.mac(),
                                      MacAddress.BROADCAST,
                                      host.vlan(),
                                      NeighbourMessageType.REQUEST);
    }

    /**
     * Generates reply message context by given source and destination host.
     *
     * @param src the source host
     * @param dst the destination host
     * @return the reply message context
     */
    private TestMessageContext makeReplyContext(Host src, Host dst) {
        return new TestMessageContext(src.location(),
                                      src.mac(),
                                      dst.mac(),
                                      src.vlan(),
                                      NeighbourMessageType.REPLY);
    }

    /**
     * Test message context.
     */
    private class TestMessageContext implements NeighbourMessageContext {
        private final NeighbourMessageType type;
        private final MacAddress srcMac;
        private final MacAddress dstMac;
        private final ConnectPoint inPort;
        private final VlanId vlanId;
        private boolean dropped = false;
        public Set<Interface> forwardResults;

        /**
         * Creates new neighbour message context for test.
         *
         * @param inPort the input port
         * @param srcMac the source Mac
         * @param dstMac the destination Mac
         * @param vlanId the VLAN Id
         * @param type the message context type
         */
        public TestMessageContext(
                ConnectPoint inPort,
                MacAddress srcMac,
                MacAddress dstMac,
                VlanId vlanId,
                NeighbourMessageType type) {

            this.inPort = inPort;
            this.srcMac = srcMac;
            this.dstMac = dstMac;
            this.vlanId = vlanId;
            this.type = type;
            this.forwardResults = Sets.newHashSet();
            this.dropped = false;
        }

        @Override
        public ConnectPoint inPort() {
            return inPort;
        }

        @Override
        public NeighbourMessageType type() {
            return type;
        }

        @Override
        public VlanId vlan() {
            return vlanId;
        }

        @Override
        public MacAddress srcMac() {
            return srcMac;
        }

        @Override
        public MacAddress dstMac() {
            return dstMac;
        }

        @Override
        public IpAddress target() {
            return null;
        }

        @Override
        public IpAddress sender() {
            return null;
        }

        @Override
        public void forward(ConnectPoint outPort) {
        }

        /**
         * Records all forward network interface information.
         * @param outIntf output interface
         */
        @Override
        public void forward(Interface outIntf) {
            forwardResults.add(outIntf);
        }

        @Override
        public void reply(MacAddress targetMac) {
        }

        @Override
        public void flood() {
        }

        @Override
        public void drop() {
            this.dropped = true;
        }

        @Override
        public Ethernet packet() {
            return null;
        }

        @Override
        public NeighbourProtocol protocol() {
            return null;
        }

        public boolean dropped() {
            return dropped;
        }
    }

    /**
     * Test neighbour service; records all registrations between neighbour
     * message handler and interfaces.
     */
    private class TestNeighbourService implements NeighbourResolutionService {
        private SetMultimap<ConnectPoint, NeighbourHandlerRegistration> handlerRegs;

        public TestNeighbourService() {
            handlerRegs = HashMultimap.create();
        }

        @Override
        public void registerNeighbourHandler(ConnectPoint connectPoint,
                                             NeighbourMessageHandler handler,
                                             ApplicationId appId) {
            Interface intf =
                    new Interface(null, connectPoint, null, null, null);

            NeighbourHandlerRegistration reg =
                    new HandlerRegistration(handler, intf, appId);

            handlerRegs.put(connectPoint, reg);
        }

        @Override
        public void registerNeighbourHandler(Interface intf,
                                             NeighbourMessageHandler handler,
                                             ApplicationId appId) {
            NeighbourHandlerRegistration reg =
                    new HandlerRegistration(handler, intf, appId);
            handlerRegs.put(intf.connectPoint(), reg);
        }

        @Override
        public void unregisterNeighbourHandler(ConnectPoint connectPoint,
                                               NeighbourMessageHandler handler,
                                               ApplicationId appId) {
            handlerRegs.removeAll(connectPoint);
        }

        @Override
        public void unregisterNeighbourHandler(Interface intf,
                                               NeighbourMessageHandler handler,
                                               ApplicationId appId) {
            handlerRegs.removeAll(intf.connectPoint());
        }

        @Override
        public void unregisterNeighbourHandlers(ApplicationId appId) {
            handlerRegs.clear();
        }

        @Override
        public Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations() {
            return handlerRegs.asMap();
        }

        /**
         * Sends neighbour message context to all handler which related to the
         * context.
         *
         * @param context the neighbour message context
         */
        public void sendNeighourMessage(NeighbourMessageContext context) {
            ConnectPoint connectPoint = context.inPort();
            VlanId vlanId = context.vlan();
            Collection<NeighbourHandlerRegistration> registrations = handlerRegs.get(connectPoint);
            registrations.forEach(reg -> {
                if (reg.intf().vlan().equals(vlanId)) {
                    reg.handler().handleMessage(context, hostService);
                }
            });
        }

        /**
         * Test handler registration.
         */
        private class HandlerRegistration implements NeighbourHandlerRegistration {
            private final Interface intf;
            private final NeighbourMessageHandler handler;
            private final ApplicationId appId;

            /**
             * Creates a new registration handler.
             *
             * @param handler the neighbour message handler
             * @param intf the interface
             */
            public HandlerRegistration(NeighbourMessageHandler handler,
                                       Interface intf,
                                       ApplicationId appId) {
                this.intf = intf;
                this.handler = handler;
                this.appId = appId;
            }

            @Override
            public Interface intf() {
                return intf;
            }

            @Override
            public NeighbourMessageHandler handler() {
                return handler;
            }

            @Override
            public ApplicationId appId() {
                return appId;
            }
        }
    }
}
