package net.onrc.onos.apps.sdnip;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.api.newintent.IntentService;
import net.onrc.onos.api.newintent.MultiPointToSinglePointIntent;
import net.onrc.onos.api.newintent.PointToPointIntent;
import net.onrc.onos.apps.proxyarp.IArpRequester;
import net.onrc.onos.apps.proxyarp.IProxyArpService;
import net.onrc.onos.apps.sdnip.RibUpdate.Operation;
import net.onrc.onos.apps.sdnip.web.SdnIpWebRoutable;
import net.onrc.onos.apps.sdnip.web.SdnIpWebRoutableNew;
import net.onrc.onos.core.intent.IntentOperation;
import net.onrc.onos.core.intent.IntentOperationList;
import net.onrc.onos.core.intent.ShortestPathIntent;
import net.onrc.onos.core.intent.runtime.IPathCalcRuntimeService;
import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
import net.onrc.onos.core.main.config.IConfigInfoService;
import net.onrc.onos.core.matchaction.action.Actions;
import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
import net.onrc.onos.core.matchaction.match.PacketMatch;
import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
import net.onrc.onos.core.newintent.IdBlockAllocatorBasedIntentIdGenerator;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.registry.IControllerRegistryService;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.IPv4;
import net.onrc.onos.core.util.PortNumber;
import net.onrc.onos.core.util.SwitchPort;
import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

import org.apache.commons.configuration.ConfigurationRuntimeException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.net.InetAddresses;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.googlecode.concurrenttrees.radix.RadixTree;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;

/**
 * This class sets up BGP paths, handles RIB updates and relative intents.
 * TODO: Thread-safe.
 */
