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

import com.google.common.collect.Iterators;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.osgi.TestServiceDirectory;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.core.CoreService;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.IdGenerator;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualLink;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Link;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.PortNumber;
import org.onosproject.net.TestDeviceParams;
import org.onosproject.net.intent.FakeIntentManager;
import org.onosproject.net.intent.TestableIntentService;
import org.onosproject.net.link.LinkService;
import org.onosproject.store.service.TestStorageService;

import java.util.Iterator;
import java.util.concurrent.atomic.AtomicLong;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

/**
 * Junit tests for VirtualNetworkLinkService.
 */
public class VirtualNetworkLinkManagerTest extends TestDeviceParams {

    private final String tenantIdValue1 = "TENANT_ID1";

    private VirtualNetworkManager manager;
    private DistributedVirtualNetworkStore virtualNetworkManagerStore;
    private CoreService coreService;
    private TestableIntentService intentService = new FakeIntentManager();
    private TestServiceDirectory testDirectory;

    @Before
    public void setUp() throws Exception {
        virtualNetworkManagerStore = new DistributedVirtualNetworkStore();

        coreService = new VirtualNetworkLinkManagerTest.TestCoreService();
        TestUtils.setField(virtualNetworkManagerStore, "coreService", coreService);
        TestUtils.setField(virtualNetworkManagerStore, "storageService", new TestStorageService());
        virtualNetworkManagerStore.activate();

        manager = new VirtualNetworkManager();
        manager.store = virtualNetworkManagerStore;
        manager.intentService = intentService;
        NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher());

        testDirectory = new TestServiceDirectory();
        TestUtils.setField(manager, "serviceDirectory", testDirectory);

