/*
 * Copyright 2016 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.provider.netcfglinks;

import java.nio.ByteBuffer;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ChassisId;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ONOSLLDP;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.LinkKey;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.config.basics.BasicLinkConfig;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProviderRegistryAdapter;
import org.onosproject.net.link.LinkProviderServiceAdapter;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketServiceAdapter;

import com.google.common.collect.ImmutableList;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

/**
 * Unit tests for the network config links provider.
 */
public class NetworkConfigLinksProviderTest {

    private NetworkConfigLinksProvider provider;

    private PacketProcessor testProcessor;
    private LinkProviderServiceAdapter providerService;
    private NetworkConfigListener configListener;
    private final TestNetworkConfigRegistry configRegistry =
            new TestNetworkConfigRegistry();

    static Device dev1 = NetTestTools.device("sw1");
    static Device dev2 = NetTestTools.device("sw2");
    static Device dev3 = NetTestTools.device("sw3");
    static PortNumber portNumber1 = PortNumber.portNumber(1);
    static PortNumber portNumber2 = PortNumber.portNumber(2);
    static PortNumber portNumber3 = PortNumber.portNumber(3);
    static ConnectPoint src = new ConnectPoint(dev1.id(), portNumber2);
    static ConnectPoint dst = new ConnectPoint(dev2.id(), portNumber2);

    static DeviceListener deviceListener;

    /**
     * Test device manager. Returns a known set of devices and ports.
     */
    static class TestDeviceManager extends DeviceServiceAdapter {

        @Override
        public Iterable<Device> getAvailableDevices() {
            return ImmutableList.of(dev1, dev2);
        }

        @Override
        public List<Port> getPorts(DeviceId deviceId) {
            return ImmutableList.of(new DefaultPort(dev1, portNumber1, true),
                                    new DefaultPort(dev2, portNumber2, true));
        }

        @Override
        public void addListener(DeviceListener listener) {
            deviceListener = listener;
        }
    }

    /**
     * Test mastership service. All devices owned by the local node for testing.
     */
    static class TestMastershipService extends MastershipServiceAdapter {
        @Override
        public boolean isLocalMaster(DeviceId deviceId) {
            return true;
        }
    }

    /**
     * Test packet context for generation of LLDP packets.
     */
    private class TestPacketContext implements PacketContext {

        protected ConnectPoint src;
        protected ConnectPoint dst;
        protected boolean blocked = false;

        public TestPacketContext(ConnectPoint src, ConnectPoint dst) {
            this.src = src;
            this.dst = dst;
        }

        @Override
        public long time() {
            return 0;
        }

        @Override
        public InboundPacket inPacket() {
            ONOSLLDP lldp = ONOSLLDP.onosLLDP(src.deviceId().toString(),
                                              new ChassisId(),
                                              (int) src.port().toLong());

            Ethernet ethPacket = new Ethernet();
            ethPacket.setEtherType(Ethernet.TYPE_LLDP);
            ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_NICIRA);
            ethPacket.setPayload(lldp);
            ethPacket.setPad(true);

            ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11");

            return new DefaultInboundPacket(dst, ethPacket,
                                            ByteBuffer.wrap(ethPacket.serialize()));

        }

        @Override
        public OutboundPacket outPacket() {
            return null;
        }

        @Override
        public TrafficTreatment.Builder treatmentBuilder() {
            return null;
        }

        @Override
        public void send() {

        }

        @Override
        public boolean block() {
            blocked = true;
            return true;
        }