public class SdnIp implements IFloodlightModule, ISdnIpService,
        IArpRequester, IConfigInfoService {

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

    private ILinkDiscoveryService linkDiscoveryService;
    private IRestApiService restApi;
    private IProxyArpService proxyArp;

    private InvertedRadixTree<RibEntry> bgpRoutes;
    private InvertedRadixTree<Interface> interfaceRoutes;

    private BlockingQueue<RibUpdate> ribUpdates;

    private String bgpdRestIp;
    private String routerId;
    private static final String DEFAULT_CONFIG_FILENAME = "config.json";
    private String currentConfigFilename = DEFAULT_CONFIG_FILENAME;

    /* ShortestPath Intent Variables */
    private final String caller = "SdnIp";
    private IControllerRegistryService controllerRegistryService;
    private IntentService intentService;
    private IPathCalcRuntimeService pathRuntime;
    /* Shortest Intent Path Variables */
    private IdBlockAllocatorBasedIntentIdGenerator intentIdGenerator;
    //private static final short ARP_PRIORITY = 20;

    private static final short BGP_PORT = 179;
    public static final byte PROTOCOL_ICMP = 0x1;
    public static final byte PROTOCOL_TCP = 0x6;

    // Configuration stuff
    private List<String> switches;
    private Map<String, Interface> interfaces;
    private Map<InetAddress, BgpPeer> bgpPeers;
    private SwitchPort bgpdAttachmentPoint;
    private MACAddress bgpdMacAddress;
    private short vlan;
    private Set<SwitchPort> externalNetworkSwitchPorts;

    private SetMultimap<InetAddress, RibUpdate> prefixesWaitingOnArp;

    private ExecutorService bgpUpdatesExecutor;

    private ConcurrentHashMap<Prefix, MultiPointToSinglePointIntent> pushedRouteIntents;

    /**
     * SDN-IP application has a configuration file. This method is to read all
     * the info from this file.
     *
     * @param configFilename the name of configuration file for SDN-IP application
     */
    private void readConfiguration(String configFilename) {
        File gatewaysFile = new File(configFilename);
        ObjectMapper mapper = new ObjectMapper();

        try {
            Configuration config = mapper.readValue(gatewaysFile, Configuration.class);

            switches = config.getSwitches();
            interfaces = new HashMap<>();
            for (Interface intf : config.getInterfaces()) {
                interfaces.put(intf.getName(), intf);
                externalNetworkSwitchPorts.add(new SwitchPort(intf.getDpid(),
                        intf.getPort()));
            }
            bgpPeers = new HashMap<>();
            for (BgpPeer peer : config.getPeers()) {
                bgpPeers.put(peer.getIpAddress(), peer);
            }

            bgpdAttachmentPoint = new SwitchPort(
                    new Dpid(config.getBgpdAttachmentDpid()),
                    PortNumber.uint16(config.getBgpdAttachmentPort()));

            bgpdMacAddress = config.getBgpdMacAddress();
            vlan = config.getVlan();
        } catch (JsonParseException | JsonMappingException e) {
            log.error("Error in JSON file", e);
            throw new ConfigurationRuntimeException("Error in JSON file", e);
        } catch (IOException e) {
            log.error("Error reading JSON file", e);
            throw new ConfigurationRuntimeException("Error in JSON file", e);
        }

        // Populate the interface InvertedRadixTree
        for (Interface intf : interfaces.values()) {
            Prefix prefix = new Prefix(intf.getIpAddress().getAddress(),
                    intf.getPrefixLength());
            interfaceRoutes.put(prefix.toBinaryString(), intf);
        }
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        Collection<Class<? extends IFloodlightService>> l = new ArrayList<>();
        l.add(ISdnIpService.class);
        l.add(IConfigInfoService.class);
        return l;
    }

    @Override
    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
        Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>();
        m.put(ISdnIpService.class, this);
        m.put(IConfigInfoService.class, this);
        return m;
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
        Collection<Class<? extends IFloodlightService>> l = new ArrayList<>();
        l.add(IRestApiService.class);
        l.add(IControllerRegistryService.class);
        l.add(IPathCalcRuntimeService.class);
        return l;
    }

    @Override
    public void init(FloodlightModuleContext context)
            throws FloodlightModuleException {

        bgpRoutes = new ConcurrentInvertedRadixTree<>(
                new DefaultByteArrayNodeFactory());
        interfaceRoutes = new ConcurrentInvertedRadixTree<>(
                new DefaultByteArrayNodeFactory());
        externalNetworkSwitchPorts = new HashSet<SwitchPort>();

        ribUpdates = new LinkedBlockingQueue<>();

        // Register REST handler.
        restApi = context.getServiceImpl(IRestApiService.class);
        proxyArp = context.getServiceImpl(IProxyArpService.class);

        controllerRegistryService = context
                .getServiceImpl(IControllerRegistryService.class);
        pathRuntime = context.getServiceImpl(IPathCalcRuntimeService.class);
        linkDiscoveryService = context.getServiceImpl(ILinkDiscoveryService.class);

        intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(
                controllerRegistryService);

        // TODO: initialize intentService

        pushedRouteIntents = new ConcurrentHashMap<>();

        prefixesWaitingOnArp = Multimaps.synchronizedSetMultimap(
                HashMultimap.<InetAddress, RibUpdate>create());

        //flowCache = new FlowCache(floodlightProvider);

        bgpUpdatesExecutor = Executors.newSingleThreadExecutor(
                new ThreadFactoryBuilder().setNameFormat("bgp-updates-%d").build());

        // Read in config values
        bgpdRestIp = context.getConfigParams(this).get("BgpdRestIp");
        if (bgpdRestIp == null) {
            log.error("BgpdRestIp property not found in config file");
            throw new ConfigurationRuntimeException(
                    "BgpdRestIp property not found in config file");
        } else {
            log.info("BgpdRestIp set to {}", bgpdRestIp);
        }

        routerId = context.getConfigParams(this).get("RouterId");
        if (routerId == null) {
            log.error("RouterId property not found in config file");
            throw new ConfigurationRuntimeException(
                    "RouterId property not found in config file");
        } else {
            log.info("RouterId set to {}", routerId);
        }

        String configFilenameParameter = context.getConfigParams(this).get("configfile");
        if (configFilenameParameter != null) {
            currentConfigFilename = configFilenameParameter;
        }
        log.debug("Config file set to {}", currentConfigFilename);

        readConfiguration(currentConfigFilename);
    }

    @Override
    public void startUp(FloodlightModuleContext context) {
        restApi.addRestletRoutable(new SdnIpWebRoutable());
        restApi.addRestletRoutable(new SdnIpWebRoutableNew());

        // Retrieve the RIB from BGPd during startup
        retrieveRib();
    }

    @Override
    public RadixTree<RibEntry> getPtree() {
        return bgpRoutes;
    }

    @Override
    public void clearPtree() {
        log.warn("Clear table operation not supported");
    }

    @Override
    public String getBgpdRestIp() {
        return bgpdRestIp;
    }

    @Override
    public String getRouterId() {
        return routerId;
    }

    /**
     * SDN-IP application will fetch all rib entries from BGPd when it starts.
     * Especially when we restart SDN-IP application while the BGPd has been
     * running all the time. Then before SDN-IP application re-connects to BGPd,
     * there are already lots of rib entries in BGPd.
     */
    private void retrieveRib() {
        String url = "http://" + bgpdRestIp + "/wm/bgp/" + routerId;
        String response = RestClient.get(url);

        if ("".equals(response)) {
            return;
        }

        try {
            response = response.replaceAll("\"", "'");
            JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(response);
            JSONArray ribArray = jsonObj.getJSONArray("rib");
            String inboundRouterId = jsonObj.getString("router-id");

            int size = ribArray.size();

            log.info("Retrived RIB of {} entries from BGPd", size);

            for (int j = 0; j < size; j++) {
                JSONObject ribEntry = ribArray.getJSONObject(j);
                String prefix = ribEntry.getString("prefix");
                String nexthop = ribEntry.getString("nexthop");

                // Insert each rib entry into the local rib
                String[] substring = prefix.split("/");
                String prefix1 = substring[0];
                String mask1 = substring[1];

                Prefix p;
                try {
                    p = new Prefix(prefix1, Integer.parseInt(mask1));
                } catch (NumberFormatException e) {
                    log.warn("Wrong mask format in RIB JSON: {}", mask1);
                    continue;
                } catch (IllegalArgumentException e1) {
                    log.warn("Wrong prefix format in RIB JSON: {}", prefix1);
                    continue;
                }

                RibEntry rib = new RibEntry(inboundRouterId, nexthop);

                try {
                    ribUpdates.put(new RibUpdate(Operation.UPDATE, p, rib));
                } catch (InterruptedException e) {
                    log.debug("Interrupted while pushing onto update queue");
                }
            }
        } catch (JSONException e) {
            // TODO don't parse JSON manually
            log.error("Error parsing inital route table JSON:", e);
        }
    }

    /**
     * Put RIB update to RIB update queue.
     *
     * @param update RIB update
     */
    @Override
    public void newRibUpdate(RibUpdate update) {
        try {
            ribUpdates.put(update);
        } catch (InterruptedException e) {
            log.debug("Interrupted while putting on ribUpdates queue", e);
            Thread.currentThread().interrupt();
        }
    }

    /**
     * Process adding RIB update.
     * Put new RIB update into InvertedRadixTree. If there was an existing nexthop
     * for this prefix, but the next hop was different, then execute deleting old
     * RIB update. If the next hop is the SDN domain, we do not handle it at the
     * moment. Otherwise, execute adding RIB.
     *
     * @param update RIB update
     */
    protected void processRibAdd(RibUpdate update) {
        synchronized (this) {
            Prefix prefix = update.getPrefix();

            log.debug("Processing prefix add {}", prefix);

            RibEntry rib = bgpRoutes.put(prefix.toBinaryString(), update.getRibEntry());

            if (rib != null && !rib.equals(update.getRibEntry())) {
                // There was an existing nexthop for this prefix. This update
                // supersedes that, so we need to remove the old flows for this
                // prefix from the switches
                executeDeleteRoute(prefix, rib);
            }

            if (update.getRibEntry().getNextHop().equals(
                    InetAddresses.forString("0.0.0.0"))) {
                // Route originated by SDN domain
                // We don't handle these at the moment
                log.debug("Own route {} to {}", prefix,
                        update.getRibEntry().getNextHop().getHostAddress());
                return;
            }

            executeRibAdd(update);
        }
    }

    /**
     * Execute adding RIB update.
     * Find out the egress Interface and MAC address of next hop router for this
     * RIB update. If the MAC address can not be found in ARP cache, then this
     * prefix will be put in prefixesWaitingOnArp queue. Otherwise, new flow
     * intent will be created and installed.
     *
     * @param update RIB update
     */
    private void executeRibAdd(RibUpdate update) {

        Prefix prefix = update.getPrefix();
        RibEntry rib = update.getRibEntry();

        InetAddress nextHopIpAddress = rib.getNextHop();

        // See if we know the MAC address of the next hop
        MACAddress nextHopMacAddress = proxyArp.getMacAddress(nextHopIpAddress);

        if (nextHopMacAddress == null) {
            prefixesWaitingOnArp.put(nextHopIpAddress,
                    new RibUpdate(Operation.UPDATE, prefix, rib));
            proxyArp.sendArpRequest(nextHopIpAddress, this, true);
            return;
        }

        addRouteIntentToNextHop(prefix, nextHopIpAddress, nextHopMacAddress);
    }

    /**
     * Adds a route intent given a prefix and a next hop IP address. This
     * method will find the egress interface for the intent.
     *
     * @param prefix IP prefix of the route to add
     * @param nextHopIpAddress IP address of the next hop
     * @param nextHopMacAddress MAC address of the next hop
     */
    private void addRouteIntentToNextHop(Prefix prefix, InetAddress nextHopIpAddress,
            MACAddress nextHopMacAddress) {

        // Find the attachment point (egress interface) of the next hop
        Interface egressInterface;
        if (bgpPeers.containsKey(nextHopIpAddress)) {
            // Route to a peer
            log.debug("Route to peer {}", nextHopIpAddress);
            BgpPeer peer = bgpPeers.get(nextHopIpAddress);
            egressInterface = interfaces.get(peer.getInterfaceName());
        } else {
            // Route to non-peer
            log.debug("Route to non-peer {}", nextHopIpAddress);
            egressInterface = getOutgoingInterface(nextHopIpAddress);
            if (egressInterface == null) {
                log.warn("No outgoing interface found for {}", nextHopIpAddress
                        .getHostAddress());
                return;
            }
        }

        doAddRouteIntent(prefix, egressInterface, nextHopMacAddress);
    }

    /**
     * Install a flow intent for a prefix.
     * Intent will match dst IP prefix and rewrite dst MAC address at all other
     * border switches, then forward packets according to dst MAC address.
     *
     * @param prefix IP prefix from BGP route
     * @param egressInterface egress Interface connected to next hop router
     * @param nextHopMacAddress MAC address of next hop router
     */
    private void doAddRouteIntent(Prefix prefix, Interface egressInterface,
            MACAddress nextHopMacAddress) {
        log.debug("Adding intent for prefix {}, next hop mac {}",
                prefix, nextHopMacAddress);

        MultiPointToSinglePointIntent pushedIntent = pushedRouteIntents.get(prefix);

        // Just for testing.
        if (pushedIntent != null) {
            log.error("There should not be a pushed intent: {}", pushedIntent);
        }

        SwitchPort egressPort = egressInterface.getSwitchPort();

        Set<SwitchPort> ingressPorts = new HashSet<SwitchPort>();

        for (Interface intf : interfaces.values()) {
            if (!intf.equals(egressInterface)) {
                SwitchPort srcPort = intf.getSwitchPort();
                ingressPorts.add(srcPort);
            }
        }

        // Match the destination IP prefix at the first hop
        PacketMatchBuilder builder = new PacketMatchBuilder();
        builder.setDstIp(new IPv4(InetAddresses
                .coerceToInteger(prefix.getInetAddress())),
                (short) prefix.getPrefixLength());
        PacketMatch packetMatch = builder.build();

        // Rewrite the destination MAC address
        ModifyDstMacAction modifyDstMacAction =
                new ModifyDstMacAction(nextHopMacAddress);

        MultiPointToSinglePointIntent intent =
                new MultiPointToSinglePointIntent(intentIdGenerator.getNewId(),
                        packetMatch, modifyDstMacAction, ingressPorts, egressPort);

        intentService.submit(intent);

        // Maintain the Intent
        pushedRouteIntents.put(prefix, intent);
    }

    /**
     * Remove prefix from InvertedRadixTree, if success, then try to delete the
     * relative intent.
     *
     * @param update RIB update
     */
    protected void processRibDelete(RibUpdate update) {
        synchronized (this) {
            Prefix prefix = update.getPrefix();

            // if (ptree.remove(prefix, update.getRibEntry())) {

            // TODO check the change of logic here - remove doesn't check that
            // the rib entry was what we expected (and we can't do this
            // concurrently)

            if (bgpRoutes.remove(prefix.toBinaryString())) {
                /*
                 * Only delete flows if an entry was actually removed from the tree.
                 * If no entry was removed, the <prefix, nexthop> wasn't there so
                 * it's probably already been removed and we don't need to do anything
                 */
                executeDeleteRoute(prefix, update.getRibEntry());

            }

            prefixesWaitingOnArp.removeAll(prefix.getInetAddress());
            // TODO cancel the request in the ARP manager as well
        }
    }

    /**
     * Delete prefix intent installed.
     *
     * @param prefix IP prefix withdrew in a rib update announcement
     * @param ribEntry next hop information
     */
    private void executeDeleteRoute(Prefix prefix, RibEntry ribEntry) {
        log.debug("Deleting {} to {}", prefix, ribEntry.getNextHop());

        MultiPointToSinglePointIntent intent = pushedRouteIntents.remove(prefix);

        if (intent == null) {
            log.debug("There is no intent in pushedRouteIntents to delete for " +
                    "prefix: {}", prefix);
        } else {
            intentService.withdraw(intent);
            log.debug("Deleted the pushedRouteIntent for prefix: {}", prefix);
        }
    }

    /**
     * Setup the Paths to the BGP Daemon. Run a loop for all of the bgpPeers
     * Push flow from BGPd to the peer Push flow from peer to BGPd Parameters to
     * pass to the intent are as follows: String id, long srcSwitch, long
     * srcPort, long srcMac, int srcIP, long dstSwitch, long dstPort, long
     * dstMac, int dstIP
     */
    private void setupBgpPaths() {
        IntentOperationList operations = new IntentOperationList();
        for (BgpPeer bgpPeer : bgpPeers.values()) {
            Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
            // Inet4Address.
            int srcIP = InetAddresses.coerceToInteger(peerInterface.getIpAddress());
            int dstIP = InetAddresses.coerceToInteger(bgpPeer.getIpAddress());
            String fwdIntentId = caller + ":"
                    + controllerRegistryService.getNextUniqueId();
            String bwdIntentId = caller + ":"
                    + controllerRegistryService.getNextUniqueId();
            SwitchPort srcPort =
                    new SwitchPort(bgpdAttachmentPoint.getDpid(),
                            bgpdAttachmentPoint.getPortNumber());
            // TODO: replace the code below with peerInterface.getSwitchPort()
            // when using poingToPointIntent
            SwitchPort dstPort =
                    new SwitchPort(new Dpid(peerInterface.getDpid()),
                            new PortNumber(peerInterface.getSwitchPort().getPortNumber()));

            // TODO: add TCP port number 179 into intent for BGP

            ShortestPathIntent fwdIntent = new ShortestPathIntent(fwdIntentId,
                    srcPort.getDpid().value(), srcPort.getPortNumber().value(),
                    ShortestPathIntent.EMPTYMACADDRESS, srcIP,
                    dstPort.getDpid().value(), dstPort.getPortNumber().value(),
                    ShortestPathIntent.EMPTYMACADDRESS, dstIP);
            ShortestPathIntent bwdIntent = new ShortestPathIntent(bwdIntentId,
                    dstPort.getDpid().value(), dstPort.getPortNumber().value(),
                    ShortestPathIntent.EMPTYMACADDRESS, dstIP,
                    srcPort.getDpid().value(), srcPort.getPortNumber().value(),
                    ShortestPathIntent.EMPTYMACADDRESS, srcIP);
            IntentOperation.Operator operator = IntentOperation.Operator.ADD;
            operations.add(operator, fwdIntent);
            operations.add(operator, bwdIntent);
        }
        pathRuntime.executeIntentOperations(operations);
    }


    /**
     * Setup paths for BGP Daemon and its peers. Run a loop for all the bgpPeers.
     * Push intent for path from BGPd to the peer. Push intent for path from peer
     * to BGPd.
     */
    private void setupBgpPathsWithNewIntent() {
        for (BgpPeer bgpPeer : bgpPeers.values()) {

            log.debug("Start to set up BGP paths.");

            Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());

            IPv4 bgpdAddress = new IPv4(InetAddresses
                    .coerceToInteger(peerInterface.getIpAddress()));
            IPv4 bgpdPeerAddress = new IPv4(InetAddresses
                    .coerceToInteger(bgpPeer.getIpAddress()));

            SwitchPort bgpdSwitchPort = bgpdAttachmentPoint;
            SwitchPort bgpdPeerSwitchPort = peerInterface.getSwitchPort();

            // install intent for BGP path from BGPd to BGP peer matching
            // destination TCP port 179

            // TODO: The usage of PacketMatchBuilder will be improved, then we
            // only need to new the PacketMatchBuilder once.
            // By then, the code here will be improved accordingly.
            PacketMatchBuilder builderMatchDstTcpPort = new PacketMatchBuilder();
            builderMatchDstTcpPort.setEtherType(Ethernet.TYPE_IPV4);
            builderMatchDstTcpPort.setIpProto(PROTOCOL_TCP);
            builderMatchDstTcpPort.setSrcIp(bgpdAddress);
            builderMatchDstTcpPort.setDstIp(bgpdPeerAddress);
            builderMatchDstTcpPort.setDstTcpPort(BGP_PORT);

            PacketMatch packetMatch = builderMatchDstTcpPort.build();

            PointToPointIntent intentMatchDstTcpPort = new PointToPointIntent(
                    intentIdGenerator.getNewId(), packetMatch, Actions
                    .nullAction(), bgpdSwitchPort, bgpdPeerSwitchPort);
            intentService.submit(intentMatchDstTcpPort);
            log.debug("Submitted BGP path intent matching dst TCP port 179 "
                    + "from BGPd to peer {}: {}",
                    bgpdPeerAddress, intentMatchDstTcpPort);

            // install intent for BGP path from BGPd to BGP peer matching
            // source TCP port 179
            PacketMatchBuilder builderMatchSrcTcpPort = new PacketMatchBuilder();
            builderMatchSrcTcpPort.setEtherType(Ethernet.TYPE_IPV4);
            builderMatchSrcTcpPort.setIpProto(PROTOCOL_TCP);
            builderMatchSrcTcpPort.setSrcIp(bgpdAddress);
            builderMatchSrcTcpPort.setDstIp(bgpdPeerAddress);
            builderMatchSrcTcpPort.setSrcTcpPort(BGP_PORT);

            packetMatch = builderMatchSrcTcpPort.build();

            PointToPointIntent intentMatchSrcTcpPort = new PointToPointIntent(
                    intentIdGenerator.getNewId(), packetMatch, Actions
                    .nullAction(), bgpdSwitchPort, bgpdPeerSwitchPort);
            intentService.submit(intentMatchSrcTcpPort);
            log.debug("Submitted BGP path intent matching src TCP port 179"
                    + "from BGPd to peer {}: {}",
                    bgpdPeerAddress, intentMatchSrcTcpPort);

            // install intent for reversed BGP path from BGP peer to BGPd
            // matching destination TCP port 179
            PacketMatchBuilder reversedBuilderMatchDstTcpPort = new PacketMatchBuilder();
            reversedBuilderMatchDstTcpPort.setEtherType(Ethernet.TYPE_IPV4);
            reversedBuilderMatchDstTcpPort.setIpProto(PROTOCOL_TCP);
            reversedBuilderMatchDstTcpPort.setSrcIp(bgpdPeerAddress);
            reversedBuilderMatchDstTcpPort.setDstIp(bgpdAddress);
            reversedBuilderMatchDstTcpPort.setDstTcpPort(BGP_PORT);

            packetMatch = reversedBuilderMatchDstTcpPort.build();

            PointToPointIntent reversedIntentMatchDstTcpPort = new PointToPointIntent(
                    intentIdGenerator.getNewId(), packetMatch, Actions
                    .nullAction(), bgpdPeerSwitchPort, bgpdSwitchPort);
            intentService.submit(reversedIntentMatchDstTcpPort);
            log.debug("Submitted BGP path intent matching dst TCP port 179"
                    + "from BGP peer {} to BGPd: {}",
                    bgpdPeerAddress, reversedIntentMatchDstTcpPort);

            // install intent for reversed BGP path from BGP peer to BGPd
            // matching source TCP port 179
            PacketMatchBuilder reversedBuilderMatchSrcTcpPort = new PacketMatchBuilder();
            reversedBuilderMatchSrcTcpPort.setEtherType(Ethernet.TYPE_IPV4);
            reversedBuilderMatchSrcTcpPort.setIpProto(PROTOCOL_TCP);
            reversedBuilderMatchSrcTcpPort.setSrcIp(bgpdPeerAddress);
            reversedBuilderMatchSrcTcpPort.setDstIp(bgpdAddress);
            reversedBuilderMatchSrcTcpPort.setSrcTcpPort(BGP_PORT);

            packetMatch = reversedBuilderMatchSrcTcpPort.build();

            PointToPointIntent reversedIntentMatchSrcTcpPort = new PointToPointIntent(
                    intentIdGenerator.getNewId(), packetMatch, Actions
                    .nullAction(), bgpdPeerSwitchPort, bgpdSwitchPort);
            intentService.submit(reversedIntentMatchSrcTcpPort);
            log.debug("Submitted BGP path intent matching src TCP port 179"
                    + "from BGP peer {} to BGPd: {}",
                    bgpdPeerAddress, reversedIntentMatchSrcTcpPort);

        }

    }

    /**
     * Setup ICMP paths between BGP Daemon and its peers. Run a loop for all the
     * bgpPeers. Push intent for path from BGPd to the peer. Push intent for path
     * from peer to BGPd.
     */
    private void setupIcmpPaths() {
        for (BgpPeer bgpPeer : bgpPeers.values()) {

            Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());

            PacketMatchBuilder builder = new PacketMatchBuilder();
            builder.setEtherType(Ethernet.TYPE_IPV4);
            builder.setIpProto(PROTOCOL_ICMP);

            IPv4 bgpdAddress = new IPv4(InetAddresses
                    .coerceToInteger(peerInterface.getIpAddress()));
            IPv4 bgpdPeerAddress = new IPv4(InetAddresses
                    .coerceToInteger(bgpPeer.getIpAddress()));

            SwitchPort bgpdSwitchPort = bgpdAttachmentPoint;
            SwitchPort bgpdPeerSwitchPort = peerInterface.getSwitchPort();

            // install intent for ICMP path from BGPd to BGP peer
            builder.setSrcIp(bgpdAddress);
            builder.setDstIp(bgpdPeerAddress);
            PacketMatch packetMatch = builder.build();

            PointToPointIntent intent = new PointToPointIntent(
                    intentIdGenerator.getNewId(), packetMatch, Actions
                    .nullAction(), bgpdSwitchPort, bgpdPeerSwitchPort);
            intentService.submit(intent);
            log.debug("Submitted ICMP path intent from BGPd to peer {}: {}",
                    bgpdPeerAddress, intent);

            // install intent for reversed ICMP path from BGP peer to BGPd
            builder.setSrcIp(bgpdPeerAddress);
            builder.setDstIp(bgpdAddress);
            packetMatch = builder.build();

            PointToPointIntent reversedIntent = new PointToPointIntent(
                    intentIdGenerator.getNewId(), packetMatch, Actions
                    .nullAction(), bgpdPeerSwitchPort, bgpdSwitchPort);
            intentService.submit(reversedIntent);
            log.debug("Submitted ICMP path intent from BGP peer {} to BGPd: {}",
                    bgpdPeerAddress, reversedIntent);
        }

    }

    /**
     * This method handles the prefixes which are waiting for ARP replies for
     * MAC addresses of next hops.
     *
     * @param ipAddress next hop router IP address, for which we sent ARP request out
     * @param macAddress MAC address which is relative to the ipAddress
     */
    @Override
    public void arpResponse(InetAddress ipAddress, MACAddress macAddress) {
        log.debug("Received ARP response: {} => {}",
                ipAddress.getHostAddress(), macAddress);

        /*
         * We synchronize on this to prevent changes to the InvertedRadixTree
         * while we're pushing intent. If the InvertedRadixTree changes, the
         * InvertedRadixTree and intent could get out of sync.
         */
        synchronized (this) {

          Set<RibUpdate> prefixesToPush = prefixesWaitingOnArp.removeAll(ipAddress);

            for (RibUpdate update : prefixesToPush) {
                // These will always be adds

                RibEntry rib = bgpRoutes.getValueForExactKey(
                        update.getPrefix().toBinaryString());
                if (rib != null && rib.equals(update.getRibEntry())) {
                    log.debug("Pushing prefix {} next hop {}", update.getPrefix(),
                            rib.getNextHop().getHostAddress());
                    // We only push prefix flows if the prefix is still in the
                    // InvertedRadixTree and the next hop is the same as our update.
                    // The prefix could have been removed while we were waiting
                    // for the ARP, or the next hop could have changed.
                    addRouteIntentToNextHop(update.getPrefix(), ipAddress,
                            macAddress);
                } else {
                    log.debug("Received ARP response, but {},{} is no longer in " +
                            "InvertedRadixTree", update.getPrefix(),
                            update.getRibEntry());
                }
            }
        }
    }


    /*private void setupArpFlows() {
        OFMatch match = new OFMatch();
        match.setDataLayerType(Ethernet.TYPE_ARP);
        match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);

        OFFlowMod fm = new OFFlowMod();
        fm.setMatch(match);

        OFActionOutput action = new OFActionOutput();
        action.setPort(OFPort.OFPP_CONTROLLER.getValue());
        action.setMaxLength((short) 0xffff);
        List<OFAction> actions = new ArrayList<>(1);
        actions.add(action);
        fm.setActions(actions);

        fm.setIdleTimeout((short) 0)
                .setHardTimeout((short) 0)
                .setBufferId(OFPacketOut.BUFFER_ID_NONE)
                .setCookie(0)
                .setCommand(OFFlowMod.OFPFC_ADD)
                .setPriority(ARP_PRIORITY)
                .setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);

        for (String strdpid : switches) {
            flowCache.write(HexString.toLong(strdpid), fm);
        }
    }

    private void setupDefaultDropFlows() {
        OFFlowMod fm = new OFFlowMod();
        fm.setMatch(new OFMatch());
        fm.setActions(new ArrayList<OFAction>()); // No action means drop

        fm.setIdleTimeout((short) 0)
                .setHardTimeout((short) 0)
                .setBufferId(OFPacketOut.BUFFER_ID_NONE)
                .setCookie(0)
                .setCommand(OFFlowMod.OFPFC_ADD)
                .setPriority((short) 0)
                .setLengthU(OFFlowMod.MINIMUM_LENGTH);

        OFFlowMod fmLLDP;
        OFFlowMod fmBDDP;
        try {
            fmLLDP = fm.clone();
            fmBDDP = fm.clone();
        } catch (CloneNotSupportedException e1) {
            log.error("Error cloning flow mod", e1);
            return;
        }

        OFMatch matchLLDP = new OFMatch();
        matchLLDP.setDataLayerType((short) 0x88cc);
        matchLLDP.setWildcards(matchLLDP.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
        fmLLDP.setMatch(matchLLDP);

        OFMatch matchBDDP = new OFMatch();
        matchBDDP.setDataLayerType((short) 0x8942);
        matchBDDP.setWildcards(matchBDDP.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
        fmBDDP.setMatch(matchBDDP);

        OFActionOutput action = new OFActionOutput();
        action.setPort(OFPort.OFPP_CONTROLLER.getValue());
        action.setMaxLength((short) 0xffff);
        List<OFAction> actions = new ArrayList<>(1);
        actions.add(action);

        fmLLDP.setActions(actions);
        fmBDDP.setActions(actions);

        fmLLDP.setPriority(ARP_PRIORITY);
        fmLLDP.setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);
        fmBDDP.setPriority(ARP_PRIORITY);
        fmBDDP.setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);

        List<OFFlowMod> flowModList = new ArrayList<>(3);
        flowModList.add(fm);
        flowModList.add(fmLLDP);
        flowModList.add(fmBDDP);

        for (String strdpid : switches) {
            flowCache.write(HexString.toLong(strdpid), flowModList);
        }
    }*/

    /**
     * The SDN-IP application is started from this method.
     */
    @Override
    public void beginRouting() {
        log.debug("Topology is now ready, beginning routing function");

        // TODO
        /*setupArpFlows();
        setupDefaultDropFlows();*/

        setupBgpPaths();

        // Suppress link discovery on external-facing router ports
        for (Interface intf : interfaces.values()) {
            linkDiscoveryService.disableDiscoveryOnPort(intf.getDpid(), intf.getPort());
        }

        bgpUpdatesExecutor.execute(new Runnable() {
            @Override
            public void run() {
                doUpdatesThread();
            }
        });
    }

    /**
     * The SDN-IP application is started from this method.
     * Before intent framework is ready, we need two methods to start the
     * application.
     */
    @Override
    public void beginRoutingWithNewIntent() {
        log.debug("Topology is now ready, beginning routing function");

        // TODO
        /*setupArpFlows();
        setupDefaultDropFlows();*/

        setupBgpPathsWithNewIntent();
        setupIcmpPaths();

        // Suppress link discovery on external-facing router ports
        for (Interface intf : interfaces.values()) {
            linkDiscoveryService.disableDiscoveryOnPort(intf.getDpid(), intf.getPort());
        }

        bgpUpdatesExecutor.execute(new Runnable() {
            @Override
            public void run() {
                doUpdatesThread();
            }
        });
    }

    /**
     * Thread for handling RIB updates.
     */
    private void doUpdatesThread() {
        boolean interrupted = false;
        try {
            while (true) {
                try {
                    RibUpdate update = ribUpdates.take();
                    switch (update.getOperation()) {
                    case UPDATE:
                        if (validateUpdate(update)) {
                            processRibAdd(update);
                        } else {
                            log.debug("Rib UPDATE out of order: {} via {}",
                                    update.getPrefix(), update.getRibEntry().getNextHop());
                        }
                        break;
                    case DELETE:
                        if (validateUpdate(update)) {
                            processRibDelete(update);
                        } else {
                            log.debug("Rib DELETE out of order: {} via {}",
                                    update.getPrefix(), update.getRibEntry().getNextHop());
                        }
                        break;
                    default:
                        log.error("Unknown operation {}", update.getOperation());
                        break;
                    }
                } catch (InterruptedException e) {
                    log.debug("Interrupted while taking from updates queue", e);
                    interrupted = true;
                } catch (Exception e) {
                    log.debug("exception", e);
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }

    /**
     * Judge whether a RIB update is in correct order.
     *
     * @param update RIB update
     * @return boolean whether the RIB update is in in correct order
     */
    private boolean validateUpdate(RibUpdate update) {
        RibEntry newEntry = update.getRibEntry();
        RibEntry oldEntry = bgpRoutes.getValueForExactKey(
                update.getPrefix().toBinaryString());

        // If there is no existing entry we must assume this is the most recent
        // update. However this might not always be the case as we might have a
        // POST then DELETE reordering.
        // if (oldEntry == null ||
        // !newEntry.getNextHop().equals(oldEntry.getNextHop())) {
        if (oldEntry == null) {
            return true;
        }

        // This handles the case where routes are gathered in the initial
        // request because they don't have sequence number info
        if (newEntry.getSysUpTime() == -1 && newEntry.getSequenceNum() == -1) {
            return true;
        }

        if (newEntry.getSysUpTime() > oldEntry.getSysUpTime()) {
            return true;
        }

        return newEntry.getSysUpTime() == oldEntry.getSysUpTime() &&
                newEntry.getSequenceNum() > oldEntry.getSequenceNum();
    }

    /**
     * To find the Interface which has longest matchable IP prefix (sub-network
     *  prefix) to next hop IP address.
     *
     * @param address the IP address of next hop router
     * @return Interface the Interface which has longest matchable IP prefix
     */
    private Interface longestInterfacePrefixMatch(InetAddress address) {
        Prefix prefixToSearchFor = new Prefix(address.getAddress(),
                Prefix.MAX_PREFIX_LENGTH);
        Iterator<Interface> it =
                interfaceRoutes.getValuesForKeysPrefixing(
                        prefixToSearchFor.toBinaryString()).iterator();
        Interface intf = null;
        // Find the last prefix, which will be the longest prefix
        while (it.hasNext()) {
            intf = it.next();
        }

        return intf;
    }

    /*
     * IConfigInfoService methods
     */

    @Override
    public boolean isInterfaceAddress(InetAddress address) {
        Interface intf = longestInterfacePrefixMatch(address);
        return (intf != null && intf.getIpAddress().equals(address));
    }

    @Override
    public boolean inConnectedNetwork(InetAddress address) {
        Interface intf = longestInterfacePrefixMatch(address);
        return (intf != null && !intf.getIpAddress().equals(address));
    }

    @Override
    public boolean fromExternalNetwork(long inDpid, short inPort) {
        for (Interface intf : interfaces.values()) {
            if (intf.getDpid() == inDpid && intf.getPort() == inPort) {
                return true;
            }
        }
        return false;
    }

    /**
     * To find the relative egress Interface for a next hop IP address.
     *
     * @param dstIpAddress the IP address of next hop router
     */
    @Override
    public Interface getOutgoingInterface(InetAddress dstIpAddress) {
        return longestInterfacePrefixMatch(dstIpAddress);
    }

    @Override
    public boolean hasLayer3Configuration() {
        return !interfaces.isEmpty();
    }

    @Override
    public MACAddress getRouterMacAddress() {
        return bgpdMacAddress;
    }

    @Override
    public short getVlan() {
        return vlan;
    }

    @Override
    public Set<SwitchPort> getExternalSwitchPorts() {
        return Collections.unmodifiableSet(externalNetworkSwitchPorts);
    }

}
