/*
 * Copyright 2017-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.routing.impl;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
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.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
import org.onlab.packet.IP;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.OutboundPacket;
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.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.packet.IpAddress.Version.INET6;

/**
 * Reactively handles sending packets to hosts that are directly connected to
 * router interfaces.
 */
@Component(immediate = true, enabled = false)
public class DirectHostManager {

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected InterfaceService interfaceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ComponentConfigService componentConfigService;

    private static final boolean DEFAULT_ENABLED = false;

    @Property(name = "enabled", boolValue = DEFAULT_ENABLED,
            label = "Enable reactive directly-connected host processing")
    private volatile boolean enabled = DEFAULT_ENABLED;

    private static final String APP_NAME = "org.onosproject.directhost";

    private static final long MAX_QUEUED_PACKETS = 10000;
    private static final long MAX_QUEUE_DURATION = 2; // seconds

    private ApplicationId appId;

    private InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
    private InternalHostListener hostListener = new InternalHostListener();

    private Cache<IpAddress, Queue<IP>> ipPacketCache = CacheBuilder.newBuilder()
            .weigher((IpAddress key, Queue<IP> value) -> value.size())
            .maximumWeight(MAX_QUEUED_PACKETS)
            .expireAfterAccess(MAX_QUEUE_DURATION, TimeUnit.SECONDS)
            .build();

    @Activate
    public void activate(ComponentContext context) {
        componentConfigService.registerProperties(getClass());
        appId = coreService.registerApplication(APP_NAME);
        modified(context);
    }

    @Modified
    private void modified(ComponentContext context) {
        Boolean boolEnabled = Tools.isPropertyEnabled(context.getProperties(), "enabled");
        if (boolEnabled != null) {
            if (enabled && !boolEnabled) {
                enabled = false;
                disable();
            } else if (!enabled && boolEnabled) {
                enabled = true;
                enable();
            }
        }
    }

    private void enable() {
        hostService.addListener(hostListener);
        packetService.addProcessor(packetProcessor, PacketProcessor.director(3));
        // Requests packets for IPv4 traffic.
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthType(EthType.EtherType.IPV4.ethType().toShort()).build();
        packetService.requestPackets(selector, PacketPriority.REACTIVE, appId, Optional.empty());
        // Requests packets for IPv6 traffic.
        selector = DefaultTrafficSelector.builder()
                .matchEthType(EthType.EtherType.IPV6.ethType().toShort()).build();
        packetService.requestPackets(selector, PacketPriority.REACTIVE, appId, Optional.empty());
    }

    private void disable() {
        packetService.removeProcessor(packetProcessor);
        hostService.removeListener(hostListener);
        // Withdraws IPv4 request.
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthType(EthType.EtherType.IPV4.ethType().toShort()).build();
        packetService.cancelPackets(selector, PacketPriority.REACTIVE, appId, Optional.empty());
        // Withdraws IPv6 request.
        selector = DefaultTrafficSelector.builder()
                .matchEthType(EthType.EtherType.IPV6.ethType().toShort()).build();
        packetService.cancelPackets(selector, PacketPriority.REACTIVE, appId, Optional.empty());
    }

    @Deactivate
    public void deactivate() {
        if (enabled) {
            disable();
        }

        componentConfigService.unregisterProperties(getClass(), false);
    }

    private boolean handle(Ethernet eth) {
        checkNotNull(eth);
        // If the DirectHostManager is not enabled and the
        // packets are different from what we expect just
        // skip them.
        if (!enabled || (eth.getEtherType() != Ethernet.TYPE_IPV6
                && eth.getEtherType() != Ethernet.TYPE_IPV4)) {
            return false;
        }
        // According to the type we set the destIp.
        IpAddress dstIp;
        if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
            IPv4 ip = (IPv4) eth.getPayload();
            dstIp = IpAddress.valueOf(ip.getDestinationAddress());
        } else {
            IPv6 ip = (IPv6) eth.getPayload();
            dstIp = IpAddress.valueOf(INET6, ip.getDestinationAddress());
        }
        // Looking for a candidate output port.
        Interface egressInterface = interfaceService.getMatchingInterface(dstIp);

