/*******************************************************************************
 * Copyright (c) 2014 Open Networking Laboratory.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0
 * which accompanies this distribution, and is available at
 * http://www.apache.org/licenses/LICENSE-2.0
 ******************************************************************************/

package net.onrc.onos.apps.segmentrouting;

import java.util.ArrayList;
import java.util.List;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.ICMP;
import net.onrc.onos.core.packet.IPv4;
import net.onrc.onos.core.topology.Host;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.MutableTopology;
import net.onrc.onos.core.topology.Port;
import net.onrc.onos.core.topology.Switch;
import net.onrc.onos.core.util.SwitchPort;

import org.json.JSONArray;
import org.json.JSONException;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMatchV3;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFOxmList;
import org.projectfloodlight.openflow.protocol.OFPacketOut;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class IcmpHandler {

    private SegmentRoutingManager srManager;
    private IFloodlightProviderService floodlightProvider;
    private MutableTopology mutableTopology;
    private ITopologyService topologyService;
    private static final Logger log = LoggerFactory
            .getLogger(IcmpHandler.class);

    private IFlowPusherService flowPusher;
    private boolean controllerPortAllowed = false;

    private static final int TABLE_VLAN = 0;
    private static final int TABLE_TMAC = 1;
    private static final int TABLE_IPv4_UNICAST = 2;
    private static final int TABLE_MPLS = 3;
    private static final int TABLE_META = 4;
    private static final int TABLE_ACL = 5;

    private static final short MAX_PRIORITY = (short) 0xffff;
    private static final short SLASH_24_PRIORITY = (short) 0xfff0;
    private static final short SLASH_16_PRIORITY = (short) 0xff00;
    private static final short SLASH_8_PRIORITY = (short) 0xf000;
    private static final short MIN_PRIORITY = 0x0;

    private static final int ICMP_TYPE_ECHO = 0x08;
    private static final int ICMP_TYPE_REPLY = 0x00;

    public IcmpHandler(FloodlightModuleContext context, SegmentRoutingManager manager) {

        this.floodlightProvider = context
                .getServiceImpl(IFloodlightProviderService.class);
        this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
        this.topologyService = context.getServiceImpl(ITopologyService.class);
        this.mutableTopology = topologyService.getTopology();

        this.srManager = manager;
    }

    /**
     * handle ICMP packets If it is for ICMP echo to router IP or any subnet GW
     * IP, then send ICMP response on behalf of the switch. If it is for any
     * hosts in subnets of the switches, but if the MAC address is not known,
     * then send an ARP request to the subent. If the MAC address is known, then
     * set the routing rule to the switch
     *
     * @param sw
     * @param inPort
     * @param payload
     */
    public void processPacketIn(Switch sw, Port inPort, Ethernet payload) {

        if (payload.getEtherType() == Ethernet.TYPE_IPV4) {

            IPv4 ipv4 = (IPv4) payload.getPayload();

            if (ipv4.getProtocol() == IPv4.PROTOCOL_ICMP) {

                log.debug("Received an ICMP packet from sw {} ",
                        sw.getDpid());
                IPv4Address destinationAddress =
                        IPv4Address.of(ipv4.getDestinationAddress());

                // Check if it is ICMP request to the switch
                String switchIpAddressSlash = sw.getStringAttribute("routerIp");
                if (switchIpAddressSlash != null) {
                    String switchIpAddressStr = switchIpAddressSlash.substring(0,
                            switchIpAddressSlash.indexOf('/'));
                    IPv4Address switchIpAddress = IPv4Address.of(switchIpAddressStr);
                    List<String> gatewayIps = getSubnetGatewayIps(sw);
                    if (((ICMP) ipv4.getPayload()).getIcmpType() == ICMP_TYPE_ECHO &&
                            (destinationAddress.getInt() == switchIpAddress.getInt() ||
                            gatewayIps.contains(destinationAddress.toString()))) {
                        log.debug("ICMP packet for sw {} and "
                                + "sending ICMP response ", sw.getDpid());
                        sendICMPResponse(sw, inPort, payload);
                        srManager.getIpPacketFromQueue(destinationAddress.getBytes());
                        return;
                    }
                }

                /* Check if ICMP is for any switch known host */
                for (Host host : sw.getHosts()) {
                    IPv4Address hostIpAddress =
                            IPv4Address.of(host.getIpAddress());
                    if (hostIpAddress != null &&
                            hostIpAddress.equals(destinationAddress)) {
                        /* TODO: We should not have come here as ARP itself
                         * would have installed a Route to the host. See if
                         * we can remove this code
                         *  - It can happen when the rule is set later in switches
                         *  (Ex: Ping reply arrives before the rules is set in the table)
                         *  - The rule must be set by ARP handler. But, we set the rule
                         *  again just in case and flush any pending packets to the host.
                         */
                        log.debug("ICMPHandler: ICMP request for known host {}",
                                hostIpAddress);
                        byte[] destinationMacAddress = host.getMacAddress().toBytes();
                        srManager.addRouteToHost(sw,
                                destinationAddress.getInt(), destinationMacAddress);
                        byte[] destIp = destinationAddress.getBytes();
                        for (IPv4 ipPacket : srManager.getIpPacketFromQueue(destIp)) {
                            if (ipPacket != null && !inSameSubnet(sw, ipPacket)) {
                                Ethernet eth = new Ethernet();
                                eth.setDestinationMACAddress(destinationMacAddress);
                                eth.setSourceMACAddress(sw
                                        .getStringAttribute("routerMac"));
                                eth.setEtherType(Ethernet.TYPE_IPV4);
                                eth.setPayload(ipPacket);
                                for (Port port: host.getAttachmentPoints())
                                    sendPacketOut(sw, eth, new SwitchPort(
                                            port.getDpid(),port.getNumber()), false);
                            }
                        }

                        return;
                    }
                }
                /* ICMP for an unknown host */
                log.debug("ICMPHandler: ICMP request for unknown host {}",
                        destinationAddress);
                srManager.sendArpRequest(sw, destinationAddress.getInt(), inPort);
            }

        }
    }

    /**
     * Retrieve Gateway IP address of all subnets defined in net config file
     *
     * @param sw Switch to retrieve subnet GW IPs for
     * @return list of GW IP addresses for all subnets
     */
    private List<String> getSubnetGatewayIps(Switch sw) {

        List<String> gatewayIps = new ArrayList<String>();

        String subnets = sw.getStringAttribute("subnets");
        try {
            JSONArray arry = new JSONArray(subnets);
            for (int i = 0; i < arry.length(); i++) {
                String subnetIpSlash = (String) arry.getJSONObject(i).get("subnetIp");
                if (subnetIpSlash != null) {
                    String subnetIp = subnetIpSlash.substring(0,
                            subnetIpSlash.indexOf('/'));
                    gatewayIps.add(subnetIp);
                }
            }
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return gatewayIps;
    }

    /**
     * Send ICMP reply back
     *
     * @param sw Switch
     * @param inPort Port the ICMP packet is forwarded from
     * @param icmpRequest the ICMP request to handle
     * @param destinationAddress destination address to send ICMP response to
     */
    private void sendICMPResponse(Switch sw, Port inPort, Ethernet icmpRequest) {

        Ethernet icmpReplyEth = new Ethernet();

        IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload();
        IPv4 icmpReplyIpv4 = new IPv4();
        int destAddress = icmpRequestIpv4.getDestinationAddress();
        icmpReplyIpv4.setDestinationAddress(icmpRequestIpv4.getSourceAddress());
        icmpReplyIpv4.setSourceAddress(destAddress);
        icmpReplyIpv4.setTtl((byte) 64);
        icmpReplyIpv4.setChecksum((short) 0);

        ICMP icmpReply = (ICMP) icmpRequestIpv4.getPayload().clone();
        icmpReply.setIcmpCode((byte) 0x00);
        icmpReply.setIcmpType((byte) ICMP_TYPE_REPLY);
        icmpReply.setChecksum((short) 0);

        icmpReplyIpv4.setPayload(icmpReply);

        icmpReplyEth.setPayload(icmpReplyIpv4);
        icmpReplyEth.setEtherType(Ethernet.TYPE_IPV4);
        icmpReplyEth.setDestinationMACAddress(icmpRequest.getSourceMACAddress());
        icmpReplyEth.setSourceMACAddress(icmpRequest.getDestinationMACAddress());

        sendPacketOut(sw, icmpReplyEth,
                new SwitchPort(sw.getDpid(), inPort.getPortNumber()), false);

        log.debug("Send an ICMP response {}", icmpReplyIpv4.toString());

    }

    /**
     * Send PACKET_OUT message with actions If switches support OFPP_TABLE
     * action, it sends out packet to TABLE port Otherwise, it sends the packet
     * to the port the packet came from (in this case, MPLS label is added if
     * the packet needs go through transit switches)
     *
     * @param sw Switch the packet came from
     * @param packet Ethernet packet to send
     * @param switchPort port to send the packet
     */
    private void sendPacketOut(Switch sw, Ethernet packet, SwitchPort switchPort,
            boolean supportOfppTable) {

        boolean sameSubnet = false;
        IOFSwitch ofSwitch = floodlightProvider.getMasterSwitch(sw.getDpid().value());
        OFFactory factory = ofSwitch.getFactory();

        List<OFAction> actions = new ArrayList<>();

        // If OFPP_TABLE action is not supported in the switch, MPLS label needs
        // to be set
        // if the packet needs to be delivered crossing switches
        if (!supportOfppTable) {
            // Check if the destination is the host attached to the switch
            int destinationAddress = ((IPv4) packet.getPayload()).getDestinationAddress();
            for (net.onrc.onos.core.topology.Host host : mutableTopology
                    .getHosts(switchPort)) {
                IPv4Address hostIpAddress = IPv4Address.of(host.getIpAddress());
                if (hostIpAddress != null && hostIpAddress.getInt() == destinationAddress) {
                    sameSubnet = true;
                    break;
                }
            }

            IPv4Address targetAddress = IPv4Address.of(((IPv4) packet.getPayload())
                    .getDestinationAddress());
            String destMacAddress = packet.getDestinationMAC().toString();
            // If the destination host is not attached in the switch
            // and the destination is not the neighbor switch, then add MPLS
            // label
            String targetMac = getRouterMACFromConfig(targetAddress);
            if (targetMac == null) {
                return; // targetMac should be always available
            }
            if (!sameSubnet && !targetMac.equals(destMacAddress)) {
                int mplsLabel = getMplsLabelFromConfig(targetAddress);
                if (mplsLabel > 0) {
                    OFAction pushlabel = factory.actions().pushMpls(EthType.MPLS_UNICAST);
                    OFOxmMplsLabel l = factory.oxms()
                            .mplsLabel(U32.of(mplsLabel));
                    OFAction setlabelid = factory.actions().buildSetField()
                            .setField(l).build();
                    OFAction copyTtlOut = factory.actions().copyTtlOut();
                    actions.add(pushlabel);
                    actions.add(setlabelid);
                    actions.add(copyTtlOut);
                }
            }

            OFAction outport = factory.actions().output(
                    OFPort.of(switchPort.getPortNumber().shortValue()), Short.MAX_VALUE);
            actions.add(outport);
        }
        // If OFPP_TABLE action is supported, first set a rule to allow packet
        // from CONTROLLER port.
        // Then, send the packet to the table port
        else {
            if (!controllerPortAllowed) {
                addControlPortInVlanTable(sw);
                controllerPortAllowed = true;
            }
            OFAction outport = factory.actions().output(OFPort.TABLE, Short.MAX_VALUE);
            actions.add(outport);
        }

        OFPacketOut po = factory.buildPacketOut()
                .setData(packet.serialize())
                .setActions(actions)
                .build();

        flowPusher.add(sw.getDpid(), po);
    }

    /**
     * Get MPLS label for the target address from the network config file
     *
     * @param targetAddress - IP address of the target host
     * @return MPLS label of the switch to send packets to the target address
     */
    private int getMplsLabelFromConfig(IPv4Address targetAddress) {

        int mplsLabel = -1;

        for (Switch sw : mutableTopology.getSwitches()) {

            String subnets = sw.getStringAttribute("subnets");
            try {
                JSONArray arry = new JSONArray(subnets);
                for (int i = 0; i < arry.length(); i++) {
                    String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
                    if (srManager.netMatch(subnetIp, targetAddress.toString())) {
                        String mplsLabelStr = sw.getStringAttribute("nodeSid");
                        if (mplsLabelStr != null)
                            mplsLabel = Integer.parseInt(mplsLabelStr);
                    }
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return mplsLabel;
    }

    /**
     * Get Router MAC Address for the target address from the network config
     * file
     *
     * @param targetAddress - IP address of the target host
     * @return Router MAC of the switch to send packets to the target address
     */
    private String getRouterMACFromConfig(IPv4Address targetAddress) {

        String routerMac = null;

        for (Switch sw : mutableTopology.getSwitches()) {

            String subnets = sw.getStringAttribute("subnets");
            try {
                JSONArray arry = new JSONArray(subnets);
                for (int i = 0; i < arry.length(); i++) {
                    String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
                    if (srManager.netMatch(subnetIp, targetAddress.toString())) {
                        routerMac = sw.getStringAttribute("routerMac");
                    }
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return routerMac;
    }

    /**
     * Add a new rule to VLAN table to forward packets from any port to the next
     * table It is required to forward packets from controller to pipeline
     *
     * @param sw Switch the packet came from
     */
    private void addControlPortInVlanTable(Switch sw) {

        IOFSwitch ofSwitch = floodlightProvider.getMasterSwitch(sw.getDpid().value());
        OFFactory factory = ofSwitch.getFactory();

        OFOxmInPort oxp = factory.oxms().inPort(OFPort.CONTROLLER);
        OFOxmVlanVid oxv = factory.oxms()
                .vlanVid(OFVlanVidMatch.UNTAGGED);
        OFOxmList oxmList = OFOxmList.of(oxv);

        /* Cqpd switch does not seems to support CONTROLLER port as in_port match rule */
        // OFOxmList oxmList = OFOxmList.of(oxp, oxv);

        OFMatchV3 match = factory.buildMatchV3()
                .setOxmList(oxmList)
                .build();

        OFInstruction gotoTbl = factory.instructions().buildGotoTable()
                .setTableId(TableId.of(TABLE_TMAC)).build();
        List<OFInstruction> instructions = new ArrayList<OFInstruction>();
        instructions.add(gotoTbl);
        OFMessage flowEntry = factory.buildFlowAdd()
                .setTableId(TableId.of(TABLE_VLAN))
                .setMatch(match)
                .setInstructions(instructions)
                .setPriority(1000) // does not matter - all rules
                                   // exclusive
                .setBufferId(OFBufferId.NO_BUFFER)
                .setIdleTimeout(0)
                .setHardTimeout(0)
                // .setXid(getNextTransactionId())
                .build();

        flowPusher.add(sw.getDpid(), flowEntry);
        log.debug("Adding a new vlan-rules in sw {}", sw.getDpid());

    }

    /**
     * Check if the source IP and destination IP are in the same subnet
     *
     * @param sw Switch
     * @param ipv4 IP address to check
     * @return return true if the IP packet is within the same subnet
     */
    private boolean inSameSubnet(Switch sw, IPv4 ipv4) {

        String gwIpSrc = getGwIpForSubnet(ipv4.getSourceAddress());
        String gwIpDest = getGwIpForSubnet(ipv4.getDestinationAddress());

        if (gwIpSrc.equals(gwIpDest)) {
            return true;
        }
        else
            return false;
    }

    /**
     * Get router IP address for the given IP address
     *
     * @param sourceAddress
     * @return
     */
    private String getGwIpForSubnet(int sourceAddress) {

        String gwIp = null;
        IPv4Address srcIp = IPv4Address.of(sourceAddress);

        for (Switch sw : mutableTopology.getSwitches()) {

            String subnets = sw.getStringAttribute("subnets");
            try {
                JSONArray arry = new JSONArray(subnets);
                for (int i = 0; i < arry.length(); i++) {
                    String subnetIpSlash = (String) arry.getJSONObject(i).get("subnetIp");
                    if (srManager.netMatch(subnetIpSlash, srcIp.toString())) {
                        gwIp = subnetIpSlash;
                    }
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return gwIp;
    }

}
