/*
 * 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.net.neighbour.impl;

import java.util.Collection;

import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ComponentContextAdapter;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.TestApplicationId;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.neighbour.NeighbourHandlerRegistration;
import org.onosproject.net.neighbour.NeighbourMessageContext;
import org.onosproject.net.neighbour.NeighbourMessageHandler;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketContextAdapter;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.packet.PacketServiceAdapter;

import static org.easymock.EasyMock.anyInt;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.eq;
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.assertTrue;
import static org.onosproject.net.neighbour.impl.DefaultNeighbourMessageContext.createContext;
import static org.onosproject.net.neighbour.impl.NeighbourTestUtils.createArpRequest;
import static org.onosproject.net.neighbour.impl.NeighbourTestUtils.intf;

/**
 * Unit tests for the NeighbourResolutionManager.
 */
public class NeighbourResolutionManagerTest {

    private NeighbourResolutionManager neighbourManager;

    private PacketService packetService;
    private PacketProcessor packetProcessor;

    private static final NeighbourMessageHandler HANDLER = new TestNeighbourHandler();

    private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
    private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");

    private static final MacAddress MAC1 = MacAddress.valueOf(1);
    private static final IpAddress IP1 = IpAddress.valueOf(1);
    private static final IpAddress IP2 = IpAddress.valueOf(2);

    private static final Interface INTF1 = intf(CP1, IP1, MAC1, VlanId.NONE);

    private static final ApplicationId APP_ID = TestApplicationId.create("app");

    @Before
    public void setUp() throws Exception {
        neighbourManager = new NeighbourResolutionManager();

        packetService = createMock(PacketService.class);
        packetService.requestPackets(anyObject(TrafficSelector.class),
                anyObject(PacketPriority.class), anyObject(ApplicationId.class));
        expectLastCall().anyTimes();
        packetService.addProcessor(anyObject(PacketProcessor.class), anyInt());
        expectLastCall().andDelegateTo(new TestPacketService()).once();
        packetService.cancelPackets(anyObject(TrafficSelector.class),
                anyObject(PacketPriority.class), anyObject(ApplicationId.class));
        expectLastCall().anyTimes();
        replay(packetService);

        neighbourManager.packetService = packetService;

        CoreService coreService = createNiceMock(CoreService.class);
        replay(coreService);
        neighbourManager.coreService = coreService;

        neighbourManager.componentConfigService = new ComponentConfigAdapter();

        neighbourManager.activate(new ComponentContextAdapter());
    }

    @Test
    public void testRegistration() throws Exception {
        neighbourManager.registerNeighbourHandler(CP1, HANDLER, APP_ID);

        assertTrue(verifyRegistration(CP1, HANDLER, APP_ID));
    }

    @Test
    public void testUnregister() {
        // Register a handler and verify the registration is there
        neighbourManager.registerNeighbourHandler(CP1, HANDLER, APP_ID);
        assertTrue(verifyRegistration(CP1, HANDLER, APP_ID));

        // Unregister the handler but supply a different connect point
        neighbourManager.unregisterNeighbourHandler(CP2, HANDLER, APP_ID);

        // Verify the original registration is still there on the original
        // connect point
        assertTrue(verifyRegistration(CP1, HANDLER, APP_ID));

        assertTrue(verifyNoRegistration(CP2));

        // Unregister the handler from the original connect point
        neighbourManager.unregisterNeighbourHandler(CP1, HANDLER, APP_ID);

        // Verify that it is gone
        assertTrue(verifyNoRegistration(CP1));
    }

    @Test
    public void testRegisterInterface() {
        neighbourManager.registerNeighbourHandler(INTF1, HANDLER, APP_ID);

        assertTrue(verifyRegistration(INTF1, HANDLER, APP_ID));
    }

    @Test
    public void testUnregisterInterface() {
        // Register a handler for an interface and verify it is there
        neighbourManager.registerNeighbourHandler(INTF1, HANDLER, APP_ID);
        assertTrue(verifyRegistration(INTF1, HANDLER, APP_ID));

        // Unregister the handler but use the connect point rather than the interface
        neighbourManager.unregisterNeighbourHandler(CP1, HANDLER, APP_ID);

        // Verify the interface registration is still there
        assertTrue(verifyRegistration(INTF1, HANDLER, APP_ID));

        // Unregister the handler from the interface
        neighbourManager.unregisterNeighbourHandler(INTF1, HANDLER, APP_ID);

        // Verify the registration is gone
        assertTrue(verifyNoRegistration(INTF1));
    }

