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

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.behaviour.LinkDiscovery;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

import java.util.Dictionary;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.stream.Collectors;

import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.concurrent.Executors.newScheduledThreadPool;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.onlab.util.Tools.get;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Link provider capable of polling the environment using the device driver
 * {@link LinkDiscovery} behaviour.
 */
@Component(immediate = true)
public class LinkDiscoveryProvider extends AbstractProvider
        implements LinkProvider {

    protected static final String APP_NAME = "org.onosproject.linkdiscovery";
    protected static final String SCHEME_NAME = "linkdiscovery";
    private static final String LINK_PROVIDER_PACKAGE = "org.onosproject.provider.linkdiscovery";
    private final Logger log = getLogger(getClass());
    private static final int DEFAULT_POLL_DELAY_SECONDS = 20;
    @Property(name = "linkPollDelaySeconds", intValue = DEFAULT_POLL_DELAY_SECONDS,
            label = "Initial delay (in seconds) for polling link discovery")
    protected static int linkPollDelaySeconds = DEFAULT_POLL_DELAY_SECONDS;
    private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 10;
    @Property(name = "linkPollFrequencySeconds", intValue = DEFAULT_POLL_FREQUENCY_SECONDS,
            label = "Frequency (in seconds) for polling link discovery")
    protected static int linkPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS;


    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkProviderRegistry providerRegistry;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkService linkService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService mastershipService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;
    protected ScheduledExecutorService executor =
            newScheduledThreadPool(2, groupedThreads("onos/netconf-link",
                                                     "discovery-%d"));
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ComponentConfigService cfgService;

    protected LinkProviderService providerService;
    private InternalDeviceListener deviceListener = new InternalDeviceListener();
    private ApplicationId appId;
    private ScheduledFuture<?> scheduledTask;

    /**
     * Creates a provider with the supplied identifier.
     */
    public LinkDiscoveryProvider() {
        super(new ProviderId(SCHEME_NAME, LINK_PROVIDER_PACKAGE));
    }

    @Activate
    public void activate(ComponentContext context) {
        providerService = providerRegistry.register(this);
        appId = coreService.registerApplication(APP_NAME);
        deviceService.addListener(deviceListener);
        cfgService.registerProperties(getClass());

        if (context == null) {
            linkPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS;
            log.info("No component configuration");
        } else {
            Dictionary<?, ?> properties = context.getProperties();
            linkPollFrequencySeconds =
                    getNewPollFrequency(properties, linkPollFrequencySeconds);
        }
        scheduledTask = schedulePolling();
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        cfgService.unregisterProperties(getClass(), false);
        deviceService.removeListener(deviceListener);
        providerRegistry.unregister(this);
        providerService = null;
        scheduledTask.cancel(true);
        executor.shutdown();
        log.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        if (context == null) {
            log.info("No component configuration");
            return;
        } else {
            Dictionary<?, ?> properties = context.getProperties();

            int newPollFrequency = getNewPollFrequency(properties, linkPollFrequencySeconds);
            int newPollDelay = getNewPollDealy(properties, linkPollDelaySeconds);
            if (newPollFrequency != linkPollFrequencySeconds ||
                    newPollDelay != linkPollDelaySeconds) {
                linkPollFrequencySeconds = newPollFrequency;
                linkPollDelaySeconds = newPollDelay;
                //stops the old scheduled task
                scheduledTask.cancel(true);
                //schedules new task at the new polling rate
                scheduledTask = schedulePolling();
            }
        }
        log.info("Modified");
    }

    private int getNewPollFrequency(Dictionary<?, ?> properties, int pollFrequency) {
        int newPollFrequency;
        try {
            String s = get(properties, "linkPollFrequencySeconds");
            newPollFrequency = isNullOrEmpty(s) ? pollFrequency : Integer.parseInt(s.trim());
        } catch (NumberFormatException | ClassCastException e) {
            newPollFrequency = DEFAULT_POLL_FREQUENCY_SECONDS;
        }
        return newPollFrequency;
    }

    private int getNewPollDealy(Dictionary<?, ?> properties, int pollDelay) {
        int newPollFrequency;
        try {
            String s = get(properties, "linkPollDelaySeconds");
            newPollFrequency = isNullOrEmpty(s) ? pollDelay : Integer.parseInt(s.trim());
        } catch (NumberFormatException | ClassCastException e) {
            newPollFrequency = DEFAULT_POLL_DELAY_SECONDS;
        }
        return newPollFrequency;
    }

    private ScheduledFuture schedulePolling() {
        return executor.scheduleAtFixedRate(this::discoverLinksTasks,
                                            linkPollDelaySeconds,
                                            linkPollFrequencySeconds,
                                            SECONDS);
    }

    private void discoverLinksTasks() {
        deviceService.getAvailableDevices().forEach(device -> {
            if (isSupported(device)) {
                evaluateLinks(device.id(), device.as(LinkDiscovery.class).getLinks());
            }
        });
    }

    private void evaluateLinks(DeviceId deviceId, Set<LinkDescription> discoveredLinksDesc) {
        if (discoveredLinksDesc == null) {
            return;
        }

        //The provider will get only existing links related to LinkDiscovery
        Set<Link> storedLinks = linkService.getDeviceEgressLinks(deviceId)
                .stream()
                .filter(link -> {
                    String value = link.annotations().value(AnnotationKeys.PROTOCOL);
                    if (value != null && value.equals(SCHEME_NAME.toUpperCase())) {
                        return true;
                    }
                    return false;
                })
                .collect(Collectors.toSet());

        //Convert Link to LinkDescription for comparison
        Set<LinkDescription> storedLinkDescs = new HashSet<>();
        storedLinks.forEach(link -> storedLinkDescs
                .add(new DefaultLinkDescription(
                        link.src(), link.dst(), link.type(), link.isExpected(),
                        DefaultAnnotations.builder().putAll(link.annotations()).build())));
        log.debug("Current stored links provider related {}", storedLinks);

        //Add the correct annotation for comparison
        Set<LinkDescription> discoveredLinkDescsAnn = new HashSet<>();

        discoveredLinksDesc.forEach(linkDesc -> discoveredLinkDescsAnn
                .add(new DefaultLinkDescription(
                        linkDesc.src(), linkDesc.dst(), linkDesc.type(), false,
                        DefaultAnnotations.builder().putAll(linkDesc.annotations())
                                .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
                                .build())));

        Set<LinkDescription> linkDescsToBeRemoved = new HashSet<>(storedLinkDescs);
        linkDescsToBeRemoved.removeAll(discoveredLinkDescsAnn);
        log.debug("Links to be removed {}", linkDescsToBeRemoved);
        linkDescsToBeRemoved.forEach(linkDesc ->
                                             providerService.linkVanished(linkDesc));

        Set<LinkDescription> linksToBeAdded = new HashSet<>(discoveredLinkDescsAnn);
        linksToBeAdded.removeAll(storedLinkDescs);
        log.debug("Links to be added {}", linksToBeAdded);
        linksToBeAdded.forEach(linkDesc -> providerService.linkDetected(linkDesc)
        );
    }

    protected boolean isSupported(Device device) {
        boolean supported = mastershipService.isLocalMaster(device.id())
                && device.is(LinkDiscovery.class);
        if (!supported) {
            log.debug("Device {} does not support LinkDiscovery", device);
        }
        return supported;
    }

    /**
     * Listener for core device events.
     */
    private class InternalDeviceListener implements DeviceListener {
        @Override
        public void event(DeviceEvent event) {
            if ((event.type() == DeviceEvent.Type.DEVICE_ADDED)) {
                executor.execute(() -> event.subject().as(LinkDiscovery.class).getLinks()
                        .forEach(linkDesc -> {
                            providerService.linkDetected(new DefaultLinkDescription(
                                    linkDesc.src(), linkDesc.dst(), linkDesc.type(), false,
                                    DefaultAnnotations.builder()
                                            .putAll(linkDesc.annotations())
                                            .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
                                            .build()));
                        }));
            }
        }

        @Override
        public boolean isRelevant(DeviceEvent event) {
            return isSupported(event.subject());
        }
    }
}