        manager.activate();
    }

    @After
    public void tearDown() {
        virtualNetworkManagerStore.deactivate();
        manager.deactivate();
        NetTestTools.injectEventDispatcher(manager, null);
    }

    /**
     * Tests the getLinks(), getActiveLinks(), getLinkCount(), getLink(),
     * getLinks(ConnectPoint), getDeviceLinks(), getDeviceEgressLinks(), getDeviceIngressLinks(),
     * getEgressLinks(), getIngressLinks() methods.
     */
    @Test
    public void testGetLinks() {

        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        VirtualDevice srcVirtualDevice =
                manager.createVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice =
                manager.createVirtualDevice(virtualNetwork.id(), DID2);
        ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
        manager.createVirtualPort(virtualNetwork.id(), src.deviceId(), src.port(),
                                  new ConnectPoint(srcVirtualDevice.id(), src.port()));

        ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));
        manager.createVirtualPort(virtualNetwork.id(), dst.deviceId(), dst.port(),
                                  new ConnectPoint(dstVirtualDevice.id(), dst.port()));

        VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), src, dst);
        VirtualLink link2 = manager.createVirtualLink(virtualNetwork.id(), dst, src);

        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getLinks() method
        Iterator<Link> it = linkService.getLinks().iterator();
        assertEquals("The link set size did not match.", 2, Iterators.size(it));

        // test the getActiveLinks() method where all links are INACTIVE
        Iterator<Link> it2 = linkService.getActiveLinks().iterator();
        assertEquals("The link set size did not match.", 0, Iterators.size(it2));

        // test the getActiveLinks() method where one link is ACTIVE
        virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE);
        Iterator<Link> it3 = linkService.getActiveLinks().iterator();
        assertEquals("The link set size did not match.", 1, Iterators.size(it3));

        // test the getLinkCount() method
        assertEquals("The link set size did not match.", 2, linkService.getLinkCount());

        // test the getLink() method
        assertEquals("The expect link did not match.", link1,
                     linkService.getLink(src, dst));
        assertEquals("The expect link did not match.", link2,
                     linkService.getLink(dst, src));
        assertNotEquals("The expect link should not have matched.", link1,
                        linkService.getLink(dst, src));

        // test the getLinks(ConnectPoint) method
        assertEquals("The link set size did not match.", 2, linkService.getLinks(src).size());
        assertEquals("The link set size did not match.", 2, linkService.getLinks(dst).size());
        ConnectPoint connectPoint = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(3));
        assertEquals("The link set size did not match.", 0, linkService.getLinks(connectPoint).size());

        // test the getDeviceLinks() method
        assertEquals("The link set size did not match.", 2,
                     linkService.getDeviceLinks(DID1).size());
        assertEquals("The link set size did not match.", 2,
                     linkService.getDeviceLinks(DID2).size());
        assertEquals("The link set size did not match.", 0,
                     linkService.getDeviceLinks(DID3).size());

        // test the getDeviceEgressLinks() method
        assertEquals("The link set size did not match.", 1,
                     linkService.getDeviceEgressLinks(DID1).size());
        assertEquals("The link set size did not match.", 1,
                     linkService.getDeviceEgressLinks(DID2).size());
        assertEquals("The link set size did not match.", 0,
                     linkService.getDeviceEgressLinks(DID3).size());

        // test the getDeviceIngressLinks() method
        assertEquals("The link set size did not match.", 1,
                     linkService.getDeviceIngressLinks(DID1).size());
        assertEquals("The link set size did not match.", 1,
                     linkService.getDeviceIngressLinks(DID2).size());
        assertEquals("The link set size did not match.", 0,
                     linkService.getDeviceIngressLinks(DID3).size());

        // test the getEgressLinks() method
        assertEquals("The link set size did not match.", 1,
                     linkService.getEgressLinks(src).size());
        assertEquals("The link set size did not match.", 1,
                     linkService.getEgressLinks(dst).size());
        assertEquals("The link set size did not match.", 0,
                     linkService.getEgressLinks(connectPoint).size());

        // test the getIngressLinks() method
        assertEquals("The link set size did not match.", 1,
                     linkService.getIngressLinks(src).size());
        assertEquals("The link set size did not match.", 1,
                     linkService.getIngressLinks(dst).size());
        assertEquals("The link set size did not match.", 0,
                     linkService.getIngressLinks(connectPoint).size());
    }

    /**
     * Tests the getLink() method using a null src connect point.
     */
    @Test(expected = NullPointerException.class)
    public void testGetLinkByNullSrc() {

        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        VirtualDevice srcVirtualDevice =
                manager.createVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice =
                manager.createVirtualDevice(virtualNetwork.id(), DID2);
        ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
        ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));
        manager.createVirtualLink(virtualNetwork.id(), src, dst);
        manager.createVirtualLink(virtualNetwork.id(), dst, src);

        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getLink() method with a null src connect point.
        linkService.getLink(null, dst);
    }

    /**
     * Tests the getLink() method using a null dst connect point.
     */
    @Test(expected = NullPointerException.class)
    public void testGetLinkByNullDst() {

        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        VirtualDevice srcVirtualDevice =
                manager.createVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice =
                manager.createVirtualDevice(virtualNetwork.id(), DID2);
        ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
        ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));
        manager.createVirtualLink(virtualNetwork.id(), src, dst);
        manager.createVirtualLink(virtualNetwork.id(), dst, src);

        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getLink() method with a null dst connect point.
        linkService.getLink(src, null);
    }

    /**
     * Tests querying for links using a null device identifier.
     */
    @Test(expected = NullPointerException.class)
    public void testGetDeviceLinksByNullId() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getDeviceLinks() method with a null device identifier.
        linkService.getDeviceLinks(null);
    }

    /**
     * Tests querying for links using a null connect point.
     */
    @Test(expected = NullPointerException.class)
    public void testGetLinksByNullId() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getLinks() method with a null connect point.
        linkService.getLinks(null);
    }

    /**
     * Tests querying for device egress links using a null device identifier.
     */
    @Test(expected = NullPointerException.class)
    public void testGetDeviceEgressLinksByNullId() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getDeviceEgressLinks() method with a null device identifier.
        linkService.getDeviceEgressLinks(null);
    }

    /**
     * Tests querying for device ingress links using a null device identifier.
     */
    @Test(expected = NullPointerException.class)
    public void testGetDeviceIngressLinksByNullId() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getDeviceIngressLinks() method with a null device identifier.
        linkService.getDeviceIngressLinks(null);
    }

    /**
     * Tests querying for egress links using a null connect point.
     */
    @Test(expected = NullPointerException.class)
    public void testGetEgressLinksByNullId() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getEgressLinks() method with a null connect point.
        linkService.getEgressLinks(null);
    }

    /**
     * Tests querying for ingress links using a null connect point.
     */
    @Test(expected = NullPointerException.class)
    public void testGetIngressLinksByNullId() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        LinkService linkService = manager.get(virtualNetwork.id(), LinkService.class);

        // test the getIngressLinks() method with a null connect point.
        linkService.getIngressLinks(null);
    }

    /**
     * Core service test class.
     */
    private class TestCoreService extends CoreServiceAdapter {

        @Override
        public IdGenerator getIdGenerator(String topic) {
            return new IdGenerator() {
                private AtomicLong counter = new AtomicLong(0);

                @Override
                public long getNewId() {
                    return counter.getAndIncrement();
                }
            };
        }
    }
}
