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

import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.osgi.ComponentContextAdapter;
import org.onlab.packet.ChassisId;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.mastership.MastershipService;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.AbstractProjectableModel;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Annotations;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.LinkDiscovery;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.driver.Behaviour;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverAdapter;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverServiceAdapter;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProviderRegistryAdapter;
import org.onosproject.net.link.LinkProviderServiceAdapter;
import org.onosproject.net.link.LinkServiceAdapter;
import org.onosproject.net.provider.ProviderId;

import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import static org.onlab.junit.TestTools.assertAfter;
import static org.onosproject.provider.linkdiscovery.impl.LinkDiscoveryProvider.APP_NAME;
import static org.onosproject.provider.linkdiscovery.impl.LinkDiscoveryProvider.SCHEME_NAME;

/**
 * Test for polling mechanism of the NetconfLinkProvider.
 */
public class LinkDiscoveryProviderTest {

    private static final ComponentContextAdapter CONTEXT =
            new ComponentContextAdapter() {
                @Override
                public Dictionary getProperties() {
                    Hashtable<String, Integer> props = new Hashtable<>();
                    props.put("linkPollFrequencySeconds", 2);
                    props.put("linkPollDelaySeconds", 1);
                    props.put("linkDiscoveryTimeoutSeconds", 1);
                    return props;
                }
            };
    // Network Mocks
    private static final DeviceId DEVICE_ID_1 = DeviceId.deviceId("netconf:1.1.1.1");
    private static final DeviceId DEVICE_ID_2 = DeviceId.deviceId("netconf:1.1.1.2");
    private static final ConnectPoint CP11 = new ConnectPoint(DEVICE_ID_1, PortNumber.portNumber(1));
    private static final ConnectPoint CP12 = new ConnectPoint(DEVICE_ID_1, PortNumber.portNumber(2));
    private static final ConnectPoint CP13 = new ConnectPoint(DEVICE_ID_1, PortNumber.portNumber(3));
    private static final ConnectPoint CP14 = new ConnectPoint(DEVICE_ID_1, PortNumber.portNumber(4));
    private static final ConnectPoint CP21 = new ConnectPoint(DEVICE_ID_2, PortNumber.portNumber(1));
    private static final ConnectPoint CP22 = new ConnectPoint(DEVICE_ID_2, PortNumber.portNumber(2));
    private static final ConnectPoint CP23 = new ConnectPoint(DEVICE_ID_2, PortNumber.portNumber(3));
    private static final ConnectPoint CP24 = new ConnectPoint(DEVICE_ID_2, PortNumber.portNumber(4));
    private static final DefaultAnnotations DEVICE_ANNOTATIONS = DefaultAnnotations.builder()
            .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()).build();
    private static final DefaultAnnotations LINK_ANNOTATIONS = DefaultAnnotations.builder()
            .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()).build();
    private static final LinkKey LINKKEY1 = LinkKey.linkKey(CP11, CP21);
    private static final LinkDescription LINK1 = new DefaultLinkDescription(CP11, CP21,
                                                                            Link.Type.DIRECT,
                                                                            LINK_ANNOTATIONS);
    private static final LinkKey LINKKEY2 = LinkKey.linkKey(CP12, CP22);
    private static final LinkDescription LINK2 = new DefaultLinkDescription(CP12, CP22,
                                                                            Link.Type.DIRECT,
                                                                            LINK_ANNOTATIONS);
    private static final LinkKey LINKKEY3 = LinkKey.linkKey(CP13, CP23);
    private static final LinkDescription LINK3 = new DefaultLinkDescription(CP13, CP23,
                                                                            Link.Type.DIRECT,
                                                                            DefaultAnnotations.builder()
                                                                                    .build());
    private static final LinkKey LINKKEY4 = LinkKey.linkKey(CP14, CP24);
    private static final LinkDescription LINK4 = new DefaultLinkDescription(CP14, CP24,
                                                                            Link.Type.DIRECT,
                                                                            DefaultAnnotations.builder().build());
    //Service Mocks
    private final MockDeviceService deviceService = new MockDeviceService();
    private final LinkProviderRegistryAdapter linkRegistry = new LinkProviderRegistryAdapter();
    private final MastershipService mastershipService = new MockMastershipService();
    private final MockLinkService linkService = new MockLinkService();
    private final Driver driver = new MockDriver();
    //Provider related classes
    private LinkProviderServiceAdapter providerService;
    private CoreService coreService;
    private LinkDiscoveryProvider provider = new LinkDiscoveryProvider();
    private final Device device1 = new MockDevice(provider.id(), DEVICE_ID_1, Device.Type.SWITCH,
                                                  "foo.inc", "0", "0", "0", new ChassisId(),
                                                  DEVICE_ANNOTATIONS);
    private Set<DeviceListener> deviceListeners = new HashSet<>();
    private ApplicationId appId =
            new DefaultApplicationId(100, APP_NAME);
    private TestLink testLink = new TestLink();

    @Before
    public void setUp() {
        coreService = createMock(CoreService.class);
        expect(coreService.registerApplication(appId.name()))
                .andReturn(appId).anyTimes();
        replay(coreService);
        provider.coreService = coreService;
        provider.providerRegistry = linkRegistry;
        provider.deviceService = deviceService;
        provider.mastershipService = mastershipService;
        provider.linkService = linkService;
        provider.cfgService = new ComponentConfigAdapter();
        AbstractProjectableModel.setDriverService(null, new DriverServiceAdapter());
        provider.activate(null);
        providerService = linkRegistry.registeredProvider();
    }

    @Test
    public void activate() throws Exception {
        assertTrue("Provider should be registered", linkRegistry.getProviders().contains(provider.id()));
        assertEquals("Device service should be registered", provider.deviceService, deviceService);
        assertEquals("Device listener should be added", 1, deviceListeners.size());
        assertNotNull("Registration expected", providerService);
        assertEquals("Incorrect  provider", provider, providerService.provider());
        assertFalse("Executor should be running", provider.executor.isShutdown());
        assertFalse("Executor should be running", provider.executor.isTerminated());
        assertEquals("Incorrect polling frequency, should be default", 10,
                     provider.linkPollFrequencySeconds);
        assertEquals("Incorrect polling delay , should be default", 20,
                     provider.linkPollDelaySeconds);
        assertEquals("Incorrect polling discovery delay , should be default", 300,
                     provider.linkDiscoveryTimeoutSeconds);
    }

    @Test
    public void modified() throws Exception {
        provider.modified(CONTEXT);
        assertEquals("Incorrect polling frequency, should be default", 2,
                     provider.linkPollFrequencySeconds);
        assertEquals("Incorrect polling delay , should be default", 1,
                     provider.linkPollDelaySeconds);
        assertEquals("Incorrect polling discovery delay , should be default", 1,
                     provider.linkDiscoveryTimeoutSeconds);

    }


    @Test
    public void deactivate() throws Exception {
        provider.deactivate();
        assertEquals("Device listener should be removed", 0, deviceListeners.size());
        assertFalse("Provider should not be registered", linkRegistry.getProviders().contains(provider.id()));
        assertTrue(provider.executor.isShutdown());
        assertNull(provider.providerService);
    }


    @Test
    @Ignore("FIXME: fails intermittently; suspecting insufficient time and race condition")
    public void linksTestForStoredDevice() {
        provider.modified(CONTEXT);
        providerService.discoveredLinkDescriptions().put(LINKKEY1, LINK1);
        providerService.discoveredLinkDescriptions().put(LINKKEY2, LINK2);
        providerService.discoveredLinkDescriptions().put(LINKKEY4, LINK4);
        testLink.addLinkDesc(LINK2);
        testLink.addLinkDesc(LINK3);
        assertAfter(1100, () -> {
            assertEquals("Total number of link must be 3", 3, providerService.discoveredLinkDescriptions().size());
            assertFalse("Link1 should be removed",
                        providerService.discoveredLinkDescriptions().containsKey(LINKKEY1));
            assertTrue("Link2 should be present",
                       providerService.discoveredLinkDescriptions().containsKey(LINKKEY2));
            assertTrue("Link3 should be added",
                       providerService.discoveredLinkDescriptions().containsKey(LINKKEY3));
            assertEquals("Link3 should be annotated", SCHEME_NAME.toUpperCase(),
                         providerService.discoveredLinkDescriptions()
                    .get(LINKKEY3).annotations().value(AnnotationKeys.PROTOCOL));
            assertTrue("Link4 should be present because it is not related to the LinkDiscovery",
                       providerService.discoveredLinkDescriptions().containsKey(LINKKEY4));

        });
        clear();
    }

    private void clear() {
        testLink.clearLinkDesc();
        providerService.discoveredLinkDescriptions().clear();
        providerService.discoveredLinks().clear();
    }

    private class MockDeviceService extends DeviceServiceAdapter {

        @Override
        public Iterable<Device> getAvailableDevices() {
            return ImmutableSet.of(device1);
        }

        @Override
        public Device getDevice(DeviceId deviceId) {
            return device1;
        }

        @Override
        public void addListener(DeviceListener listener) {
            deviceListeners.add(listener);
        }

        @Override
        public void removeListener(DeviceListener listener) {
            deviceListeners.remove(listener);
        }
    }

    private class MockMastershipService extends MastershipServiceAdapter {

        @Override
        public boolean isLocalMaster(DeviceId deviceId) {
            return true;
        }
    }

    private class MockLinkService extends LinkServiceAdapter {
        @Override
        public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
            Set<Link> links = new HashSet<>();
            providerService.discoveredLinkDescriptions().values()
                    .forEach(x -> links.add(DefaultLink.builder()
                                                    .providerId(provider.id())
                                                    .src(x.src())
                                                    .dst(x.dst())
                                                    .type(x.type())
                                                    .isExpected(x.isExpected())
                                                    .annotations(x.annotations()).build()));
            return ImmutableSet.copyOf(links);
        }
    }

    private class MockDevice extends DefaultDevice {

        public MockDevice(ProviderId providerId, DeviceId id, Type type,
                          String manufacturer, String hwVersion, String swVersion,
                          String serialNumber, ChassisId chassisId, Annotations... annotations) {
            super(providerId, id, type, manufacturer, hwVersion, swVersion, serialNumber,
                  chassisId, annotations);
        }

        @Override
        protected Driver locateDriver() {
            return driver;
        }

        @Override
        public Driver driver() {
            return driver;
        }
    }

    private class MockDriver extends DriverAdapter {
        @Override
        public <T extends Behaviour> T createBehaviour(DriverHandler handler, Class<T> behaviourClass) {

            return (T) testLink;
        }
    }

    private class TestLink extends AbstractHandlerBehaviour implements LinkDiscovery {
        Set<LinkDescription> linkDescriptions = new HashSet<>();

        @Override
        public Set<LinkDescription> getLinks() {
            return ImmutableSet.copyOf(linkDescriptions);
        }

        private void addLinkDesc(LinkDescription link) {
            linkDescriptions.add(link);
        }

        private void clearLinkDesc() {
            linkDescriptions.clear();
        }

    }
}
