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

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.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.net.ConnectPoint;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContextAdapter;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
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 java.util.Collection;

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.incubator.net.neighbour.impl.DefaultNeighbourMessageContext.createContext;
import static org.onosproject.incubator.net.neighbour.impl.NeighbourTestUtils.createArpRequest;
import static org.onosproject.incubator.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) {

        }
    }

}
