package net.onrc.onos.ofcontroller.networkgraph;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.onrc.onos.datastore.topology.RCLink;
import net.onrc.onos.datastore.topology.RCPort;
import net.onrc.onos.datastore.topology.RCSwitch;
import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
import net.onrc.onos.ofcontroller.util.Dpid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The "NB" read-only Network Map.
 *
 * - Maintain Invariant/Relationships between Topology Objects.
 *
 * TODO To be synchronized based on TopologyEvent Notification.
 *
 * TODO TBD: Caller is expected to maintain parent/child calling order. Parent
 * Object must exist before adding sub component(Add Switch -> Port).
 *
 * TODO TBD: This class may delay the requested change to handle event
 * re-ordering. e.g.) Link Add came in, but Switch was not there.
 *
 */
public class NetworkGraphImpl extends AbstractNetworkGraph implements
	NetworkGraphDiscoveryInterface, NetworkGraphReplicationInterface {

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

    private final NetworkGraphDatastore datastore;

    public NetworkGraphImpl() {
	super();
	datastore = new NetworkGraphDatastore(this);
    }

    /**
     * put Switch
     *
     * XXX Internal In-memory object mutation method. Will not write to DB.
     * Will not fire Notification.
     *
     * @param swEvt
     */
    void putSwitch(SwitchEvent swEvt) {
	if (swEvt == null) {
	    throw new IllegalArgumentException("Switch cannot be null");
	}

	Switch sw = switches.get(swEvt.getDpid());

	if (sw == null) {
	    sw = new SwitchImpl(this, swEvt.getDpid());
	    Switch existing = switches.putIfAbsent(swEvt.getDpid(), sw);
	    if (existing != null) {
		log.warn(
			"Concurrent putSwitch not expected. Continuing updating {}",
			existing);
		sw = existing;
	    }
	}

	// Update when more attributes are added to Event object
	// no attribute to update for now

	// TODO handle child Port event properly for performance
	for (PortEvent portEvt : swEvt.getPorts() ) {
	    putPort(portEvt);
	}

    }

    /**
     * remove Switch.
     *
     * XXX Internal In-memory object mutation method. Will not write to DB.
     * Will not fire Notification.
     *
     * @param swEvt
     */
    void removeSwitch(SwitchEvent swEvt) {
	if (swEvt == null) {
	    throw new IllegalArgumentException("Switch cannot be null");
	}

	// TODO handle child Port event properly for performance
	for (PortEvent portEvt : swEvt.getPorts() ) {
	    removePort(portEvt);
	}

	Switch sw = switches.get(swEvt.getDpid());

	if (sw == null) {
	    log.warn("Switch {} already removed, ignoring", swEvt);
	    return;
	}

	// Sanity check
	if (!sw.getPorts().isEmpty()) {
	    log.warn(
		    "Ports on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
		    swEvt);
	    // XXX Should we remove Port?
	}
	if (!sw.getDevices().isEmpty()) {
	    log.warn(
		    "Devices on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
		    swEvt);
	    // XXX Should we remove Device to Switch relation?
	}
	if (!sw.getIncomingLinks().iterator().hasNext()) {
	    log.warn(
		    "IncomingLinks on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
		    swEvt);
	    // XXX Should we remove Link?
	}
	if (!sw.getOutgoingLinks().iterator().hasNext()) {
	    log.warn(
		    "OutgoingLinks on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
		    swEvt);
	    // XXX Should we remove Link?
	}

	boolean removed = switches.remove(swEvt.getDpid(), sw);
	if (removed) {
	    log.warn(
		    "Switch instance was replaced concurrently while removing {}. Something is not right.",
		    sw);
	}
    }

    /**
     * put Port
     *
     * XXX Internal In-memory object mutation method. Will not write to DB.
     * Will not fire Notification.
     *
     * @param portEvt
     */
    void putPort(PortEvent portEvt) {
	if (portEvt == null) {
	    throw new IllegalArgumentException("Port cannot be null");
	}
	Switch sw = switches.get(portEvt.getDpid());
	if (sw == null) {
	    throw new BrokenInvariantException(String.format(
		    "Switch with dpid %s did not exist.",
		    new Dpid(portEvt.getDpid())));
	}
	Port p = sw.getPort(portEvt.getNumber());
	PortImpl port = null;
	if (p != null) {
	    port = getPortImpl(p);
	}

	if (port == null) {
	    port = new PortImpl(this, sw, portEvt.getNumber());
	}

	// TODO update attributes

	SwitchImpl s = getSwitchImpl(sw);
	s.addPort(port);
    }

    /**
     * remove Port
     *
     * XXX Internal In-memory object mutation method. Will not write to DB.
     * Will not fire Notification.
     *
     * @param portEvt
     */
    void removePort(PortEvent portEvt) {
	if (portEvt == null) {
	    throw new IllegalArgumentException("Port cannot be null");
	}

	Switch sw = switches.get(portEvt.getDpid());
	if (sw == null) {
	    log.warn("Parent Switch for Port {} already removed, ignoring", portEvt);
	    return;
	}

	Port p = sw.getPort(portEvt.getNumber());
	if (p == null) {
	    log.warn("Port {} already removed, ignoring", portEvt);
	    return;
	}

	// check if there is something referring to this Port

	if (!p.getDevices().iterator().hasNext()) {
	    log.warn(
		    "Devices on Port {} should be removed prior to removing Port. Removing Port anyways",
		    portEvt);
	    // XXX Should we remove Device to Port relation?
	}
	if (p.getIncomingLink() != null) {
	    log.warn(
		    "IncomingLinks on Port {} should be removed prior to removing Port. Removing Port anyways",
		    portEvt);
	    // XXX Should we remove Link?
	}
	if (p.getOutgoingLink() != null) {
	    log.warn(
		    "OutgoingLinks on Port {} should be removed prior to removing Port. Removing Port anyways",
		    portEvt);
	    // XXX Should we remove Link?
	}

	// remove Port from Switch
	 SwitchImpl s = getSwitchImpl(sw);
	 s.removePort(p);
    }

    /**
     * put Link
     *
     * XXX Internal In-memory object mutation method. Will not write to DB.
     * Will not fire Notification.
     *
     * @param linkEvt
     */
    void putLink(LinkEvent linkEvt) {
	if (linkEvt == null) {
	    throw new IllegalArgumentException("Link cannot be null");
	}

	Switch srcSw = switches.get(linkEvt.getSrc().dpid);
	if (srcSw == null) {
	    throw new BrokenInvariantException(
		    String.format(
			    "Switch with dpid %s did not exist.",
			    new Dpid(linkEvt.getSrc().dpid)));
	}

	Switch dstSw = switches.get(linkEvt.getDst().dpid);
	if (dstSw == null) {
	    throw new BrokenInvariantException(
		    String.format(
			    "Switch with dpid %s did not exist.",
			    new Dpid(linkEvt.getDst().dpid)));
	}

	Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
	if (srcPort == null) {
	    throw new BrokenInvariantException(
		    String.format(
			    "Src Port %s of a Link did not exist.",
			    linkEvt.getSrc() ));
	}

	Port dstPort = dstSw.getPort(linkEvt.getDst().number);
	if (dstPort == null) {
	    throw new BrokenInvariantException(
		    String.format(
			    "Dst Port %s of a Link did not exist.",
			    linkEvt.getDst() ));
	}

	// getting Link instance from destination port incoming Link
	Link l = dstPort.getIncomingLink();
	LinkImpl link = null;
	assert( l == srcPort.getOutgoingLink() );
	if (l != null) {
	    link = getLinkImpl(l);
	}

	if (link == null) {
	    link = new LinkImpl(this, srcPort, dstPort);
	}


	PortImpl dstPortMem = getPortImpl(dstPort);
	PortImpl srcPortMem = getPortImpl(srcPort);

	// Add Link first to avoid further Device addition

	// add Link to Port
	dstPortMem.setIncomingLink(link);
	srcPortMem.setOutgoingLink(link);

	// remove Device Pointing to Port if any
	for(Device d : dstPortMem.getDevices() ) {
	    log.error("Device {} on Port {} should have been removed prior to adding Link {}", d, dstPort, linkEvt);
	    DeviceImpl dev = getDeviceImpl(d);
	    dev.removeAttachmentPoint(dstPort);
	    // XXX This implies that change is made to Device Object,
	    // which need to be written to DB, how should that be done?
	    // should we write here or ignore and leave DB in inconsistent state?
	}
	dstPortMem.removeAllDevice();
	for(Device d : srcPortMem.getDevices() ) {
	    log.error("Device {} on Port {} should have been removed prior to adding Link {}", d, srcPort, linkEvt);
	    DeviceImpl dev = getDeviceImpl(d);
	    dev.removeAttachmentPoint(srcPort);
	    // XXX This implies that change is made to Device Object,
	    // which need to be written to DB, how should that be done?
	    // should we write here or ignore and leave DB in inconsistent state?
	}
	srcPortMem.removeAllDevice();

    }

    /**
     * removeLink
     *
     * XXX Internal In-memory object mutation method. Will not write to DB.
     * Will not fire Notification.
     *
     * @param linkEvt
     */
    void removeLink(LinkEvent linkEvt) {
	if (linkEvt == null) {
	    throw new IllegalArgumentException("Link cannot be null");
	}

	Switch srcSw = switches.get(linkEvt.getSrc().dpid);
	if (srcSw == null) {
	    log.warn("Src Switch for Link {} already removed, ignoring", linkEvt);
	    return;
	}

	Switch dstSw = switches.get(linkEvt.getDst().dpid);
	if (dstSw == null) {
	    log.warn("Dst Switch for Link {} already removed, ignoring", linkEvt);
	    return;
	}

	Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
	if (srcPort == null) {
	    log.warn("Src Port for Link {} already removed, ignoring", linkEvt);
	    return;
	}

	Port dstPort = dstSw.getPort(linkEvt.getDst().number);
	if (dstPort == null) {
	    log.warn("Dst Port for Link {} already removed, ignoring", linkEvt);
	    return;
	}

	Link l = dstPort.getIncomingLink();
	if (  l == null ) {
	    log.warn("Link {} already removed on destination Port", linkEvt);
	}
	l = srcPort.getOutgoingLink();
	if (  l == null ) {
	    log.warn("Link {} already removed on src Port", linkEvt);
	}

	getPortImpl(dstPort).setIncomingLink(null);
	getPortImpl(srcPort).setOutgoingLink(null);
    }

    // XXX Need to rework Device related
    /**
     * Add new device to DB
     *
     * @param device
     */
    void putDevice(DeviceEvent deviceEvt) {
	if (deviceEvt == null) {
	    throw new IllegalArgumentException("Device cannot be null");
	}

	Device device = getDeviceByMac(deviceEvt.getMac());
	if ( device == null ) {
	    device = new DeviceImpl(this, deviceEvt.getMac());
	    Device existing = mac2Device.putIfAbsent(deviceEvt.getMac(), device);
	    if (existing != null) {
		log.warn(
			"Concurrent putDevice seems to be in action. Continuing updating {}",
			existing);
		device = existing;
	    }
	}
	DeviceImpl memDevice = getDeviceImpl(device);

	// for each attachment point
	for (SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
	    // Attached Ports' Parent Switch must exist
	    Switch sw = getSwitch(swp.dpid);
	    if ( sw ==  null ) {
		log.warn("Switch {} for the attachment point did not exist. skipping mutation", sw);
		continue;
	    }
	    // Attached Ports must exist
	    Port port = sw.getPort(swp.number);
	    if ( port == null ) {
		log.warn("Port {} for the attachment point did not exist. skipping mutation", port);
		continue;
	    }
	    // Attached Ports must not have Link
	    if ( port.getOutgoingLink() != null || port.getIncomingLink() != null ) {
		log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.", port.getOutgoingLink(), port.getIncomingLink());
		continue;
	    }

	    // finally add Device <-> Port on In-memory structure
	    PortImpl memPort = getPortImpl(port);
	    memPort.addDevice(device);
	    memDevice.addAttachmentPoint(port);
	}

	// for each IP address
	for( InetAddress ipAddr : deviceEvt.getIpAddresses() ) {
	    // Add Device -> IP
	    memDevice.addIpAddress(ipAddr);

	    // Add IP -> Set<Device>
	    boolean updated = false;
	    do {
		Set<Device> devices = this.addr2Device.get(ipAddr);
		if ( devices == null ) {
		    devices = new HashSet<>();
		    Set<Device> existing = this.addr2Device.putIfAbsent(ipAddr, devices);
		    if ( existing == null ) {
			// success
			updated = true;
		    }
		} else {
		    Set<Device> updateDevices = new HashSet<>(devices);
		    updateDevices.add(device);
		    updated = this.addr2Device.replace(ipAddr, devices, updateDevices);
		}
		if (!updated) {
		    log.debug("Collision detected, updating IP to Device mapping retrying.");
		}
	    } while( !updated );
	}
    }

    void removeDevice(DeviceEvent deviceEvt) {
	if (deviceEvt == null) {
	    throw new IllegalArgumentException("Device cannot be null");
	}

	Device device = getDeviceByMac(deviceEvt.getMac());
	if ( device == null ) {
	    log.warn("Device {} already removed, ignoring", deviceEvt);
	    return;
	}
	DeviceImpl memDevice = getDeviceImpl(device);

	// for each attachment point
	for (SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
	    // Attached Ports' Parent Switch must exist
	    Switch sw = getSwitch(swp.dpid);
	    if ( sw ==  null ) {
		log.warn("Switch {} for the attachment point did not exist. skipping attachment point mutation", sw);
		continue;
	    }
	    // Attached Ports must exist
	    Port port = sw.getPort(swp.number);
	    if ( port == null ) {
		log.warn("Port {} for the attachment point did not exist. skipping attachment point mutation", port);
		continue;
	    }

	    // finally remove Device <-> Port on In-memory structure
	    PortImpl memPort = getPortImpl(port);
	    memPort.removeDevice(device);
	    memDevice.removeAttachmentPoint(port);
	}

	// for each IP address
	for( InetAddress ipAddr : deviceEvt.getIpAddresses() ) {
	    // Remove Device -> IP
	    memDevice.removeIpAddress(ipAddr);

	    // Remove IP -> Set<Device>
	    boolean updated = false;
	    do {
		Set<Device> devices = this.addr2Device.get(ipAddr);
		if ( devices == null ) {
		    // already empty set, nothing to do
		    updated = true;
		} else {
		    Set<Device> updateDevices = new HashSet<>(devices);
		    updateDevices.remove(device);
		    updated = this.addr2Device.replace(ipAddr, devices, updateDevices);
		}
		if (!updated) {
		    log.debug("Collision detected, updating IP to Device mapping retrying.");
		}
	    } while( !updated );
	}
    }

    private SwitchImpl getSwitchImpl(Switch sw) {
	if (sw instanceof SwitchImpl) {
	    return (SwitchImpl) sw;
	}
	throw new ClassCastException("SwitchImpl expected, but found: " + sw);
    }

    private PortImpl getPortImpl(Port p) {
	if (p instanceof PortImpl) {
	    return (PortImpl) p;
	}
	throw new ClassCastException("PortImpl expected, but found: " + p);
    }

    private LinkImpl getLinkImpl(Link l) {
	if (l instanceof LinkImpl) {
	    return (LinkImpl) l;
	}
	throw new ClassCastException("LinkImpl expected, but found: " + l);
    }

    private DeviceImpl getDeviceImpl(Device d) {
	if (d instanceof DeviceImpl) {
	    return (DeviceImpl) d;
	}
	throw new ClassCastException("DeviceImpl expected, but found: " + d);
    }

    public void loadWholeTopologyFromDB() {
	// TODO this method needs to use East-bound API if we still need this
	// XXX clear everything first?

	for (RCSwitch sw : RCSwitch.getAllSwitches()) {
	    if ( sw.getStatus() != RCSwitch.STATUS.ACTIVE ) {
		continue;
	    }
	    putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
	}

	for (RCPort p : RCPort.getAllPorts()) {
	    if (p.getStatus() != RCPort.STATUS.ACTIVE) {
		continue;
	    }
	    putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber() ));
	}

	// TODO Is Device going to be in DB? If so, read from DB.
	//	for (RCDevice d : RCDevice.getAllDevices()) {
	//	    DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
	//	    for (byte[] portId : d.getAllPortIds() ) {
	//		devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
	//	    }
	//	}

	for (RCLink l : RCLink.getAllLinks()) {
	    putLinkReplicationEvent( new LinkEvent(l.getSrc().dpid, l.getSrc().number, l.getDst().dpid, l.getDst().number));
	}
    }

    /**
     * Exception to be thrown when Modification to the Network Graph cannot be continued due to broken invariant.
     *
     * XXX Should this be checked exception or RuntimeException
     */
    public static class BrokenInvariantException extends RuntimeException {
	private static final long serialVersionUID = 1L;

	public BrokenInvariantException() {
	    super();
	}

	public BrokenInvariantException(String message) {
	    super(message);
	}
    }

    /* ******************************
     * NetworkGraphDiscoveryInterface methods
     * ******************************/

	@Override
	public void putSwitchEvent(SwitchEvent switchEvent) {
		if (prepareForAddSwitchEvent(switchEvent)) {
			datastore.addSwitch(switchEvent);
			putSwitch(switchEvent);
			// TODO send out notification
		}
		// TODO handle invariant violation
	}

	@Override
	public void removeSwitchEvent(SwitchEvent switchEvent) {
		if (prepareForRemoveSwitchEvent(switchEvent)) {
			datastore.deactivateSwitch(switchEvent);
			removeSwitch(switchEvent);
			// TODO send out notification
		}
		// TODO handle invariant violation
	}

	@Override
	public void putPortEvent(PortEvent portEvent) {
		// TODO Auto-generated method stub

	}

	@Override
	public void removePortEvent(PortEvent portEvent) {
		// TODO Auto-generated method stub

	}

	@Override
	public void putLinkEvent(LinkEvent linkEvent) {
		if (prepareForAddLinkEvent(linkEvent)) {
			datastore.addLink(linkEvent);
			putLink(linkEvent);
			// TODO send out notification
		}
		// TODO handle invariant violation
	}

	@Override
	public void removeLinkEvent(LinkEvent linkEvent) {
		if (prepareForRemoveLinkEvent(linkEvent)) {
			datastore.removeLink(linkEvent);
			removeLink(linkEvent);
			// TODO send out notification
		}
		// TODO handle invariant violation
	}

	@Override
	public void putDeviceEvent(DeviceEvent device) {
	    // XXX if prepareFor~ method returned false, event should be dropped
		// TODO Auto-generated method stub

	}

	@Override
	public void removeDeviceEvent(DeviceEvent deviceEvent) {
		// TODO Auto-generated method stub

	}

	/* *****************
	 * Internal methods to maintain invariants of the network graph
	 * *****************/

	/**
	 *
	 * @param swEvt
	 * @return true if ready to accept event.
	 */
	private boolean prepareForAddSwitchEvent(SwitchEvent swEvt) {
	    // No show stopping precondition?
	    // Prep: remove(deactivate) Ports on Switch, which is not on event
	    removePortsNotOnEvent(swEvt);
	    return true;
	}

	private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvt) {
	    // No show stopping precondition?
	    // Prep: remove(deactivate) Ports on Switch, which is not on event
	    // XXX may be remove switch should imply wipe all ports
	    removePortsNotOnEvent(swEvt);
	    return true;
	}

	private void removePortsNotOnEvent(SwitchEvent swEvt) {
	    Switch sw = switches.get( swEvt.getDpid() );
	    if ( sw != null ) {
		Set<Long> port_noOnEvent = new HashSet<>();
		for( PortEvent portEvent : swEvt.getPorts()) {
		    port_noOnEvent.add(portEvent.getNumber());
		}
		// Existing ports not on event should be removed.
		// TODO Should batch eventually for performance?
		for( Port p : sw.getPorts() ) {
		    if ( !port_noOnEvent.contains(p.getNumber()) ) {
			PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
			// calling Discovery removePort() API to wipe from DB, etc.
			removePortEvent(rmEvent);
		    }
		}
	    }
	}

	private boolean prepareForAddPortEvent(PortEvent portEvt) {
		// Parent Switch must exist
		if ( getSwitch(portEvt.getDpid()) == null) {
		    return false;
		}
		// Prep: None
		return true;
	}

	private boolean prepareForRemovePortEvent(PortEvent portEvt) {
		// Parent Switch must exist
		Switch sw = getSwitch(portEvt.getDpid());
		if ( sw ==  null ) {
		    return false;
		}
		Port port = sw.getPort(portEvt.getNumber());
		if ( port == null ) {
		    log.debug("Port already removed? {}", portEvt);
		    // let it pass
		    return true;
		}

		// Prep: Remove Link and Device Attachment
		for (Device device : port.getDevices()) {
		    DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
		    devEvt.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(), port.getNumber()));
		    // calling Discovery API to wipe from DB, etc.
		    removeDeviceEvent(devEvt);
		}
		Set<Link> links = new HashSet<>();
		links.add(port.getOutgoingLink());
		links.add(port.getIncomingLink());
		for ( Link link : links) {
		    if (link == null ) {
			continue;
		    }
		    LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(), link.getSourcePortNumber(), link.getDestinationSwitchDpid(), link.getDestinationPortNumber());
		    // calling Discovery API to wipe from DB, etc.
		    removeLinkEvent(linkEvent);
		}
		return true;
	}

	private boolean prepareForAddLinkEvent(LinkEvent linkEvt) {
	    // Src/Dst Switch must exist
	    Switch srcSw = getSwitch(linkEvt.getSrc().dpid);
	    Switch dstSw = getSwitch(linkEvt.getDst().dpid);
	    if ( srcSw == null || dstSw == null ) {
		return false;
	    }
	    // Src/Dst Port must exist
	    Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
	    Port dstPort = srcSw.getPort(linkEvt.getDst().number);
	    if ( srcPort == null || dstPort == null ) {
		return false;
	    }

	    // Prep: remove Device attachment on both Ports
	    for (Device device : srcPort.getDevices()) {
		DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
		devEvt.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
		// calling Discovery API to wipe from DB, etc.
		removeDeviceEvent(devEvt);
	    }
	    for (Device device : dstPort.getDevices()) {
		DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
		devEvt.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(), dstPort.getNumber()));
		// calling Discovery API to wipe from DB, etc.
		removeDeviceEvent(devEvt);
	    }

	    return true;
	}

	private boolean prepareForRemoveLinkEvent(LinkEvent linkEvt) {
	    // Src/Dst Switch must exist
	    Switch srcSw = getSwitch(linkEvt.getSrc().dpid);
	    Switch dstSw = getSwitch(linkEvt.getDst().dpid);
	    if ( srcSw == null || dstSw == null ) {
		return false;
	    }
	    // Src/Dst Port must exist
	    Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
	    Port dstPort = srcSw.getPort(linkEvt.getDst().number);
	    if ( srcPort == null || dstPort == null ) {
		return false;
	    }

	    // Prep: None
	    return true;
	}

	/**
	 *
	 * @param deviceEvt Event will be modified to remove inapplicable attachemntPoints/ipAddress
	 * @return false if this event should be dropped.
	 */
	private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvt) {
	    boolean preconditionBroken = false;
	    ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
	    for ( PortEvent.SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
		// Attached Ports' Parent Switch must exist
		Switch sw = getSwitch(swp.dpid);
		if ( sw ==  null ) {
		    preconditionBroken = true;
		    failedSwitchPort.add(swp);
		    continue;
		}
		// Attached Ports must exist
		Port port = sw.getPort(swp.number);
		if ( port == null ) {
		    preconditionBroken = true;
		    failedSwitchPort.add(swp);
		    continue;
		}
		// Attached Ports must not have Link
		if ( port.getOutgoingLink() != null || port.getIncomingLink() != null ) {
		    preconditionBroken = true;
		    failedSwitchPort.add(swp);
		    continue;
		}
	    }

	    // Rewriting event to exclude failed attachmentPoint
	    // XXX Assumption behind this is that inapplicable device event should
	    // be dropped, not deferred. If we decide to defer Device event,
	    // rewriting can become a problem
	    List<SwitchPort>  attachmentPoints = deviceEvt.getAttachmentPoints();
	    attachmentPoints.removeAll(failedSwitchPort);
	    deviceEvt.setAttachmentPoints(attachmentPoints);

	    if ( deviceEvt.getAttachmentPoints().isEmpty() && deviceEvt.getIpAddresses().isEmpty() ) {
		// XXX return false to represent: Nothing left to do for this event. Caller should drop event
		return false;
	    }

	// Should we return false to tell caller that the event was trimmed?
	// if ( preconditionBroken ) {
	//     return false;
	// }

	    return true;
	}

	private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvt) {
		// No show stopping precondition?
		// Prep: none
		return true;
	}

	@Override
	public void putSwitchReplicationEvent(SwitchEvent switchEvent) {
	    // TODO who is in charge of ignoring event triggered by my self?
	    // This method or caller?
	    if (prepareForAddSwitchEvent(switchEvent)) {
		putSwitch(switchEvent);
	    }
	    // TODO handle invariant violation
	}

	@Override
	public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
	    // TODO who is in charge of ignoring event triggered by my self?
	    // This method or caller?
	    if (prepareForRemoveSwitchEvent(switchEvent)) {
		removeSwitch(switchEvent);
	    }
	    // TODO Auto-generated method stub
	}

	@Override
	public void putPortReplicationEvent(PortEvent portEvent) {
	    // TODO who is in charge of ignoring event triggered by my self?
	    // This method or caller?
	    if (prepareForAddPortEvent(portEvent)) {
		putPort(portEvent);
	    }
	    // TODO Auto-generated method stub
	}

	@Override
	public void removePortReplicationEvent(PortEvent portEvent) {
	    // TODO who is in charge of ignoring event triggered by my self?
	    // This method or caller?
	    if (prepareForRemovePortEvent(portEvent)) {
		removePort(portEvent);
	    }
	    // TODO Auto-generated method stub
	}

	@Override
	public void putLinkReplicationEvent(LinkEvent linkEvent) {
	    // TODO who is in charge of ignoring event triggered by my self?
	    // This method or caller?
	    if (prepareForAddLinkEvent(linkEvent)) {
		putLink(linkEvent);
	    }
	    // TODO Auto-generated method stub
	}

	@Override
	public void removeLinkReplicationEvent(LinkEvent linkEvent) {
	    // TODO who is in charge of ignoring event triggered by my self?
	    // This method or caller?
	    if (prepareForRemoveLinkEvent(linkEvent)) {
		removeLink(linkEvent);
	    }
	    // TODO Auto-generated method stub
	}

	@Override
	public void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
	    // TODO who is in charge of ignoring event triggered by my self?
	    // This method or caller?
	    if (prepareForAddDeviceEvent(deviceEvent)) {
		putDevice(deviceEvent);
	    }
	    // TODO Auto-generated method stub
	}

	@Override
	public void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
	    // TODO who is in charge of ignoring event triggered by my self?
	    // This method or caller?
	    if (prepareForRemoveDeviceEvent(deviceEvent)) {
		removeDevice(deviceEvent);
	    }
	    // TODO Auto-generated method stub
	}
}
