/*******************************************************************************
 * 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.HashSet;
import java.util.Iterator;
import java.util.List;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.packet.ARP;
import net.onrc.onos.core.packet.Ethernet;
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 org.json.JSONArray;
import org.json.JSONException;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFPacketOut;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.esotericsoftware.minlog.Log;

/**
 * Handling ARP requests to switches for Segment Routing.
 * <p/>
 * The module is for handling ARP requests to switches. It sends ARP response for any known
 * hosts to the controllers.
 * TODO: need to check the network config file for all hosts and packets
 */
public class ArpHandler {

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

    private IFloodlightProviderService floodlightProvider;
    private IFlowPusherService flowPusher;
    private ITopologyService topologyService;
    private MutableTopology mutableTopology;
    //private List<ArpEntry> arpEntries;
    private SegmentRoutingManager srManager;

    private static final short IDLE_TIMEOUT = 0;
    private static final short HARD_TIMEOUT = 0;

    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;


    /*
     * Default Constructor
     */
    public ArpHandler(FloodlightModuleContext context, SegmentRoutingManager segmentRoutingManager) {

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

        Log.debug("Arp Handler is initialized");

    }

    /**
     * process ARP packets from switches
     * It add a IP routing rule to the host
     * If it is an ARP response, then flush out all pending packets to the host
     *
     * @param sw
     * @param inPort
     * @param payload
     */
    public void processPacketIn(Switch sw, Port inPort, Ethernet payload){

    	log.debug("ArpHandler: Received a ARP packet from sw {} ", sw.getDpid());

        ARP arp = (ARP)payload.getPayload();

        byte[] senderMacAddressByte = arp.getSenderHardwareAddress();
        IPv4Address hostIpAddress = IPv4Address.of(arp.getSenderProtocolAddress());
        log.debug("ArpHandler: Add IP route to Host {} ", hostIpAddress);
        srManager.addRouteToHost(sw,hostIpAddress.getInt(), senderMacAddressByte);

        if (arp.getOpCode() == ARP.OP_REQUEST) {
        	log.debug("ArpHandler: Received a ARP Requestfrom sw {} ", sw.getDpid());
            handleArpRequest(sw, inPort, payload);
        }
        else {
            byte[] destIp = arp.getSenderProtocolAddress();
            for (IPv4 ipPacket: srManager.getIpPacketFromQueue(destIp)) {
                if (ipPacket != null && !inSameSubnet(sw, ipPacket)) {
                    Ethernet eth = new Ethernet();
                    eth.setDestinationMACAddress(payload.getSourceMACAddress());
                    eth.setSourceMACAddress(sw.getStringAttribute("routerMac"));
                    eth.setEtherType(Ethernet.TYPE_IPV4);
                    eth.setPayload(ipPacket);
                    sendPacketOut(sw, eth, inPort.getNumber().shortValue());
                }
            }
        }
    }

    /**
     * Send an ARP response for the ARP request to the known switches
     *
     * @param sw Switch
     * @param inPort port to send ARP response to
     * @param arpRequest ARP request packet to handle
     */
    private void handleArpRequest(Switch sw, Port inPort, Ethernet payload) {

    	ARP arpRequest = (ARP)payload.getPayload();
    	MACAddress targetMac = null;

    	if (isArpReqForSwitch(sw, arpRequest)) {
            String switchMacAddressStr = sw.getStringAttribute("routerMac");
            targetMac = MACAddress.valueOf(switchMacAddressStr);
        	log.debug("ArpHandler: Received a ARP query for a sw {} ", sw.getDpid());
    	}

    	Host knownHost = isArpReqForKnownHost(sw, arpRequest);
    	if (knownHost != null) {
            targetMac = knownHost.getMacAddress();
        	log.debug("ArpHandler: Received a ARP query for a known host {} ",
        						IPv4Address.of(knownHost.getIpAddress()));
    	}

    	if (targetMac != null) {
    		/* ARP Destination is known. Packet out ARP Reply */
            ARP arpReply = new ARP();
            arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
                    .setProtocolType(ARP.PROTO_TYPE_IP)
                    .setHardwareAddressLength(
                            (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
                    .setProtocolAddressLength((byte) IPv4.ADDRESS_LENGTH)
                    .setOpCode(ARP.OP_REPLY)
                    .setSenderHardwareAddress(targetMac.toBytes())
                    .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
                    .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
                    .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());

            Ethernet eth = new Ethernet();
            eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
                    .setSourceMACAddress(targetMac.toBytes())
                    .setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply);

            sendPacketOut(sw, eth, inPort.getPortNumber().shortValue());
    	}
    	else
    	{
    		/* Broadcast the received ARP request to all switch ports
    		 * that subnets are connected to except the port from which
    		 * ARP request is received
    		 */
        	log.debug("ArpHandler: Received a ARP query for unknown host {} ",
        			IPv4Address.of(arpRequest.getTargetProtocolAddress()));
    		for (Integer portNo : getSwitchSubnetPorts(sw)) {
    			if (portNo.shortValue() == inPort.getPortNumber().shortValue())
    				continue;
            	log.debug("ArpHandler: Sending ARP request on switch {} port {}",
            			sw.getDpid(), portNo.shortValue());
                sendPacketOut(sw, payload, portNo.shortValue());
    		}
    	}
    }