        @Override
        public boolean isHandled() {
            return blocked;
        }

    }

    /**
     * Test packet service for capturing the packet processor from the service
     * under test.
     */
    private class TestPacketService extends PacketServiceAdapter {
        @Override
        public void addProcessor(PacketProcessor processor, int priority) {
            testProcessor = processor;
        }
    }

    /**
     * Test network config registry. Captures the network config listener from
     * the service under test.
     */
    private final class TestNetworkConfigRegistry
            extends NetworkConfigRegistryAdapter {


        @Override
        public void addListener(NetworkConfigListener listener) {
            configListener = listener;
        }
    }

    /**
     * Sets up a network config links provider under test and the services
     * required to run it.
     */
    @Before
    public void setUp() {
        provider = new NetworkConfigLinksProvider();

        provider.coreService = new CoreServiceAdapter();
        provider.packetService = new PacketServiceAdapter();
        LinkProviderRegistryAdapter linkRegistry =
                new LinkProviderRegistryAdapter();
        provider.providerRegistry = linkRegistry;
        provider.deviceService = new TestDeviceManager();
        provider.masterService = new TestMastershipService();
        provider.packetService = new TestPacketService();
        provider.netCfgService = configRegistry;

        provider.activate();

        providerService = linkRegistry.registeredProvider();
    }

    /**
     * Tears down the provider under test.
     */
    @After
    public void tearDown() {
        provider.deactivate();
    }

    /**
     * Tests that a network config links provider object can be created.
     * The actual creation is done in the setUp() method.
     */
    @Test
    public void testCreation() {
        assertThat(provider, notNullValue());
        assertThat(provider.configuredLinks, empty());
    }

    /**
     * Tests loading of devices from the device manager.
     */
    @Test
    public void testDeviceLoad() {
        assertThat(provider, notNullValue());
        assertThat(provider.discoverers.entrySet(), hasSize(2));
    }

    /**
     * Tests discovery of a link that is not expected in the configuration.
     */
    @Test
    public void testNotConfiguredLink() {
        PacketContext pktCtx = new TestPacketContext(src, dst);

        testProcessor.process(pktCtx);

        assertThat(providerService.discoveredLinks().entrySet(), hasSize(1));
        DeviceId destination = providerService.discoveredLinks().get(dev1.id());
        assertThat(destination, notNullValue());
        LinkKey key = LinkKey.linkKey(src, dst);
        LinkDescription linkDescription = providerService
                .discoveredLinkDescriptions().get(key);
        assertThat(linkDescription, notNullValue());
        assertThat(linkDescription.isExpected(), is(false));
    }

    /**
     * Tests discovery of an expected link.
     */
    @Test
    public void testConfiguredLink() {
        LinkKey key = LinkKey.linkKey(src, dst);
        configListener.event(new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED,
                                                    key,
                                                    BasicLinkConfig.class));

        PacketContext pktCtx = new TestPacketContext(src, dst);

        testProcessor.process(pktCtx);

        assertThat(providerService.discoveredLinks().entrySet(), hasSize(1));
        DeviceId destination = providerService.discoveredLinks().get(dev1.id());
        assertThat(destination, notNullValue());
        LinkDescription linkDescription = providerService
                .discoveredLinkDescriptions().get(key);
        assertThat(linkDescription, notNullValue());
        assertThat(linkDescription.isExpected(), is(true));
    }

    /**
     * Tests removal of a link from the configuration.
     */
    @Test
    public void testRemoveLink() {
        LinkKey key = LinkKey.linkKey(src, dst);
        configListener.event(new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED,
                                                    key,
                                                    BasicLinkConfig.class));

        assertThat(provider.configuredLinks, hasSize(1));

        configListener.event(new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_REMOVED,
                                                    key,
                                                    BasicLinkConfig.class));
        assertThat(provider.configuredLinks, hasSize(0));
    }

    /**
     * Tests adding a new device via an event.
     */
    @Test
    public void testAddDevice() {
        deviceListener.event(new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, dev3));
        assertThat(provider.discoverers.entrySet(), hasSize(3));
    }

    /**
     * Tests adding a new port via an event.
     */
    @Test
    public void testAddPort() {
        deviceListener.event(new DeviceEvent(DeviceEvent.Type.PORT_ADDED, dev3,
                                             new DefaultPort(dev3, portNumber3, true)));
        assertThat(provider.discoverers.entrySet(), hasSize(3));
    }

    /**
     * Tests removing a device via an event.
     */
    @Test
    public void testRemoveDevice() {
        assertThat(provider.discoverers.entrySet(), hasSize(2));
        deviceListener.event(new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, dev3));
        assertThat(provider.discoverers.entrySet(), hasSize(3));
        deviceListener.event(new DeviceEvent(DeviceEvent.Type.DEVICE_REMOVED, dev3));
        assertThat(provider.discoverers.entrySet(), hasSize(2));
    }

    /**
     * Tests removing a port via an event.
     */
    @Test
    public void testRemovePort() {
        assertThat(provider.discoverers.entrySet(), hasSize(2));
        deviceListener.event(new DeviceEvent(DeviceEvent.Type.PORT_ADDED, dev3,
                                             new DefaultPort(dev3, portNumber3, true)));
        assertThat(provider.discoverers.entrySet(), hasSize(3));
        deviceListener.event(new DeviceEvent(DeviceEvent.Type.PORT_REMOVED, dev3,
                                             new DefaultPort(dev3, portNumber3, true)));
        assertThat(provider.discoverers.entrySet(), hasSize(3));
    }

    /**
     * Tests changing device availability via an event.
     */
    @Test
    public void testDeviceAvailabilityChanged() {
        assertThat(providerService.vanishedDpid(), hasSize(0));

        deviceListener.event(
                new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, dev3));
        assertThat(providerService.vanishedDpid(), hasSize(0));

        deviceListener.event(
                new DeviceEvent(DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED, dev3));
        assertThat(providerService.vanishedDpid(), hasSize(1));
    }
}