        if (egressInterface == null) {
            log.info("No egress interface found for {}", dstIp);
            return false;
        }
        // Looking for the destination mac.
        Optional<Host> host = hostService.getHostsByIp(dstIp).stream()
                .filter(h -> h.location().equals(egressInterface.connectPoint()))
                .filter(h -> h.vlan().equals(egressInterface.vlan()))
                .findAny();
        // If we don't have a destination we start the monitoring
        // and we queue the packets waiting for a destination.
        if (host.isPresent()) {
            transformAndSend(
                    (IP) eth.getPayload(),
                    eth.getEtherType(),
                    egressInterface,
                    host.get().mac()
            );
        } else {
            hostService.startMonitoringIp(dstIp);
            ipPacketCache.asMap().compute(dstIp, (ip, queue) -> {
                if (queue == null) {
                    queue = new ConcurrentLinkedQueue<>();
                }
                queue.add((IP) eth.getPayload());
                return queue;
            });
        }

        return true;
    }

    private void transformAndSend(IP ip, short ethType,
                                  Interface egressInterface,
                                  MacAddress macAddress) {
        // Base processing for IPv4
        if (ethType == Ethernet.TYPE_IPV4) {
            IPv4 ipv4 = (IPv4) ip;
            ipv4.setTtl((byte) (ipv4.getTtl() - 1));
            ipv4.setChecksum((short) 0);
        // Base processing for IPv6.
        } else {
            IPv6 ipv6 = (IPv6) ip;
            ipv6.setHopLimit((byte) (ipv6.getHopLimit() - 1));
            ipv6.resetChecksum();
        }
        // Sends and serializes.
        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(macAddress);
        eth.setSourceMACAddress(egressInterface.mac());
        eth.setEtherType(ethType);
        eth.setPayload(ip);
        if (!egressInterface.vlan().equals(VlanId.NONE)) {
            eth.setVlanID(egressInterface.vlan().toShort());
        }
        send(eth, egressInterface.connectPoint());
    }

    private void send(Ethernet eth, ConnectPoint cp) {
        OutboundPacket packet = new DefaultOutboundPacket(cp.deviceId(),
                DefaultTrafficTreatment.builder().setOutput(cp.port()).build(), ByteBuffer.wrap(eth.serialize()));
        packetService.emit(packet);
    }

    private void sendQueued(IpAddress ipAddress, MacAddress macAddress) {
        log.debug("Sending queued packets for {} ({})", ipAddress, macAddress);
        ipPacketCache.asMap().computeIfPresent(ipAddress, (ip, packets) -> {
            packets.forEach(ipPackets -> {
                Interface egressInterface = interfaceService.getMatchingInterface(ipAddress);

                if (egressInterface == null) {
                    log.info("No egress interface found for {}", ipAddress);
                    return;
                }

                // According to the type of the address we set proper
                // protocol.
                transformAndSend(
                        ipPackets,
                        ipAddress.isIp4() ? Ethernet.TYPE_IPV4 : Ethernet.TYPE_IPV6,
                        egressInterface,
                        macAddress
                );
            });
            return null;
        });
    }

    private class InternalPacketProcessor implements PacketProcessor {

        @Override
        public void process(PacketContext context) {
            if (context.isHandled()) {
                return;
            }

            if (interfaceService.getInterfacesByPort(context.inPacket().receivedFrom()).isEmpty()) {
                // Don't handle packets that don't come from one of our configured interfaces
                return;
            }

            Ethernet eth = context.inPacket().parsed();
            if (eth == null) {
                return;
            }

            if (!handle(eth)) {
                return;
            }

            context.block();
        }
    }

    private class InternalHostListener implements HostListener {
        @Override
        public void event(HostEvent event) {
            switch (event.type()) {
            case HOST_ADDED:
                event.subject().ipAddresses().forEach(ip ->
                        DirectHostManager.this.sendQueued(ip, event.subject().mac()));
                break;
            case HOST_REMOVED:
            case HOST_UPDATED:
            case HOST_MOVED:
            default:
                break;
            }
        }
    }
}
