/*
 * 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.virtual.impl.provider;

import com.google.common.collect.ImmutableSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ethernet;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.net.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminServiceAdapter;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProviderService;
import org.onosproject.incubator.net.virtual.provider.VirtualPacketProvider;
import org.onosproject.incubator.net.virtual.provider.VirtualPacketProviderService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.DefaultPacketContext;
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 org.onosproject.net.provider.ProviderId;

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

import static org.junit.Assert.assertEquals;

public class DefaultVirtualPacketProviderTest {
    private static final String SRC_MAC_ADDR = "00:00:00:00:00:00";
    private static final String DST_MAC_ADDR = "00:00:00:00:00:01";
    private static final ProviderId PID = new ProviderId("of", "foo");

    private static final DeviceId DID1 = DeviceId.deviceId("of:001");
    private static final DeviceId DID2 = DeviceId.deviceId("of:002");
    private static final PortNumber PORT_NUM1 = PortNumber.portNumber(1);
    private static final PortNumber PORT_NUM2 = PortNumber.portNumber(2);
    private static final PortNumber PORT_NUM3 = PortNumber.portNumber(3);
    private static final PortNumber PORT_NUM4 = PortNumber.portNumber(4);

    private static final DefaultAnnotations ANNOTATIONS =
            DefaultAnnotations.builder().set("foo", "bar").build();

    private static final Device DEV1 =
            new DefaultDevice(PID, DID1, Device.Type.SWITCH, "", "", "", "", null);
    private static final Device DEV2 =
            new DefaultDevice(PID, DID2, Device.Type.SWITCH, "", "", "", "", null);
    private static final Port PORT11 =
            new DefaultPort(DEV1, PORT_NUM1, true, ANNOTATIONS);
    private static final Port PORT12 =
            new DefaultPort(DEV1, PORT_NUM2, true, ANNOTATIONS);
    private static final Port PORT21 =
            new DefaultPort(DEV2, PORT_NUM3, true, ANNOTATIONS);
    private static final Port PORT22 =
            new DefaultPort(DEV2, PORT_NUM4, true, ANNOTATIONS);

    private static final ConnectPoint CP11 = new ConnectPoint(DID1, PORT_NUM1);
    private static final ConnectPoint CP12 = new ConnectPoint(DID1, PORT_NUM2);
    private static final ConnectPoint CP21 = new ConnectPoint(DID2, PORT_NUM3);
    private static final ConnectPoint CP22 = new ConnectPoint(DID2, PORT_NUM4);
    private static final Link LINK1 = DefaultLink.builder()
            .src(CP12).dst(CP21).providerId(PID).type(Link.Type.DIRECT).build();

    private static final TenantId TENANT_ID = TenantId.tenantId("1");
    private static final NetworkId VNET_ID = NetworkId.networkId(1);
    private static final DeviceId VDID = DeviceId.deviceId("of:100");

    private static final PortNumber VPORT_NUM1 = PortNumber.portNumber(10);
    private static final PortNumber VPORT_NUM2 = PortNumber.portNumber(11);

    private static final VirtualNetwork VNET = new DefaultVirtualNetwork(
            VNET_ID, TenantId.tenantId("t1"));
    private static final VirtualDevice VDEV =
            new DefaultVirtualDevice(VNET_ID, VDID);
    private static final VirtualPort VPORT1 =
            new DefaultVirtualPort(VNET_ID, VDEV, VPORT_NUM1, CP11);
    private static final VirtualPort VPORT2 =
            new DefaultVirtualPort(VNET_ID, VDEV, VPORT_NUM2, CP22);
    private static final ConnectPoint VCP11 = new ConnectPoint(VDID, VPORT_NUM1);
    private static final ConnectPoint VCP12 = new ConnectPoint(VDID, VPORT_NUM2);

    protected DefaultVirtualPacketProvider virtualProvider;
    protected TestPacketService testPacketService;
    protected TestVirtualPacketProviderService providerService;

    private VirtualProviderManager providerManager;

    private ApplicationId vAppId;

    @Before
    public void setUp() {
        virtualProvider = new DefaultVirtualPacketProvider();

        virtualProvider.coreService = new CoreServiceAdapter();
        virtualProvider.vnaService =
                new TestVirtualNetworkAdminService();

        providerService = new TestVirtualPacketProviderService();

        testPacketService = new TestPacketService();
        virtualProvider.packetService = testPacketService;

        providerManager = new VirtualProviderManager();
        virtualProvider.providerRegistryService = providerManager;
        providerManager.registerProviderService(VNET_ID, providerService);

        virtualProvider.activate();
        vAppId = new TestApplicationId(0, "Virtual App");

        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchEthType(Ethernet.TYPE_IPV4);

        virtualProvider.startPacketHandling();
    }

    @After
    public void tearDown() {
        virtualProvider.deactivate();
        virtualProvider.coreService = null;
        virtualProvider.vnaService = null;
    }


    /** Test the virtual outbound packet is delivered to a proper (physical)
     *  device.
     */
    @Test
    public void devirtualizePacket() {
        TrafficTreatment tr = DefaultTrafficTreatment.builder()
                .setOutput(VPORT_NUM1).build();
        ByteBuffer data = ByteBuffer.wrap("abc".getBytes());

        OutboundPacket vOutPacket = new DefaultOutboundPacket(VDID, tr, data);

        virtualProvider.emit(VNET_ID, vOutPacket);

        assertEquals("The count should be 1", 1,
                     testPacketService.getRequestedPacketCount());

        OutboundPacket pOutPacket = testPacketService.getRequestedPacket(0);

        assertEquals("The packet should be requested on DEV1", DID1,
                     pOutPacket.sendThrough());

        PortNumber outPort = pOutPacket.treatment()
                .allInstructions()
                .stream()
                .filter(i -> i.type() == Instruction.Type.OUTPUT)
                .map(i -> (Instructions.OutputInstruction) i)
                .map(i -> i.port())
                .findFirst().get();
        assertEquals("The packet should be out at PORT1 of DEV1", PORT_NUM1,
                     outPort);
    }

    /** Test the physical packet context is delivered to a proper (physical)
     *  virtual network and device.
     */
    @Test
    public void virtualizePacket() {
        Ethernet eth = new Ethernet();
        eth.setSourceMACAddress(SRC_MAC_ADDR);
        eth.setDestinationMACAddress(DST_MAC_ADDR);
        eth.setVlanID((short) 1);
        eth.setPayload(null);

        InboundPacket pInPacket =
                new DefaultInboundPacket(CP22, eth,
                                         ByteBuffer.wrap(eth.serialize()));

        PacketContext pContext =
                new TestPacketContext(System.nanoTime(), pInPacket, null, false);

        testPacketService.sendTestPacketContext(pContext);

        PacketContext vContext = providerService.getRequestedPacketContext(0);
        InboundPacket vInPacket = vContext.inPacket();

        assertEquals("the packet should be received from VCP12",
                     VCP12, vInPacket.receivedFrom());

        assertEquals("VLAN tag should be excludede", VlanId.UNTAGGED,
                     vInPacket.parsed().getVlanID());
    }

    private class TestPacketContext extends DefaultPacketContext {

        /**
         * Creates a new packet context.
         *
         * @param time   creation time
         * @param inPkt  inbound packet
         * @param outPkt outbound packet
         * @param block  whether the context is blocked or not
         */
        protected TestPacketContext(long time, InboundPacket inPkt,
                                    OutboundPacket outPkt, boolean block) {
            super(time, inPkt, outPkt, block);
        }

        @Override
        public void send() {

        }
    }

    private static class TestApplicationId extends DefaultApplicationId {
        public TestApplicationId(int id, String name) {
            super(id, name);
        }
    }

    private static class TestVirtualNetworkAdminService
            extends VirtualNetworkAdminServiceAdapter {

        @Override
        public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
            return ImmutableSet.of(VNET);
        }

        @Override
        public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
            return ImmutableSet.of(VDEV);
        }

        @Override
        public Set<VirtualPort> getVirtualPorts(NetworkId networkId,
                                                DeviceId deviceId) {
            return ImmutableSet.of(VPORT1, VPORT2);
        }

        @Override
        public Set<TenantId> getTenantIds() {
            return ImmutableSet.of(TENANT_ID);
        }

    }

    private static class TestVirtualPacketProviderService
            extends AbstractVirtualProviderService<VirtualPacketProvider>
            implements VirtualPacketProviderService {

        static List<PacketContext> requestedContext = new LinkedList();
        static List<NetworkId> requestedNetworkId = new LinkedList();

        @Override
        public VirtualPacketProvider provider() {
            return null;
        }

        PacketContext getRequestedPacketContext(int index) {
            return requestedContext.get(index);
        }

        @Override
        public void processPacket(PacketContext context) {
            requestedContext.add(context);
        }
    }

    private static class TestPacketService extends PacketServiceAdapter {
        static List<OutboundPacket> requestedPacket = new LinkedList();
        static PacketProcessor processor = null;

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

        @Override
        public void emit(OutboundPacket packet) {
            requestedPacket.add(packet);
        }

        OutboundPacket getRequestedPacket(int index) {
            return requestedPacket.get(index);
        }

        int getRequestedPacketCount() {
            return requestedPacket.size();
        }

        void sendTestPacketContext(PacketContext context) {
            processor.process(context);
        }
    }
}
