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

import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.incubator.net.routing.ResolvedRoute;
import org.onosproject.incubator.net.routing.Route;
import org.onosproject.incubator.net.routing.RouteEvent;
import org.onosproject.incubator.net.routing.RouteListener;
import org.onosproject.incubator.store.routing.impl.LocalRouteStore;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
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.provider.ProviderId;

import java.util.Collections;

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.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;

/**
 * Unit tests for the route manager.
 */
public class RouteManagerTest {

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

    private static final IpPrefix V4_PREFIX1 = Ip4Prefix.valueOf("1.1.1.0/24");
    private static final IpPrefix V4_PREFIX2 = Ip4Prefix.valueOf("2.2.2.0/24");
    private static final IpPrefix V6_PREFIX1 = Ip6Prefix.valueOf("4000::/64");

    private static final IpAddress V4_NEXT_HOP1 = Ip4Address.valueOf("192.168.10.1");
    private static final IpAddress V4_NEXT_HOP2 = Ip4Address.valueOf("192.168.20.1");
    private static final IpAddress V6_NEXT_HOP1 = Ip6Address.valueOf("1000::1");
    private static final IpAddress V6_NEXT_HOP2 = Ip6Address.valueOf("2000::1");

    private static final MacAddress MAC1 = MacAddress.valueOf("00:00:00:00:00:01");
    private static final MacAddress MAC2 = MacAddress.valueOf("00:00:00:00:00:02");
    private static final MacAddress MAC3 = MacAddress.valueOf("00:00:00:00:00:03");
    private static final MacAddress MAC4 = MacAddress.valueOf("00:00:00:00:00:04");

    private HostService hostService;

    private RouteListener routeListener;
    private HostListener hostListener;

    private RouteManager routeManager;

    @Before
    public void setUp() throws Exception {
        setUpHostService();

        routeListener = createMock(RouteListener.class);

        routeManager = new TestRouteManager();
        routeManager.hostService = hostService;

        LocalRouteStore routeStore = new LocalRouteStore();
        routeStore.activate();
        routeManager.routeStore = routeStore;
        routeManager.activate();

        routeManager.addListener(routeListener);
    }

    /**
     * Sets up the host service with details of some hosts.
     */
    private void setUpHostService() {
        hostService = createMock(HostService.class);

        hostService.addListener(anyObject(HostListener.class));
        expectLastCall().andDelegateTo(new TestHostService()).anyTimes();

        Host host1 = createHost(MAC1, V4_NEXT_HOP1);
        expectHost(host1);

        Host host2 = createHost(MAC2, V4_NEXT_HOP2);
        expectHost(host2);

        Host host3 = createHost(MAC3, V6_NEXT_HOP1);
        expectHost(host3);

        Host host4 = createHost(MAC4, V6_NEXT_HOP2);
        expectHost(host4);

        replay(hostService);
    }

    /**
     * Sets expectations on the host service for a given host.
     *
     * @param host host
     */
    private void expectHost(Host host) {
        // Assume the host only has one IP address
        IpAddress ip = host.ipAddresses().iterator().next();

        expect(hostService.getHostsByIp(ip))
                .andReturn(Sets.newHashSet(host)).anyTimes();
        hostService.startMonitoringIp(ip);
        expectLastCall().anyTimes();
    }

    /**
     * Creates a host with the given parameters.
     *
     * @param macAddress MAC address
     * @param ipAddress IP address
     * @return new host
     */
    private Host createHost(MacAddress macAddress, IpAddress ipAddress) {
        return new DefaultHost(ProviderId.NONE, HostId.NONE, macAddress,
                VlanId.NONE, new HostLocation(CP1, 1),
                Sets.newHashSet(ipAddress));
    }

    /**
     * Adds a route to the route service without expecting any specific events
     * to be sent to the route listeners.
     *
     * @param route route to add
     */
    private void addRoute(Route route) {
        reset(routeListener);

        routeListener.event(anyObject(RouteEvent.class));
        expectLastCall().once();
        replay(routeListener);

        routeManager.update(Collections.singleton(route));

        reset(routeListener);
    }

    /**
     * Tests adding routes to the route manager.
     */
    @Test
    public void testRouteAdd() {
        Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1);
        ResolvedRoute resolvedRoute = new ResolvedRoute(route, MAC1, CP1);

        verifyRouteAdd(route, resolvedRoute);

