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

import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

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.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ONOSLLDP;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.basics.BasicLinkConfig;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.provider.lldpcommon.LinkDiscoveryContext;
import org.onosproject.provider.lldpcommon.LinkDiscovery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.onlab.packet.Ethernet.TYPE_BSN;
import static org.onlab.packet.Ethernet.TYPE_LLDP;
import static org.onosproject.net.PortNumber.portNumber;

/**
 * Provider to pre-discover links and devices based on a specified network
 * config.
 */

@Component(immediate = true)
public class NetworkConfigLinksProvider
        extends AbstractProvider
        implements LinkProvider {

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkProviderRegistry providerRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PacketService packetService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService masterService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigRegistry netCfgService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    private static final String PROP_PROBE_RATE = "probeRate";
    private static final int DEFAULT_PROBE_RATE = 3000;
    @Property(name = PROP_PROBE_RATE, intValue = DEFAULT_PROBE_RATE,
            label = "LLDP and BDDP probe rate specified in millis")
    private int probeRate = DEFAULT_PROBE_RATE;

    // Device link discovery helpers.
    protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>();

    private final LinkDiscoveryContext context = new InternalDiscoveryContext();

    private LinkProviderService providerService;

    private static final String PROVIDER_NAME =
            "org.onosproject.provider.netcfglinks";
    private final Logger log = LoggerFactory.getLogger(getClass());

    private ApplicationId appId;
    private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
    private final InternalDeviceListener deviceListener = new InternalDeviceListener();
    private final InternalConfigListener cfgListener = new InternalConfigListener();

    protected Set<LinkKey> configuredLinks = new HashSet<>();

    public NetworkConfigLinksProvider() {
        super(new ProviderId("lldp", PROVIDER_NAME));
    }

    private void createLinks() {
        netCfgService.getSubjects(LinkKey.class)
                .forEach(linkKey -> configuredLinks.add(linkKey));
    }

    @Activate
    protected void activate() {
        log.info("Activated");
        appId = coreService.registerApplication(PROVIDER_NAME);
        packetService.addProcessor(packetProcessor, PacketProcessor.advisor(0));
        providerService = providerRegistry.register(this);
        deviceService.addListener(deviceListener);
        netCfgService.addListener(cfgListener);
        requestIntercepts();
        loadDevices();
        createLinks();
    }

    @Deactivate
    protected void deactivate() {
        withdrawIntercepts();
        providerRegistry.unregister(this);
        disable();
        log.info("Deactivated");
    }

    /**
     * Loads available devices and registers their ports to be probed.
     */
    private void loadDevices() {
        deviceService.getAvailableDevices()
                .forEach(d -> updateDevice(d)
                        .ifPresent(ld -> updatePorts(ld, d.id())));
    }

    private Optional<LinkDiscovery> updateDevice(Device device) {
        if (device == null) {
            return Optional.empty();
        }

        LinkDiscovery ld = discoverers.computeIfAbsent(device.id(),
                                                       did -> new LinkDiscovery(device, context));
        if (ld.isStopped()) {
            ld.start();
        }
        return Optional.of(ld);
    }

    /**
     * Updates ports of the specified device to the specified discovery helper.
     */
    private void updatePorts(LinkDiscovery discoverer, DeviceId deviceId) {
        deviceService.getPorts(deviceId).forEach(p -> updatePort(discoverer, p));
    }


    private void updatePort(LinkDiscovery discoverer, Port port) {
        if (port == null) {
            return;
        }
        if (port.number().isLogical()) {
            // silently ignore logical ports
            return;
        }

        discoverer.addPort(port);
    }

    /**
     * Disables link discovery processing.
     */
    private void disable() {

        providerRegistry.unregister(this);
        discoverers.values().forEach(LinkDiscovery::stop);
        discoverers.clear();

        providerService = null;
    }

    /**
     * Provides processing context for the device link discovery helpers.
     */
    private class InternalDiscoveryContext implements LinkDiscoveryContext {
        @Override
        public MastershipService mastershipService() {
            return masterService;
        }

        @Override
        public LinkProviderService providerService() {
            return providerService;
        }

        @Override
        public PacketService packetService() {
            return packetService;
        }

        @Override
        public long probeRate() {
            return probeRate;
        }

        @Override
        public boolean useBddp() {
            return true;
        }

        @Override
        public void touchLink(LinkKey key) {
        }

        @Override
        public String fingerprint() {
            return "";
        }

        @Override
        public DeviceService deviceService() {
            return deviceService;
        }
    }

    LinkKey extractLinkKey(PacketContext packetContext) {
        Ethernet eth = packetContext.inPacket().parsed();
        if (eth == null) {
            return null;
        }

        ONOSLLDP onoslldp = ONOSLLDP.parseONOSLLDP(eth);
        if (onoslldp != null) {
            PortNumber srcPort = portNumber(onoslldp.getPort());
            PortNumber dstPort = packetContext.inPacket().receivedFrom().port();
            DeviceId srcDeviceId = DeviceId.deviceId(onoslldp.getDeviceString());
            DeviceId dstDeviceId = packetContext.inPacket().receivedFrom().deviceId();

            ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
            ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
            return LinkKey.linkKey(src, dst);
        }
        return null;
    }

    /**
     * Removes after stopping discovery helper for specified device.
     * @param deviceId device to remove
     */
    private void removeDevice(final DeviceId deviceId) {
        discoverers.computeIfPresent(deviceId, (did, ld) -> {
            ld.stop();
            return null;
        });

    }

    /**
     * Removes a port from the specified discovery helper.
     * @param port the port
     */
    private void removePort(Port port) {
        if (port.element() instanceof Device) {
            Device d = (Device) port.element();
            LinkDiscovery ld = discoverers.get(d.id());
            if (ld != null) {
                ld.removePort(port.number());
            }
        } else {
            log.warn("Attempted to remove non-Device port", port);
        }
    }


    /**
     * Processes incoming packets.
     */
    private class InternalPacketProcessor implements PacketProcessor {
        @Override
        public void process(PacketContext context) {
            if (context == null || context.isHandled()) {
                return;
            }

            Ethernet eth = context.inPacket().parsed();
            if (eth == null || (eth.getEtherType() != TYPE_LLDP && eth.getEtherType() != TYPE_BSN)) {
                return;
            }

            InboundPacket inPacket = context.inPacket();
            LinkKey linkKey = extractLinkKey(context);
            if (linkKey != null) {
                if (configuredLinks.contains(linkKey)) {
                    log.debug("Found configured link {}", linkKey);
                    LinkDiscovery ld = discoverers.get(inPacket.receivedFrom().deviceId());
                    if (ld == null) {
                        return;
                    }
                    if (ld.handleLldp(context)) {
                        context.block();
                    }
                } else {
                    log.debug("Found link that was not in the configuration {}", linkKey);
                    providerService.linkDetected(
                            new DefaultLinkDescription(linkKey.src(),
                                                       linkKey.dst(),
                                                       Link.Type.DIRECT,
                                                       DefaultLinkDescription.NOT_EXPECTED,
                                                       DefaultAnnotations.EMPTY));
                }
            }
        }
    }

    /**
     * Requests packet intercepts.
     */
    private void requestIntercepts() {
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchEthType(TYPE_LLDP);
        packetService.requestPackets(selector.build(), PacketPriority.CONTROL,
                                     appId, Optional.empty());

        selector.matchEthType(TYPE_BSN);

        packetService.requestPackets(selector.build(), PacketPriority.CONTROL,
                                     appId, Optional.empty());

    }

    /**
     * Withdraws packet intercepts.
     */
    private void withdrawIntercepts() {
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchEthType(TYPE_LLDP);
        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL,
                                    appId, Optional.empty());
        selector.matchEthType(TYPE_BSN);
        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL,
                                    appId, Optional.empty());
    }

    /**
     * Processes device events.
     */
    private class InternalDeviceListener implements DeviceListener {
        @Override
        public void event(DeviceEvent event) {
            if (event.type() == DeviceEvent.Type.PORT_STATS_UPDATED) {
                return;
            }
            Device device = event.subject();
            Port port = event.port();
            if (device == null) {
                log.error("Device is null.");
                return;
            }
            log.trace("{} {} {}", event.type(), event.subject(), event);
            final DeviceId deviceId = device.id();
            switch (event.type()) {
                case DEVICE_ADDED:
                case DEVICE_UPDATED:
                    updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId));
                    break;
                case PORT_ADDED:
                case PORT_UPDATED:
                    if (port.isEnabled()) {
                        updateDevice(device).ifPresent(ld -> updatePort(ld, port));
                    } else {
                        log.debug("Port down {}", port);
                        removePort(port);
                        providerService.linksVanished(new ConnectPoint(port.element().id(),
                                                                       port.number()));
                    }
                    break;
                case PORT_REMOVED:
                    log.debug("Port removed {}", port);
                    removePort(port);
                    providerService.linksVanished(new ConnectPoint(port.element().id(),
                                                                   port.number()));
                    break;
                case DEVICE_REMOVED:
                case DEVICE_SUSPENDED:
                    log.debug("Device removed {}", deviceId);
                    removeDevice(deviceId);
                    providerService.linksVanished(deviceId);
                    break;
                case DEVICE_AVAILABILITY_CHANGED:
                    if (deviceService.isAvailable(deviceId)) {
                        log.debug("Device up {}", deviceId);
                        updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId));
                    } else {
                        log.debug("Device down {}", deviceId);
                        removeDevice(deviceId);
                        providerService.linksVanished(deviceId);
                    }
                    break;
                case PORT_STATS_UPDATED:
                    break;
                default:
                    log.debug("Unknown event {}", event);
            }
        }
    }

    private class InternalConfigListener implements NetworkConfigListener {

        private void addLink(LinkKey linkKey) {
            configuredLinks.add(linkKey);
        }

        private void removeLink(LinkKey linkKey) {
            DefaultLinkDescription linkDescription =
                    new DefaultLinkDescription(linkKey.src(), linkKey.dst(),
                                               Link.Type.DIRECT);
            configuredLinks.remove(linkKey);
            providerService.linkVanished(linkDescription);
        }

        @Override
        public void event(NetworkConfigEvent event) {
            if (event.configClass().equals(BasicLinkConfig.class)) {
                log.info("net config event of type {} for basic link {}",
                         event.type(), event.subject());
                LinkKey linkKey = (LinkKey) event.subject();
                if (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
                    addLink(linkKey);
                } else if (event.type() == NetworkConfigEvent.Type.CONFIG_REMOVED) {
                    removeLink(linkKey);
                }
                log.info("Link reconfigured");
            }
        }
    }

}
