/*
 * Copyright 2014-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.net.host.impl;

import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv6;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onlab.util.SharedScheduledExecutors;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.edge.EdgePortService;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * Monitors hosts on the dataplane to detect changes in host data.
 * <p>
 * The HostMonitor can monitor hosts that have already been detected for
 * changes. At an application's request, it can also monitor and actively
 * probe for hosts that have not yet been detected (specified by IP address).
 * </p>
 */
public class HostMonitor implements Runnable {

    private Logger log = LoggerFactory.getLogger(getClass());

    private PacketService packetService;
    private HostManager hostManager;
    private InterfaceService interfaceService;
    private EdgePortService edgePortService;

    private final Set<IpAddress> monitoredAddresses;

    private final ConcurrentMap<ProviderId, HostProvider> hostProviders;

    private static final long DEFAULT_PROBE_RATE = 30000; // milliseconds
    private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes();
    private long probeRate = DEFAULT_PROBE_RATE;

    private ScheduledFuture<?> timeout;

    /**
     * Creates a new host monitor.
     *
     * @param packetService packet service used to send packets on the data plane
     * @param hostManager host manager used to look up host information and
     * probe existing hosts
     * @param interfaceService interface service for interface information
     * @param edgePortService  edge port service
     */
    public HostMonitor(PacketService packetService, HostManager hostManager,
                       InterfaceService interfaceService,
                       EdgePortService edgePortService) {

        this.packetService = packetService;
        this.hostManager = hostManager;
        this.interfaceService = interfaceService;
        this.edgePortService = edgePortService;

        monitoredAddresses = Collections.newSetFromMap(new ConcurrentHashMap<>());
        hostProviders = new ConcurrentHashMap<>();
    }

    /**
     * Adds an IP address to be monitored by the host monitor. The monitor will
     * periodically probe the host to detect changes.
     *
     * @param ip IP address of the host to monitor
     */
    void addMonitoringFor(IpAddress ip) {
        if (monitoredAddresses.add(ip)) {
            probe(ip);
        }
    }

    /**
     * Stops monitoring the given IP address.
     *
     * @param ip IP address to stop monitoring on
     */
    void stopMonitoring(IpAddress ip) {
        monitoredAddresses.remove(ip);
    }

    /**
     * Starts the host monitor. Does nothing if the monitor is already running.
     */
    void start() {
        synchronized (this) {
            if (timeout == null) {
                timeout = SharedScheduledExecutors.newTimeout(this, 0, TimeUnit.MILLISECONDS);
            }
        }
    }

    /**
     * Stops the host monitor.
     */
    void shutdown() {
        synchronized (this) {
            timeout.cancel(true);
            timeout = null;
        }
    }

    /*
     * Sets the probe rate.
     */
    void setProbeRate(long probeRate) {
        this.probeRate = probeRate;
    }

    /**
     * Registers a host provider with the host monitor. The monitor can use the
     * provider to probe hosts.
     *
     * @param provider the host provider to register
     */
    void registerHostProvider(HostProvider provider) {
        hostProviders.put(provider.id(), provider);
    }

    @Override
    public void run() {
        monitoredAddresses.forEach(this::probe);

        synchronized (this) {
            this.timeout = SharedScheduledExecutors.newTimeout(this, probeRate, TimeUnit.MILLISECONDS);
        }
    }

    private void probe(IpAddress ip) {
        Set<Host> hosts = hostManager.getHostsByIp(ip);

        if (hosts.isEmpty()) {
            sendRequest(ip);
        } else {
            for (Host host : hosts) {
                HostProvider provider = hostProviders.get(host.providerId());
                if (provider == null) {
                    hostProviders.remove(host.providerId(), null);
                } else {
                    provider.triggerProbe(host);
                }
            }
        }
    }

    /**
     * Sends an ARP or NDP request for the given IP address.
     *
     * @param targetIp IP address to send the request for
     */
    private void sendRequest(IpAddress targetIp) {
        interfaceService.getMatchingInterfaces(targetIp).forEach(intf -> {
            if (!edgePortService.isEdgePoint(intf.connectPoint())) {
                log.warn("Aborting attempt to send probe out non-edge port: {}", intf);
                return;
            }

            intf.ipAddressesList().stream()
                    .filter(ia -> ia.subnetAddress().contains(targetIp))
                    .forEach(ia -> {
                        log.debug("Sending probe for target:{} out of intf:{} vlan:{}",
                                targetIp, intf.connectPoint(), intf.vlan());
                        sendProbe(intf.connectPoint(), targetIp, ia.ipAddress(),
                                intf.mac(), intf.vlan());
                        // account for use-cases where tagged-vlan config is used
                        if (!intf.vlanTagged().isEmpty()) {
                            intf.vlanTagged().forEach(tag -> {
                                log.debug("Sending probe for target:{} out of intf:{} vlan:{}",
                                        targetIp, intf.connectPoint(), tag);
                                sendProbe(intf.connectPoint(), targetIp, ia.ipAddress(),
                                        intf.mac(), tag);
                            });
                        }
                    });
        });
    }

    public void sendProbe(ConnectPoint connectPoint,
                          IpAddress targetIp,
                          IpAddress sourceIp,
                          MacAddress sourceMac,
                          VlanId vlan) {
        Ethernet probePacket;

        if (targetIp.isIp4()) {
            // IPv4: Use ARP
            probePacket = buildArpRequest(targetIp, sourceIp, sourceMac, vlan);
        } else {
             // IPv6: Use Neighbor Discovery. According to the NDP protocol,
             // we should use the solicitation node address as IPv6 destination
             // and the multicast mac address as Ethernet destination.
            byte[] destIp = IPv6.getSolicitNodeAddress(targetIp.toOctets());
            probePacket = NeighborSolicitation.buildNdpSolicit(
                    targetIp.toOctets(),
                    sourceIp.toOctets(),
                    destIp,
                    sourceMac.toBytes(),
                    IPv6.getMCastMacAddress(destIp),
                    vlan
            );
        }

        if (probePacket == null) {
            log.warn("Not able to build the probe packet");
            return;
        }

        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
            .setOutput(connectPoint.port())
            .build();

        OutboundPacket outboundPacket =
            new DefaultOutboundPacket(connectPoint.deviceId(), treatment,
                                      ByteBuffer.wrap(probePacket.serialize()));

        packetService.emit(outboundPacket);
    }

    private Ethernet buildArpRequest(IpAddress targetIp, IpAddress sourceIp,
                                     MacAddress sourceMac, VlanId vlan) {

        ARP arp = new ARP();
        arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
           .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
           .setProtocolType(ARP.PROTO_TYPE_IP)
           .setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH)
           .setOpCode(ARP.OP_REQUEST);

        arp.setSenderHardwareAddress(sourceMac.toBytes())
           .setSenderProtocolAddress(sourceIp.toOctets())
           .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
           .setTargetProtocolAddress(targetIp.toOctets());

        Ethernet ethernet = new Ethernet();
        ethernet.setEtherType(Ethernet.TYPE_ARP)
                .setDestinationMACAddress(MacAddress.BROADCAST)
                .setSourceMACAddress(sourceMac)
                .setPayload(arp);

        if (!vlan.equals(VlanId.NONE)) {
            ethernet.setVlanID(vlan.toShort());
        }

        ethernet.setPad(true);

        return ethernet;
    }

}
