/*
 * Copyright 2015-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.segmentrouting;

import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Handler of IP packets that forwards IP packets that are sent to the controller,
 * except the ICMP packets which are processed by @link{IcmpHandler}.
 */
public class IpHandler {

    private static Logger log = LoggerFactory.getLogger(IpHandler.class);
    private SegmentRoutingManager srManager;
    private DeviceConfiguration config;
    private ConcurrentHashMap<Ip4Address, ConcurrentLinkedQueue<IPv4>> ipPacketQueue;

    /**
     * Creates an IpHandler object.
     *
     * @param srManager SegmentRoutingManager object
     */
    public IpHandler(SegmentRoutingManager srManager) {
        this.srManager = srManager;
        this.config = checkNotNull(srManager.deviceConfiguration);
        ipPacketQueue = new ConcurrentHashMap<>();
    }

    /**
     * Processes incoming IP packets.
     *
     * If it is an IP packet for known host, then forward it to the host.
     * If it is an IP packet for unknown host in subnet, then send an ARP request
     * to the subnet.
     *
     * @param pkt incoming packet
     */
    public void processPacketIn(InboundPacket pkt) {
        Ethernet ethernet = pkt.parsed();
        IPv4 ipv4 = (IPv4) ethernet.getPayload();

        ConnectPoint connectPoint = pkt.receivedFrom();
        DeviceId deviceId = connectPoint.deviceId();
        Ip4Address destinationAddress =
                Ip4Address.valueOf(ipv4.getDestinationAddress());

        // IP packet for know hosts
        if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
            forwardPackets(deviceId, destinationAddress);

        // IP packet for unknown host in the subnet of the router
        } else if (config.inSameSubnet(deviceId, destinationAddress)) {
            srManager.arpHandler.sendArpRequest(deviceId, destinationAddress, connectPoint);

        // IP packets for unknown host
        } else {
            log.debug("IP request for unknown host {} which is not in the subnet",
                    destinationAddress);
            // Do nothing
        }
    }

    /**
     * Adds the IP packet to a buffer.
     * The packets are forwarded to corresponding destination when the destination
     * MAC address is known via ARP response.
     *
     * @param ipPacket IP packet to add to the buffer
     */
    public void addToPacketBuffer(IPv4 ipPacket) {

        // Better not buffer TCP packets due to out-of-order packet transfer
        if (ipPacket.getProtocol() == IPv4.PROTOCOL_TCP) {
            return;
        }

        Ip4Address destIpAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());

        ipPacketQueue
            .computeIfAbsent(destIpAddress, a -> new ConcurrentLinkedQueue<>())
            .add(ipPacket);
    }

    /**
     * Forwards IP packets in the buffer to the destination IP address.
     * It is called when the controller finds the destination MAC address
     * via ARP responses.
     *
     * @param deviceId switch device ID
     * @param destIpAddress destination IP address
     */
    public void forwardPackets(DeviceId deviceId, Ip4Address destIpAddress) {
        if (ipPacketQueue.get(destIpAddress) == null) {
            return;
        }

        for (IPv4 ipPacket : ipPacketQueue.get(destIpAddress)) {
            Ip4Address destAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());
            if (config.inSameSubnet(deviceId, destAddress)) {
                ipPacket.setTtl((byte) (ipPacket.getTtl() - 1));
                ipPacket.setChecksum((short) 0);
                for (Host dest: srManager.hostService.getHostsByIp(destIpAddress)) {
                    Ethernet eth = new Ethernet();
                    eth.setDestinationMACAddress(dest.mac());
                    try {
                        eth.setSourceMACAddress(config.getDeviceMac(deviceId));
                    } catch (DeviceConfigNotFoundException e) {
                        log.warn(e.getMessage()
                                + " Skipping forwardPackets for this destination.");
                        continue;
                    }
                    eth.setEtherType(Ethernet.TYPE_IPV4);
                    eth.setPayload(ipPacket);

                    TrafficTreatment treatment = DefaultTrafficTreatment.builder().
                            setOutput(dest.location().port()).build();
                    OutboundPacket packet = new DefaultOutboundPacket(deviceId,
                            treatment, ByteBuffer.wrap(eth.serialize()));
                    srManager.packetService.emit(packet);
                    ipPacketQueue.get(destIpAddress).remove(ipPacket);
                }
                ipPacketQueue.get(destIpAddress).remove(ipPacket);
            }
        }
    }

}
