/*
 * 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 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.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
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)
    protected LinkProviderRegistry providerRegistry;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected CoreService coreService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LinkService linkService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected MastershipService mastershipService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected DeviceService deviceService;
    protected ScheduledExecutorService executor =
            newScheduledThreadPool(2, groupedThreads("onos/netconf-link",
                                                     "discovery-%d"));
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    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.getDeviceIngressLinks(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());
        }
    }
}
