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

import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.neighbour.NeighbourMessageContext;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.host.HostService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;
import java.util.stream.Collectors;

import static org.onosproject.net.neighbour.NeighbourMessageType.REQUEST;

/**
 * Handler of ARP packets that responses or forwards ARP packets that
 * are sent to the controller.
 */
public class ArpHandler extends SegmentRoutingNeighbourHandler {

    private static Logger log = LoggerFactory.getLogger(ArpHandler.class);

    /**
     * Creates an ArpHandler object.
     *
     * @param srManager SegmentRoutingManager object
     */
    public ArpHandler(SegmentRoutingManager srManager) {
        super(srManager);
    }

    /**
     * Processes incoming ARP packets.
     *
     * If it is an ARP request to router itself or known hosts,
     * then it sends ARP response.
     * If it is an ARP request to unknown hosts in its own subnet,
     * then it flood the ARP request to the ports.
     * If it is an ARP response, then set a flow rule for the host
     * and forward any IP packets to the host in the packet buffer to the host.
     * <p>
     * Note: We handles all ARP packet in, even for those ARP packets between
     * hosts in the same subnet.
     * For an ARP packet with broadcast destination MAC,
     * some switches pipelines will send it to the controller due to table miss,
     * other switches will flood the packets directly in the data plane without
     * packet in.
     * We can deal with both cases.
     *
     * @param pkt incoming ARP packet and context information
     * @param hostService the host service
     */
    public void processPacketIn(NeighbourMessageContext pkt, HostService hostService) {

        SegmentRoutingAppConfig appConfig = srManager.cfgService
                .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
        if (appConfig != null && appConfig.suppressSubnet().contains(pkt.inPort())) {
            // Ignore ARP packets come from suppressed ports
            pkt.drop();
            return;
        }

        if (!validateArpSpa(pkt)) {
            log.debug("Ignore ARP packet discovered on {} with unexpected src protocol address {}.",
                    pkt.inPort(), pkt.sender().getIp4Address());
            pkt.drop();
            return;
        }

        if (pkt.type() == REQUEST) {
            handleArpRequest(pkt, hostService);
        } else {
            handleArpReply(pkt, hostService);
        }
    }

    private void handleArpRequest(NeighbourMessageContext pkt, HostService hostService) {
        // ARP request for router. Send ARP reply.
        if (isArpForRouter(pkt)) {
            MacAddress targetMac = config.getRouterMacForAGatewayIp(pkt.target().getIp4Address());
            if (targetMac == null) {
                log.warn("Router MAC of {} is not configured. Cannot handle ARP request from {}",
                        pkt.inPort().deviceId(), pkt.sender());
                return;
            }
            sendResponse(pkt, targetMac, hostService, true);
        } else {
            // NOTE: Ignore ARP packets except those target for the router
            //       We will reconsider enabling this when we have host learning support
            /*
            Set<Host> hosts = hostService.getHostsByIp(pkt.target());
            if (hosts.size() > 1) {
                log.warn("More than one host with the same ip {}", pkt.target());
            }
            Host targetHost = hosts.stream().findFirst().orElse(null);
            // ARP request for known hosts. Send proxy ARP reply on behalf of the target.
            if (targetHost != null) {
                pkt.forward(targetHost.location());
            // ARP request for unknown host in the subnet. Flood in the subnet.
            } else {
                flood(pkt);
            }
            */
        }
    }

    private void handleArpReply(NeighbourMessageContext pkt, HostService hostService) {
        // ARP reply for router. Process all pending IP packets.
        if (isArpForRouter(pkt)) {
            Ip4Address hostIpAddress = pkt.sender().getIp4Address();
            srManager.ipHandler.forwardPackets(pkt.inPort().deviceId(), hostIpAddress);
        } else {
            // NOTE: Ignore ARP packets except those target for the router
            //       We will reconsider enabling this when we have host learning support
            /*
            HostId targetHostId = HostId.hostId(pkt.dstMac(), pkt.vlan());
            Host targetHost = hostService.getHost(targetHostId);
            // ARP reply for known hosts. Forward to the host.
            if (targetHost != null) {
                pkt.forward(targetHost.location());
            // ARP reply for unknown host, Flood in the subnet.
            } else {
                // Don't flood to non-edge ports
                if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
                    return;
                }
                flood(pkt);
            }
            */
        }
    }

    /**
     * Check if the source protocol address of an ARP packet belongs to the same
     * subnet configured on the port it is seen.
     *
     * @param pkt ARP packet and context information
     * @return true if the source protocol address belongs to the configured subnet
     */
    private boolean validateArpSpa(NeighbourMessageContext pkt) {
        Ip4Address spa = pkt.sender().getIp4Address();
        Set<IpPrefix> subnet = config.getPortSubnets(pkt.inPort().deviceId(), pkt.inPort().port())
                .stream()
                .filter(ipPrefix -> ipPrefix.isIp4() && ipPrefix.contains(spa))
                .collect(Collectors.toSet());
        return !subnet.isEmpty();
    }


    private boolean isArpForRouter(NeighbourMessageContext pkt) {
        Ip4Address targetProtocolAddress = pkt.target().getIp4Address();
        Set<IpAddress> gatewayIpAddresses = null;
        try {
            if (targetProtocolAddress.equals(config.getRouterIpv4(pkt.inPort().deviceId()))) {
                return true;
            }
            gatewayIpAddresses = config.getPortIPs(pkt.inPort().deviceId());
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting check for router IP in processing arp");
        }
        if (gatewayIpAddresses != null &&
                gatewayIpAddresses.contains(targetProtocolAddress)) {
            return true;
        }
        return false;
    }

    /**
     * Sends an APR request for the target IP address to all ports except in-port.
     *
     * @param deviceId Switch device ID
     * @param targetAddress target IP address for ARP
     * @param inPort in-port
     */
    public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
        byte[] senderMacAddress = new byte[MacAddress.MAC_ADDRESS_LENGTH];
        byte[] senderIpAddress = new byte[Ip4Address.BYTE_LENGTH];
        /*
         * Retrieves device info.
         */
        if (!getSenderInfo(senderMacAddress, senderIpAddress, deviceId, targetAddress)) {
            log.warn("Aborting sendArpRequest, we cannot get all the information needed");
            return;
        }
        /*
         * Creates the request.
         */
        Ethernet arpRequest = ARP.buildArpRequest(
                senderMacAddress,
                senderIpAddress,
                targetAddress.toOctets(),
                VlanId.NO_VID
        );
        flood(arpRequest, inPort, targetAddress);
    }

}
