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;

import edu.stanford.ramcloud.JRamCloud.ObjectDoesntExistException;

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

	    // 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()) {
	    try {
		sw.read();
		// TODO if there is going to be inactive Switch in DB, skip
		// TODO update other attributes if there exist any
		putSwitch(new SwitchEvent(sw.getDpid()));
	    } catch (ObjectDoesntExistException e) {
		log.error("Read Switch Failed, skipping", e);
	    }
	}

	for (RCPort p : RCPort.getAllPorts()) {
	    try {
		p.read();

		Switch sw = this.getSwitch(p.getDpid());
		if (sw == null) {
		    log.error("Switch {} missing when adding Port {}",
			    new Dpid(p.getDpid()), p);
		    continue;
		}
		PortEvent portEvent = new PortEvent(p.getDpid(), p.getNumber());
		// TODO update other attributes if there exist any
		putPort(portEvent);
	    } catch (ObjectDoesntExistException e) {
		log.error("Read Port Failed, skipping", e);
	    }
	}

	// TODO Is Device going to be in DB? If so, read from DB.
	// for (RCDevice d : RCDevice.getAllDevices()) {
	// try {
	// d.read();
	//
	// } catch (ObjectDoesntExistException e) {
	// log.debug("Read Device Failed, skipping", e);
	// }
	// }

	for (RCLink l : RCLink.getAllLinks()) {
	    try {
		l.read();

		Switch srcSw = this.getSwitch(l.getSrc().dpid);
		if (srcSw == null) {
		    log.error("Switch {} missing when adding Link {}",
			    new Dpid(l.getSrc().dpid), l);
		    continue;
		}

		Switch dstSw = this.getSwitch(l.getDst().dpid);
		if (dstSw == null) {
		    log.error("Switch {} missing when adding Link {}",
			    new Dpid(l.getDst().dpid), l);
		    continue;
		}

		LinkEvent linkEvent = new LinkEvent(l.getSrc().dpid,
			l.getSrc().number, l.getDst().dpid, l.getDst().number);
		// TODO update other attributes if there exist any
		putLink(linkEvent);
	    } catch (ObjectDoesntExistException e) {
		log.debug("Delete Link Failed", e);
	    }
	}
    }

    /**
     * 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) {
		if (prepareForAddSwitchEvent(switchEvent)) {
			putSwitch(switchEvent);
		}
		// TODO handle invariant violation
	}

	@Override
	public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
	    // TODO Auto-generated method stub

	}

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

	}

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

	}

	@Override
	public void putLinkReplicationEvent(LinkEvent linkEvent) {
	    // TODO Auto-generated method stub

	}

	@Override
	public void removeLinkReplicationEvent(LinkEvent linkEvent) {
	    // TODO Auto-generated method stub

	}

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

	}

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

	}
}
