package net.onrc.onos.ofcontroller.networkgraph;

import java.util.ArrayList;
import java.util.List;

import net.onrc.onos.datastore.RCObject;
import net.onrc.onos.datastore.RCObject.WriteOp;
import net.onrc.onos.datastore.topology.RCLink;
import net.onrc.onos.datastore.topology.RCPort;
import net.onrc.onos.datastore.topology.RCPort.STATUS;
import net.onrc.onos.datastore.topology.RCSwitch;

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

/**
 * The southbound interface to the network graph which allows clients to
 * mutate the graph. This class will maintain the invariants of the network
 * graph. The southbound discovery modules will use this interface to update
 * the network graph as they learn about the state of the network.
 *
 * Modification to the Network Map by this module will:
 * 1. Writes to Cluster-wide DataStore.
 * 2. Update ONOS instance In-memory Network Map.
 * 3. Send-out Notification. (TBD)
 *    (XXX: To update other instances In-memory Network Map,
 *          notification should be triggered here.
 *          But if we want to aggregate notification to minimize notification,
 *          It might be better for the caller to trigger notification.)
 *
 */
public class NetworkGraphDatastore {
	private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);

	/**
	 * Add a switch to the database.
	 *
	 * @param sw the switch to add.
	 * @return true on success, otherwise false.
	 */
	public boolean addSwitch(SwitchEvent sw) {
		log.debug("Adding switch {}", sw);
		ArrayList<WriteOp> groupOp = new ArrayList<>();

		RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
		rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);

		// XXX Is ForceCreating Switch on DB OK here?
		// If ForceCreating, who ever is calling this method needs
		// to assure that DPID is unique cluster-wide, etc.
		groupOp.add(WriteOp.ForceCreate(rcSwitch));

		for (PortEvent portEvent : sw.getPorts()) {
			RCPort rcPort = new RCPort(sw.getDpid(), portEvent.getNumber());
			rcPort.setStatus(RCPort.STATUS.ACTIVE);

			groupOp.add(WriteOp.ForceCreate(rcPort));
		}

		boolean failed = RCObject.multiWrite(groupOp);

		if (failed) {
		    log.error("Adding Switch {} and its ports failed.", sw.getDpid());
		    for (WriteOp op : groupOp) {
			log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );

			// If we changed the operation from ForceCreate to
			// Conditional operation (Create/Update) then we should retry here.
		    }
		}
		return !failed;
	}

	/**
	 * Update a switch as inactive in the database.
	 *
	 * @param sw the switch to update.
	 * @return true on success, otherwise false.
	 */
	public boolean deactivateSwitch(SwitchEvent sw) {
		log.debug("Deactivating switch {}", sw);
		RCSwitch rcSwitch = new RCSwitch(sw.getDpid());

		List<WriteOp> groupOp = new ArrayList<>();
		rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);

		groupOp.add(WriteOp.ForceCreate(rcSwitch));

		for (PortEvent portEvent : sw.getPorts()) {
			RCPort rcPort = new RCPort(sw.getDpid(), (long)portEvent.getNumber());
			rcPort.setStatus(RCPort.STATUS.INACTIVE);

			groupOp.add(WriteOp.ForceCreate(rcPort));
		}

		boolean failed = RCObject.multiWrite(groupOp);
		
		return !failed;
	}

	/**
	 * Add a port to the database.
	 *
	 * @param port the port to add.
	 * @return true on success, otherwise false.
	 */
	public boolean addPort(PortEvent port) {
		log.debug("Adding port {}", port);

		RCPort rcPort = new RCPort(port.getDpid(), port.getNumber());
		rcPort.setStatus(RCPort.STATUS.ACTIVE);
		rcPort.forceCreate();
		// TODO add description into RCPort
		//rcPort.setDescription(port.getDescription());

		return true;
	}

	/**
	 * Update a port as inactive in the database.
	 *
	 * @param port the port to update.
	 * @return true on success, otherwise false.
	 */
	public boolean deactivatePort(PortEvent port) {
		log.debug("Deactivating port {}", port);
		
		RCPort rcPort = new RCPort(port.getDpid(), port.getNumber());
		rcPort.setStatus(STATUS.INACTIVE);
		
		rcPort.forceCreate();

		return true;
	}

	/**
	 * Add a link to the database.
	 *
	 * @param link the link to add.
	 * @return true on success, otherwise false.
	 */
	public boolean addLink(LinkEvent link) {
		log.debug("Adding link {}", link);

		RCLink rcLink = new RCLink(link.getSrc().getDpid(),
					   link.getSrc().getNumber(),
					   link.getDst().getDpid(),
					   link.getDst().getNumber());

		// XXX This method is called only by discovery,
		// which means what we are trying to write currently is the truth
		// so we can force write here
		//
		// TODO: We need to check for errors
		rcLink.setStatus(RCLink.STATUS.ACTIVE);
		rcLink.forceCreate();

		return true;					// Success
	}

	public boolean removeLink(LinkEvent linkEvent) {
		log.debug("Removing link {}", linkEvent);
		
		RCLink rcLink = new RCLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
				linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
		rcLink.forceDelete();

		return true;
	}

	/**
	 * Add a device to the database.
	 *
	 * @param device the device to add.
	 * @return true on success, otherwise false.
	 */
	public boolean addDevice(DeviceEvent device) {
		// TODO implement
		return false;			// Failure: not implemented yet
	}

	/**
	 * Remove a device from the database.
	 *
	 * @param device the device to remove.
	 * @return true on success, otherwise false.
	 */
	public boolean removeDevice(DeviceEvent device) {
		// TODO implement
		return false;			// Failure: not implemented yet
	}
}