    @Test
    public void testUnregisterByAppId() {
        // Register some handlers and verify they are there
        neighbourManager.registerNeighbourHandler(CP1, HANDLER, APP_ID);
        neighbourManager.registerNeighbourHandler(CP2, HANDLER, APP_ID);

        assertEquals(2, neighbourManager.getHandlerRegistrations().size());

        // Unregister all handlers for the given app ID
        neighbourManager.unregisterNeighbourHandlers(APP_ID);

        // Verify the handlers are gone
        assertEquals(0, neighbourManager.getHandlerRegistrations().size());
    }

    @Test
    public void testPacketDistribution() {
        Ethernet arpRequest = createArpRequest(IP1);

        NeighbourMessageHandler handler = createMock(NeighbourMessageHandler.class);
        handler.handleMessage(eq(createContext(arpRequest, CP1, null)), anyObject(HostService.class));
        expectLastCall().once();
        replay(handler);
        neighbourManager.registerNeighbourHandler(CP1, handler, APP_ID);

        // Incoming packet on the connect point where the handler is registered
        packetProcessor.process(context(arpRequest, CP1));

        // Send a packet from a different connect point that should not be
        // delivered to the handler
        packetProcessor.process(context(arpRequest, CP2));

        verify(handler);
    }

    @Test
    public void testPacketDistributionToInterface() {
        Ethernet arpRequest = createArpRequest(IP1);

        NeighbourMessageHandler handler = createMock(NeighbourMessageHandler.class);
        handler.handleMessage(eq(createContext(arpRequest, CP1, null)), anyObject(HostService.class));
        expectLastCall().once();
        replay(handler);
        neighbourManager.registerNeighbourHandler(INTF1, handler, APP_ID);

        // Incoming packet matching the interface where the handler is registered
        packetProcessor.process(context(arpRequest, CP1));

        verify(handler);

        reset(handler);
        replay(handler);

        // Incoming packet on same connect point but not matching the interface
        packetProcessor.process(context(createArpRequest(IP2), CP1));

        verify(handler);
    }

    /**
     * Verifies that there is one registration for the given connect point and
     * that the registration matches the given handler and appId.
     *
     * @param cp connect point to verify registration for
     * @param handler neighbour message handler
     * @param appId application ID
     * @return true if the registration is the only registration present for
     * this connect point, otherwise false
     */
    private boolean verifyRegistration(ConnectPoint cp, NeighbourMessageHandler handler, ApplicationId appId) {
        Collection<NeighbourHandlerRegistration> registrations =
                neighbourManager.getHandlerRegistrations().get(cp);

        if (registrations == null) {
            return false;
        }

        if (registrations.size() != 1) {
            return false;
        }

        NeighbourHandlerRegistration reg = registrations.stream().findFirst().get();

        return reg.appId().equals(appId) &&
                reg.handler().equals(handler);
    }

    /**
     * Verifies that there is one registration for the given interface and
     * that the registration matches the given handler and appId.
     *
     * @param intf interface to verify registration for
     * @param handler neighbour message handler
     * @param appId application ID
     * @return true if the registration is the only registration present for
     * this interface, otherwise false
     */
    private boolean verifyRegistration(Interface intf, NeighbourMessageHandler handler, ApplicationId appId) {
        return verifyRegistration(intf.connectPoint(), handler, appId);
    }

    /**
     * Verifies that there are no registrations for the given connect point.
     *
     * @param cp connect point
     * @return true if there are no registrations for this connect point,
     * otherwise false
     */
    private boolean verifyNoRegistration(ConnectPoint cp) {
        return neighbourManager.getHandlerRegistrations().get(cp) == null;
    }

    /**
     * Verifies that there are no registrations for the given interface.
     *
     * @param intf interface
     * @return true if there are no registrations for this interface,
     * otherwise false
     */
    private boolean verifyNoRegistration(Interface intf) {
        return verifyNoRegistration(intf.connectPoint());
    }

    /**
     * Creates a packet context for the given packet coming in the given port.
     *
     * @param packet packet to wrap in a packet context
     * @param inPort input port of the packet
     * @return packet context
     */
    private static PacketContext context(Ethernet packet, ConnectPoint inPort) {
        InboundPacket inboundPacket = new DefaultInboundPacket(inPort, packet, null);
        OutboundPacket outboundPacket = new DefaultOutboundPacket(null, null, null);
        return new PacketContextAdapter(0, inboundPacket, outboundPacket, false);
    }

    private class TestPacketService extends PacketServiceAdapter {

        @Override
        public void addProcessor(PacketProcessor processor, int priority) {
            NeighbourResolutionManagerTest.this.packetProcessor = processor;
        }
    }

    private static class TestNeighbourHandler implements NeighbourMessageHandler {

        @Override
        public void handleMessage(NeighbourMessageContext context, HostService hostService) {

        }
    }

}