        route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1);
        resolvedRoute = new ResolvedRoute(route, MAC3, CP1);

        verifyRouteAdd(route, resolvedRoute);
    }

    /**
     * Tests adding a new route and verifies that the correct event was sent
     * to the route listener.
     *
     * @param route route to add
     * @param resolvedRoute resolved route that should be sent to the route
     *                      listener
     */
    private void verifyRouteAdd(Route route, ResolvedRoute resolvedRoute) {
        reset(routeListener);

        routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, resolvedRoute));

        replay(routeListener);

        routeManager.update(Collections.singleton(route));

        verify(routeListener);
    }

    /**
     * Tests updating routes in the route manager.
     */
    @Test
    public void testRouteUpdate() {
        Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1);
        Route updatedRoute = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP2);
        ResolvedRoute updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2, CP1);

        verifyRouteRemoveThenAdd(route, updatedRoute, updatedResolvedRoute);

        // Different prefix pointing to the same next hop.
        // In this case we expect to receive a ROUTE_UPDATED event.
        route = new Route(Route.Source.STATIC, V4_PREFIX2, V4_NEXT_HOP1);
        updatedRoute = new Route(Route.Source.STATIC, V4_PREFIX2, V4_NEXT_HOP2);
        updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2, CP1);

        verifyRouteUpdated(route, updatedRoute, updatedResolvedRoute);

        route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1);
        updatedRoute = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP2);
        updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC4, CP1);

        verifyRouteRemoveThenAdd(route, updatedRoute, updatedResolvedRoute);
    }

    /**
     * Tests updating a route and verifies that the route listener receives a
     * route remove event followed by a route add event.
     *
     * @param original original route
     * @param updated updated route
     * @param updatedResolvedRoute resolved route that is expected to be sent to
     *                             the route listener
     */
    private void verifyRouteRemoveThenAdd(Route original, Route updated,
                                          ResolvedRoute updatedResolvedRoute) {
        // First add the original route
        addRoute(original);

        routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED,
                new ResolvedRoute(original, null, null)));
        expectLastCall().once();
        routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, updatedResolvedRoute));
        expectLastCall().once();

        replay(routeListener);

        routeManager.update(Collections.singleton(updated));

        verify(routeListener);
    }

    /**
     * Tests updating a route and verifies that the route listener receives a
     * route updated event.
     *
     * @param original original route
     * @param updated updated route
     * @param updatedResolvedRoute resolved route that is expected to be sent to
     *                             the route listener
     */
    private void verifyRouteUpdated(Route original, Route updated,
                                    ResolvedRoute updatedResolvedRoute) {
        // First add the original route
        addRoute(original);

        routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, updatedResolvedRoute));
        expectLastCall().once();

        replay(routeListener);

        routeManager.update(Collections.singleton(updated));

        verify(routeListener);
    }

    /**
     * Tests deleting routes from the route manager.
     */
    @Test
    public void testRouteDelete() {
        Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1);

        verifyDelete(route);

        route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1);

        verifyDelete(route);
    }

    /**
     * Tests deleting a route and verifies that the correct event is sent to
     * the route listener.
     *
     * @param route route to delete
     */
    private void verifyDelete(Route route) {
        addRoute(route);

        RouteEvent withdrawRouteEvent = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED,
                new ResolvedRoute(route, null, null));

        reset(routeListener);
        routeListener.event(withdrawRouteEvent);

        replay(routeListener);

        routeManager.withdraw(Collections.singleton(route));

        verify(routeListener);
    }

    /**
     * Tests adding a route entry where the HostService does not immediately
     * know the MAC address of the next hop, but this is learnt later.
     */
    @Test
    public void testAsyncRouteAdd() {
        Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1);

        // Host service will reply with no hosts when asked
        reset(hostService);
        expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
                Collections.emptySet()).anyTimes();
        hostService.startMonitoringIp(V4_NEXT_HOP1);
        replay(hostService);

        // Initially when we add the route, no route event will be sent because
        // the host is not known
        replay(routeListener);

        routeManager.update(Collections.singleton(route));

        verify(routeListener);

        // Now when we send the event, we expect the FIB update to be sent
        reset(routeListener);
        routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED,
                new ResolvedRoute(route, MAC1, CP1)));
        replay(routeListener);

        // Send in the host event
        Host host = createHost(MAC1, V4_NEXT_HOP1);
        hostListener.event(new HostEvent(HostEvent.Type.HOST_ADDED, host));

        verify(routeListener);
    }

    /**
     * Test host service that stores a reference to the host listener.
     */
    private class TestHostService extends HostServiceAdapter {
        @Override
        public void addListener(HostListener listener) {
            hostListener = listener;
        }
    }

    /**
     * Test route manager that extends the real route manager and injects a test
     * listener queue instead of the real listener queue.
     */
    private static class TestRouteManager extends RouteManager {
        @Override
        ListenerQueue createListenerQueue(RouteListener listener) {
            return new TestListenerQueue(listener);
        }
    }

    /**
     * Test listener queue that simply passes route events straight through to
     * the route listener on the caller's thread.
     */
    private static class TestListenerQueue implements ListenerQueue {

        private final RouteListener listener;

        public TestListenerQueue(RouteListener listener) {
            this.listener = listener;
        }

        @Override
        public void post(RouteEvent event) {
            listener.event(event);
        }

        @Override
        public void start() {
        }

        @Override
        public void stop() {
        }
    }

}
