/*
 * Copyright 2018-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 java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapBuilder;
import org.onosproject.store.service.WallClockTimestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;


public class LinkHandler {
    private static final Logger log = LoggerFactory.getLogger(LinkHandler.class);
    protected final SegmentRoutingManager srManager;

    // Local store for all links seen and their present status, used for
    // optimized routing. The existence of the link in the keys is enough to know
    // if the link has been "seen-before" by this instance of the controller.
    // The boolean value indicates if the link is currently up or not.
    // Currently the optimized routing logic depends on "forgetting" a link
    // when a switch goes down, but "remembering" it when only the link goes down.
    private Map<Link, Boolean> seenLinks = new ConcurrentHashMap<>();
    private Set<Link> seenBefore = Sets.newConcurrentHashSet();
    private EventuallyConsistentMap<DeviceId, Set<PortNumber>> downedPortStore = null;

    /**
     * Constructs the LinkHandler.
     *
     * @param srManager Segment Routing manager
     */
    LinkHandler(SegmentRoutingManager srManager) {
        this.srManager = srManager;
        log.debug("Creating EC map downedportstore");
        EventuallyConsistentMapBuilder<DeviceId, Set<PortNumber>> downedPortsMapBuilder
                = srManager.storageService.eventuallyConsistentMapBuilder();
        downedPortStore = downedPortsMapBuilder.withName("downedportstore")
                .withSerializer(srManager.createSerializer())
                .withTimestampProvider((k, v) -> new WallClockTimestamp())
                .build();
        log.trace("Current size {}", downedPortStore.size());
    }

    /**
     * Constructs the LinkHandler for unit-testing.
     *
     * @param srManager SegmentRoutingManager
     * @param linkService LinkService
     */
    LinkHandler(SegmentRoutingManager srManager, LinkService linkService) {
        this.srManager = srManager;
    }

    /**
     * Initialize LinkHandler.
     */
    void init() {
        log.info("Loading stored links");
        srManager.linkService.getActiveLinks().forEach(this::processLinkAdded);
    }

    /**
     * Preprocessing of added link before being sent for route-path handling.
     * Also performs post processing of link.
     *
     * @param link the link to be processed
     */
    void processLinkAdded(Link link) {
        log.info("** LINK ADDED {}", link.toString());
        if (!isLinkValid(link)) {
            return;
        }
        // Irrespective of whether the local is a MASTER or not for this device,
        // create group handler instance and push default TTP flow rules if needed,
        // as in a multi-instance setup, instances can initiate groups for any
        // device. Also update local groupHandler stores.
        DefaultGroupHandler groupHandler = srManager.groupHandlerMap
                                                .get(link.src().deviceId());
        if (groupHandler == null) {
            Device device = srManager.deviceService.getDevice(link.src().deviceId());
            if (device != null) {
                log.warn("processLinkAdded: Link Added notification without "
                        + "Device Added event, still handling it");
                srManager.processDeviceAdded(device);
            }
        }

        if (isSeenLink(link)) {
            // temp store retains previous state, just before the state is updated in
            // seenLinks; previous state is necessary when processing the
            // linkupdate in defaultRoutingHandler
            seenBefore.add(link);
        }
        updateSeenLink(link, true);

        if (srManager.deviceConfiguration == null ||
                !srManager.deviceConfiguration.isConfigured(link.src().deviceId())) {
            log.warn("Source device of this link is not configured.. "
                    + "not processing further");
            return;
        }

        // process link only if it is bidirectional
        if (!isBidirectionalLinkUp(link)) {
            log.debug("Link not bidirectional.. waiting for other direction " +
                    "src {} --> dst {} ", link.dst(), link.src());
            return;
        }

        log.info("processing bidi links {} <--> {} UP", link.src(), link.dst());
        // update groupHandler internal port state for both directions
        List<Link> ulinks = getBidiComponentLinks(link);
        for (Link ulink : ulinks) {
            DefaultGroupHandler gh = srManager.groupHandlerMap
                                         .get(ulink.src().deviceId());
            if (gh != null) {
                gh.portUpForLink(ulink);
            }
        }

        for (Link ulink : ulinks) {
            log.info("-- Starting optimized route-path processing for component "
                    + "unidirectional link {} --> {} UP", ulink.src(), ulink.dst());
            // Performs the seenBefore optimization iff we have seen before both links in that case
            // we have programmed the group (unless there were major issues in the system)
            srManager.defaultRoutingHandler
                    .populateRoutingRulesForLinkStatusChange(null, ulink, null,
                            (seenBefore.contains(ulink) && seenBefore.contains(getReverseLink(ulink))));

            if (srManager.mastershipService.isLocalMaster(ulink.src().deviceId())) {
                // handle edge-ports for dual-homed hosts
                updateHostPorts(ulink, true);

                // It's possible that linkUp causes no route-path change as ECMP graph does
                // not change if the link is a parallel link (same src-dst as
                // another link). However we still need to update ECMP hash
                // groups to include new buckets for the link that has come up.
                DefaultGroupHandler gh = srManager.groupHandlerMap
                                            .get(ulink.src().deviceId());
                if (gh != null) {
                    if (!seenBefore.contains(ulink) && isParallelLink(ulink)) {
                        // if link seen first time, we need to ensure hash-groups have
                        // all ports
                        log.debug("Attempting retryHash for paralled first-time link {}",
                                  ulink);
                        gh.retryHash(ulink, false, true);
                    } else {
                        // seen before-link
                        if (isParallelLink(ulink)) {
                            log.debug("Attempting retryHash for paralled seen-before "
                                    + "link {}", ulink);
                            gh.retryHash(ulink, false, false);
                        }
                    }
                }
            }
            //clean up temp state
            seenBefore.remove(ulink);
        }

    }

    /**
     * Preprocessing of removed link before being sent for route-path handling.
     * Also performs post processing of link.
     *
     * @param link the link to be processed
     */
    void processLinkRemoved(Link link) {
        log.info("** LINK REMOVED {}", link.toString());
        if (!isLinkValid(link)) {
            return;
        }
        // when removing links, update seen links first, before doing route-path
        // changes. Link should be already there because was up before. If not,
        // we should not update the store. This could be a LINK DOWN happening
        // after a DEVICE DOWN event.
        if (isSeenLink(link)) {
            updateSeenLink(link, false);
        } else {
            // Exiting here may not be needed since other checks later should fail
            log.warn("received a link down for the link {} which is not in the store", link);
        }
        // handle edge-ports for dual-homed hosts
        if (srManager.mastershipService.isLocalMaster(link.src().deviceId())) {
            updateHostPorts(link, false);
        }

        // device availability check helps to ensure that multiple link-removed
        // events are actually treated as a single switch removed event.
        // purgeSeenLink is necessary so we do rerouting (instead of rehashing)
        // when switch comes back.
        if (link.src().elementId() instanceof DeviceId
                && !srManager.deviceService.isAvailable(link.src().deviceId())) {
            purgeSeenLink(link);
            return;
        }
        if (link.dst().elementId() instanceof DeviceId
                && !srManager.deviceService.isAvailable(link.dst().deviceId())) {
            purgeSeenLink(link);
            return;
        }

        // process link only if it is bidirectional
        if (!isBidirectionalLinkDown(link)) {
            log.debug("Link not bidirectional.. waiting for other direction " +
                    "src {} --> dst {} ", link.dst(), link.src());
            return;
        }
        log.info("processing bidi links {} <--> {} DOWN", link.src(), link.dst());

        for (Link ulink : getBidiComponentLinks(link)) {
            log.info("-- Starting optimized route-path processing for component "
                    + "unidirectional link {} --> {} DOWN", ulink.src(), ulink.dst());
            srManager.defaultRoutingHandler
                .populateRoutingRulesForLinkStatusChange(ulink, null, null, true);

            // attempt rehashing for parallel links
            DefaultGroupHandler groupHandler = srManager.groupHandlerMap
                    .get(ulink.src().deviceId());
            if (groupHandler != null) {
                if (srManager.mastershipService.isLocalMaster(ulink.src().deviceId())
                        && isParallelLink(ulink)) {
                    log.debug("* retrying hash for parallel link removed:{}", ulink);
                    groupHandler.retryHash(ulink, true, false);
                } else {
                    log.debug("Not attempting retry-hash for link removed: {} .. {}",
                              ulink,
                              (srManager.mastershipService.isLocalMaster(ulink
                                      .src().deviceId())) ? "not parallel"
                                                          : "not master");
                }
                // ensure local stores are updated after all rerouting or rehashing
                groupHandler.portDownForLink(ulink);
            } else {
                log.warn("group handler not found for dev:{} when removing link: {}",
                         ulink.src().deviceId(), ulink);
            }
        }
    }

    /**
     * Checks validity of link. Examples of invalid links include
     * indirect-links, links between ports on the same switch, and more.
     *
     * @param link the link to be processed
     * @return true if valid link
     */
     boolean isLinkValid(Link link) {
        if (link.type() != Link.Type.DIRECT) {
            // NOTE: A DIRECT link might be transiently marked as INDIRECT
            // if BDDP is received before LLDP. We can safely ignore that
            // until the LLDP is received and the link is marked as DIRECT.
            log.info("Ignore link {}->{}. Link type is {} instead of DIRECT.",
                     link.src(), link.dst(), link.type());
            return false;
        }
        DeviceId srcId = link.src().deviceId();
        DeviceId dstId = link.dst().deviceId();
        if (srcId.equals(dstId)) {
            log.warn("Links between ports on the same switch are not "
                    + "allowed .. ignoring link {}", link);
            return false;
        }
        DeviceConfiguration devConfig = srManager.deviceConfiguration;
        if (devConfig == null) {
            log.warn("Cannot check validity of link without device config");
            return true;
        }
        try {
            /*if (!devConfig.isEdgeDevice(srcId)
                    && !devConfig.isEdgeDevice(dstId)) {
                // ignore links between spines
                // XXX revisit when handling multi-stage fabrics
                log.warn("Links between spines not allowed...ignoring "
                        + "link {}", link);
                return false;
            }*/
            if (devConfig.isEdgeDevice(srcId)
                    && devConfig.isEdgeDevice(dstId)) {
                // ignore links between leaves if they are not pair-links
                // XXX revisit if removing pair-link config or allowing more than
                // one pair-link
                if (devConfig.getPairDeviceId(srcId).equals(dstId)
                        && devConfig.getPairLocalPort(srcId)
                                .equals(link.src().port())
                        && devConfig.getPairLocalPort(dstId)
                                .equals(link.dst().port())) {
                    // found pair link - allow it
                    return true;
                } else {
                    log.warn("Links between leaves other than pair-links are "
                            + "not allowed...ignoring link {}", link);
                    return false;
                }
            }
        } catch (DeviceConfigNotFoundException e) {
            // We still want to count the links in seenLinks even though there
            // is no config. So we let it return true
            log.warn("Could not check validity of link {} as subtending devices "
                    + "are not yet configured", link);
        }
        return true;
    }

    /**
     * Administratively enables or disables edge ports if the link that was
     * added or removed was the only uplink port from an edge device. Edge ports
     * that belong to dual-homed hosts are always processed. In addition,
     * single-homed host ports are optionally processed depending on the
     * singleHomedDown property.
     *
     * @param link the link to be processed
     * @param added true if link was added, false if link was removed
     */
    private void updateHostPorts(Link link, boolean added) {
        // Topology has only a single pair of leaves
        if (srManager.getInfraDeviceIds().isEmpty()) {
            log.debug("No spine configured. Not updating edge port for {} {}", link, added ? "add" : "remove");
            return;
        }

        DeviceConfiguration devConfig = srManager.deviceConfiguration;
        if (added) {
            try {
                if (!devConfig.isEdgeDevice(link.src().deviceId())
                        || devConfig.isEdgeDevice(link.dst().deviceId())) {
                    return;
                }
            } catch (DeviceConfigNotFoundException e) {
                log.warn("Unable to determine if link is a valid uplink"
                        + e.getMessage());
            }
            // re-enable previously disabled ports on this edge-device if any
            Set<PortNumber> p = downedPortStore.remove(link.src().deviceId());
            if (p != null) {
                log.warn("Link src {} --> dst {} added is an edge-device uplink, "
                        + "enabling dual homed ports if any: {}", link.src().deviceId(),
                        link.dst().deviceId(), (p.isEmpty()) ? "no ports" : p);
                p.forEach(pnum -> srManager.deviceAdminService
                        .changePortState(link.src().deviceId(), pnum, true));
            }
        } else {
            // If the device does not have a pair device - skip
            DeviceId dev = link.src().deviceId();
            if (getPairDeviceIdOrNull(dev) == null) {
                log.info("Device {} does not have pair device " +
                                 "not disabling access port", dev);
                return;
            }
            // Verify if last uplink
            if (!lastUplink(link)) {
                return;
            }
            // find dual homed hosts on this dev to disable
            Set<PortNumber> dp = srManager.hostHandler
                    .getDualHomedHostPorts(dev);
            log.warn("Link src {} --> dst {} removed was the last uplink, "
                    + "disabling  dual homed ports:  {}", dev,
                     link.dst().deviceId(), (dp.isEmpty()) ? "no ports" : dp);
            dp.forEach(pnum -> srManager.deviceAdminService
                        .changePortState(dev, pnum, false));
            if (srManager.singleHomedDown) {
                // get all configured ports and down them if they haven't already
                // been downed
                srManager.deviceService.getPorts(dev).stream()
                    .filter(p -> p.isEnabled() && !dp.contains(p.number()))
                    .filter(p -> srManager.interfaceService
                            .isConfigured(new ConnectPoint(dev, p.number())))
                    .filter(p -> !srManager.deviceConfiguration
                            .isPairLocalPort(dev, p.number()))
                    .forEach(p -> {
                        log.warn("Last uplink gone src {} -> dst {} .. removing "
                                + "configured port {}", p.number());
                        srManager.deviceAdminService
                            .changePortState(dev, p.number(), false);
                        dp.add(p.number());
                    });
            }
            if (!dp.isEmpty()) {
                // update global store
                Set<PortNumber> p = downedPortStore.get(dev);
                if (p == null) {
                    p = dp;
                } else {
                    p.addAll(dp);
                }
                downedPortStore.put(link.src().deviceId(), p);
            }
        }
    }

    /**
     * Returns true if given link was the last active uplink from src-device of
     * link. An uplink is defined as a unidirectional link with src as
     * edgeRouter and dst as non-edgeRouter.
     *
     * @param link
     * @return true if given link was the last uplink from the src device
     */
    private boolean lastUplink(Link link) {
        DeviceConfiguration devConfig = srManager.deviceConfiguration;
        try {
            if (!devConfig.isEdgeDevice(link.src().deviceId())
                    || devConfig.isEdgeDevice(link.dst().deviceId())) {
                return false;
            }
            // note that using linkservice here would cause race conditions as
            // more links can show up while the app is still processing the first one
            Set<Link> devLinks = seenLinks.entrySet().stream()
                    .filter(entry -> entry.getKey().src().deviceId()
                            .equals(link.src().deviceId()))
                    .filter(entry -> entry.getValue())
                    .filter(entry -> !entry.getKey().equals(link))
                    .map(entry -> entry.getKey())
                    .collect(Collectors.toSet());

            for (Link l : devLinks) {
                if (devConfig.isEdgeDevice(l.dst().deviceId())) {
                    continue;
                }
                log.debug("Found another active uplink {}", l);
                return false;
            }
            log.debug("No active uplink found");
            return true;
        } catch (DeviceConfigNotFoundException e) {
            log.warn("Unable to determine if link was the last uplink"
                    + e.getMessage());
        }
        return false;
    }

    /**
     * Returns true if this controller instance has seen this link before. The
     * link may not be currently up, but as long as the link had been seen
     * before this method will return true. The one exception is when the link
     * was indeed seen before, but this controller instance was forced to forget
     * it by a call to purgeSeenLink method.
     *
     * @param link the infrastructure link being queried
     * @return true if this controller instance has seen this link before
     */
    boolean isSeenLink(Link link) {
        return seenLinks.containsKey(link);
    }

    /**
     * Updates the seen link store. Updates can be for links that are currently
     * available or not.
     *
     * @param link the link to update in the seen-link local store
     * @param up the status of the link, true if up, false if down
     */
    void updateSeenLink(Link link, boolean up) {
        seenLinks.put(link, up);
    }

    /**
     * Returns the status of a seen-link (up or down). If the link has not been
     * seen-before, a null object is returned.
     *
     * @param link the infrastructure link being queried
     * @return null if the link was not seen-before; true if the seen-link is
     *         up; false if the seen-link is down
     */
    private Boolean isSeenLinkUp(Link link) {
        return seenLinks.get(link);
    }

    /**
     * Makes this controller instance forget a previously seen before link.
     *
     * @param link the infrastructure link to purge
     */
    private void purgeSeenLink(Link link) {
        seenLinks.remove(link);
        seenBefore.remove(link);
    }

    /**
     * Returns the status of a link as parallel link. A parallel link is defined
     * as a link which has common src and dst switches as another seen-link that
     * is currently enabled. It is not necessary for the link being queried to
     * be a seen-link.
     *
     * @param link the infrastructure link being queried
     * @return true if a seen-link exists that is up, and shares the same src
     *         and dst switches as the link being queried
     */
    private boolean isParallelLink(Link link) {
        for (Entry<Link, Boolean> seen : seenLinks.entrySet()) {
            Link seenLink = seen.getKey();
            if (seenLink.equals(link)) {
                continue;
            }
            if (seenLink.src().deviceId().equals(link.src().deviceId())
                    && seenLink.dst().deviceId().equals(link.dst().deviceId())
                    && seen.getValue()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if the link being queried is a bidirectional link that is
     * up. A bidi-link is defined as a component unidirectional link, whose
     * reverse link - ie. the component unidirectional link in the reverse
     * direction - has been seen-before and is up. It is NOT necessary for the
     * link being queried to be a previously seen-link.
     *
     * @param link the infrastructure (unidirectional) link being queried
     * @return true if another unidirectional link exists in the reverse
     *         direction, has been seen-before and is up
     */
    boolean isBidirectionalLinkUp(Link link) {
        // cannot call linkService as link may be gone
        Link reverseLink = getReverseLink(link);
        if (reverseLink == null) {
            return false;
        }
        Boolean result = isSeenLinkUp(reverseLink);
        if (result == null) {
            return false;
        }
        return result.booleanValue();
    }

    /**
     * Returns true if the link being queried is a bidirectional link that is
     * down. A bidi-link is defined as a component unidirectional link, whose
     * reverse link - i.e the component unidirectional link in the reverse
     * direction - has been seen before and is down. It is necessary for the
     * reverse-link to have been previously seen.
     *
     * @param link the infrastructure (unidirectional) link being queried
     * @return true if another unidirectional link exists in the reverse
     *         direction, has been seen-before and is down
     */
    boolean isBidirectionalLinkDown(Link link) {
        // cannot call linkService as link may be gone
        Link reverseLink = getReverseLink(link);
        if (reverseLink == null) {
            log.warn("Query for bidi-link down but reverse-link not found "
                    + "for link {}", link);
            return false;
        }
        Boolean result = seenLinks.get(reverseLink);
        if (result == null) {
            return false;
        }
        // if reverse link is seen UP (true), then its not bidi yet
        return !result.booleanValue();
    }

    /**
     * Returns the link in the reverse direction from the given link, by
     * consulting the seen-links store.
     *
     * @param link the given link
     * @return the reverse link or null
     */
    Link getReverseLink(Link link) {
        return seenLinks.keySet().stream()
                .filter(l -> l.src().equals(link.dst()) && l.dst().equals(link.src()))
                .findAny()
                .orElse(null);
    }

    /**
     * Returns the component unidirectional links of a declared bidirectional
     * link, by consulting the seen-links store. Caller is responsible for
     * previously verifying bidirectionality. Returned list may be empty if
     * errors are encountered.
     *
     * @param link the declared bidirectional link
     * @return list of component unidirectional links
     */
    List<Link> getBidiComponentLinks(Link link) {
        Link reverseLink = getReverseLink(link);
        List<Link> componentLinks;
        if (reverseLink == null) { // really should not happen if link is bidi
            log.error("cannot find reverse link for given link: {} ... is it "
                    + "bi-directional?", link);
            componentLinks = ImmutableList.of();
        } else {
            componentLinks = ImmutableList.of(reverseLink, link);
        }
        return componentLinks;
    }

    /**
     * Determines if the given link should be avoided in routing calculations by
     * policy or design.
     *
     * @param link the infrastructure link being queried
     * @return true if link should be avoided
     */
    boolean avoidLink(Link link) {
        // XXX currently only avoids all pair-links. In the future can be
        // extended to avoid any generic link
        DeviceId src = link.src().deviceId();
        PortNumber srcPort = link.src().port();
        DeviceConfiguration devConfig = srManager.deviceConfiguration;
        if (devConfig == null || !devConfig.isConfigured(src)) {
            log.warn("Device {} not configured..cannot avoid link {}", src,
                     link);
            return false;
        }
        DeviceId pairDev;
        PortNumber pairLocalPort, pairRemotePort = null;
        try {
            pairDev = devConfig.getPairDeviceId(src);
            pairLocalPort = devConfig.getPairLocalPort(src);
            if (pairDev != null) {
                pairRemotePort = devConfig
                        .getPairLocalPort(pairDev);
            }
        } catch (DeviceConfigNotFoundException e) {
            log.warn("Pair dev for dev {} not configured..cannot avoid link {}",
                     src, link);
            return false;
        }

        return srcPort.equals(pairLocalPort)
                && link.dst().deviceId().equals(pairDev)
                && link.dst().port().equals(pairRemotePort);
    }

    /**
     * Cleans up internal LinkHandler stores.
     *
     * @param device the device that has been removed
     */
    void processDeviceRemoved(Device device) {
        seenLinks.keySet()
                .removeIf(key -> key.src().deviceId().equals(device.id())
                        || key.dst().deviceId().equals(device.id()));
    }

    /**
     * Administratively disables the host location switchport if the edge device
     * has no viable uplinks. The caller needs to determine if such behavior is
     * desired for the single or dual-homed host.
     *
     * @param loc the host location
     */
    void checkUplinksForHost(HostLocation loc) {
        // Topology has only a single pair of leaves
        if (srManager.getInfraDeviceIds().isEmpty()) {
            log.debug("No spine configured. Not disabling access port for {}", loc);
            return;
        }

        // If the device does not have a pair device - return
        if (getPairDeviceIdOrNull(loc.deviceId()) == null) {
            log.info("Device {} does not have pair device " +
                             "not disabling access port", loc.deviceId());
            return;
        }

        // Verify link validity
        try {
            for (Link l : srManager.linkService.getDeviceLinks(loc.deviceId())) {
                if (srManager.deviceConfiguration.isEdgeDevice(l.dst().deviceId())
                        || l.state() == Link.State.INACTIVE) {
                    continue;
                }
                // found valid uplink - so, nothing to do
                return;
            }
        } catch (DeviceConfigNotFoundException e) {
            log.warn("Could not check for valid uplinks due to missing device"
                    + "config " + e.getMessage());
            return;
        }
        log.warn("Host location {} has no valid uplinks disabling port", loc);
        srManager.deviceAdminService.changePortState(loc.deviceId(), loc.port(),
                                                     false);
        Set<PortNumber> p = downedPortStore.get(loc.deviceId());
        if (p == null) {
            p = Sets.newHashSet(loc.port());
        } else {
            p.add(loc.port());
        }
        downedPortStore.put(loc.deviceId(), p);
    }

    private DeviceId getPairDeviceIdOrNull(DeviceId deviceId) {
        DeviceId pairDev;
        try {
            pairDev = srManager.deviceConfiguration.getPairDeviceId(deviceId);
        } catch (DeviceConfigNotFoundException e) {
            pairDev = null;
        }
        return pairDev;
    }

    ImmutableMap<Link, Boolean> getSeenLinks() {
        return ImmutableMap.copyOf(seenLinks);
    }

    ImmutableMap<DeviceId, Set<PortNumber>> getDownedPorts() {
        return ImmutableMap.copyOf(downedPortStore.entrySet());
    }

    /**
     * Returns all links that egress from given device that are UP in the
     * seenLinks store. The returned links are also confirmed to be
     * bidirectional.
     *
     * @param deviceId the device identifier
     * @return set of egress links from the device
     */
    Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
        return seenLinks.keySet().stream()
                .filter(link -> link.src().deviceId().equals(deviceId))
                .filter(link -> seenLinks.get(link))
                .filter(link -> isBidirectionalLinkUp(link))
                .collect(Collectors.toSet());
    }

}