    /**
     * Check if the ARP request is to known hosts
     *
     * @param sw  Switch
     * @param arpRequest  ARP request to check
     */
    private Host isArpReqForKnownHost(Switch sw, ARP arpRequest) {
    	Host knownHost = null;

        IPv4Address targetIPAddress = IPv4Address.of(
        					arpRequest.getTargetProtocolAddress());

        for (Host host:sw.getHosts()) {
        	if (host.getIpAddress() == targetIPAddress.getInt()) {
        		knownHost = host;
        		break;
        	}
        }
        return knownHost;

    }

    /**
     *
     * Check if the ARP is for the switch
     *
     * @param sw Switch
     * @param arpRequest ARP request to check
     * @return true if the ARP is for the switch
     */
    private boolean isArpReqForSwitch(Switch sw, ARP arpRequest) {
        List<String> subnetGatewayIPs = getSubnetGatewayIps(sw);
        boolean isArpForSwitch = false;
        if (!subnetGatewayIPs.isEmpty()) {
            IPv4Address targetProtocolAddress = IPv4Address.of(arpRequest.getTargetProtocolAddress());
            if (subnetGatewayIPs.contains(targetProtocolAddress.toString())) {
            	isArpForSwitch = true;
            }
        }
        return isArpForSwitch;
    }

    /**
     * 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;
    }

    private HashSet<Integer> getSwitchSubnetPorts(Switch sw) {
        HashSet<Integer> switchSubnetPorts = new HashSet<Integer>();

        String subnets = sw.getStringAttribute("subnets");
        try {
            JSONArray arry = new JSONArray(subnets);
            for (int i = 0; i < arry.length(); i++) {
                Integer subnetPort = (Integer)arry.getJSONObject(i).get("portNo");
                switchSubnetPorts.add(subnetPort);
            }
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return switchSubnetPorts;
    }

    /**
     * Send an ARP request
     *
     * @param sw Switch
     * @param targetAddress Target IP address
     * @param inPort Port to send the ARP request
     *
     */
    public void sendArpRequest(Switch sw, int targetAddressInt, Port inPort) {

        IPv4Address targetAddress = IPv4Address.of(targetAddressInt);
        String senderMacAddressStr = sw.getStringAttribute("routerMac");
        String senderIpAddressSlash = sw.getStringAttribute("routerIp");
        if (senderMacAddressStr == null || senderIpAddressSlash == null)
            return;
        String senderIpAddressStr =
                senderIpAddressSlash.substring(0, senderIpAddressSlash.indexOf('/'));
        byte[] senderMacAddress = MacAddress.of(senderMacAddressStr).getBytes();
        byte[] senderIpAddress = IPv4Address.of(senderIpAddressStr).getBytes();

        ARP arpRequest = new ARP();
        arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
                .setProtocolType(ARP.PROTO_TYPE_IP)
                .setHardwareAddressLength(
                        (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
                .setProtocolAddressLength((byte) IPv4.ADDRESS_LENGTH)
                .setOpCode(ARP.OP_REQUEST)
                .setSenderHardwareAddress(senderMacAddress)
                .setTargetHardwareAddress(MacAddress.NONE.getBytes())
                .setSenderProtocolAddress(senderIpAddress)
                .setTargetProtocolAddress(targetAddress.getBytes());

        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(MacAddress.BROADCAST.getBytes())
                .setSourceMACAddress(senderMacAddress)
                .setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest);

		/* Broadcast the ARP request to all switch ports
		 * that subnets are connected to except the port from which
		 * ARP request is received
		 */
		for (Integer portNo : getSwitchSubnetPorts(sw)) {
			if (portNo.shortValue() == inPort.getPortNumber().shortValue())
				continue;
        	log.debug("ArpHandler: Sending ARP request on switch {} port {}",
        			sw.getDpid(), portNo.shortValue());
            sendPacketOut(sw, eth, portNo.shortValue());
		}
    }

    /**
     * Send PACKET_OUT packet to switch
     *
     * @param sw Switch to send the packet to
     * @param packet Packet to send
     * @param switchPort port to send (if -1, broadcast)
     */
    private void sendPacketOut(Switch sw, Ethernet packet, short port) {

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

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

        if (port > 0) {
            OFAction outport = factory.actions().output(OFPort.of(port), Short.MAX_VALUE);
            actions.add(outport);
        }
        else {
            Iterator<Port> iter = sw.getPorts().iterator();
            while (iter.hasNext()) {
                Port p = iter.next();
                int pnum = p.getPortNumber().shortValue();
                if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
                    OFAction outport = factory.actions().output(OFPort.of(p.getNumber().shortValue()),
                            Short.MAX_VALUE);
                    actions.add(outport);
                }
            }
        }

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

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

    /**
     * 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;
    }

}

