/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.onrc.onos.graph;

import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.FramedGraph;
import com.tinkerpop.frames.structures.FramedVertexIterable;
import com.tinkerpop.gremlin.java.GremlinPipeline;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IBaseObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IIpv4Address;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.core.ISwitchStorage;
import net.onrc.onos.ofcontroller.util.FlowEntryId;
import net.onrc.onos.ofcontroller.util.FlowId;

/**
 *
 * @author nickkaranatsios
 */
public abstract class DBOperation implements IDBOperation {

	protected DBConnection conn;

	/**
	 * Search and get an active switch object with DPID.
	 * @param dpid DPID of the switch
	 */
	@Override
	public ISwitchObject searchActiveSwitch(String dpid) {
	    ISwitchObject sw = searchSwitch(dpid);
	    if ((sw != null)
		    && sw.getState().equals(ISwitchStorage.SwitchState.ACTIVE.toString())) {
		return sw;
	    }
	    return null;
	}

	/**
	 * Create a new switch and return the created switch object.
	 * @param dpid DPID of the switch
	 */
	@Override
	public ISwitchObject newSwitch(final String dpid) {
	    //System.out.println("newSwitch");
	    ISwitchObject obj = (ISwitchObject) conn.getFramedGraph().addVertex(null, ISwitchObject.class);
	    if (obj != null) {
		obj.setType("switch");
		obj.setDPID(dpid);
	    }
	    return obj;
	}

	/**
	 * Get all switch objects.
	 */
	@Override
	public Iterable<ISwitchObject> getAllSwitches() {
	    //System.out.println("getAllSwitches");
	    Iterable<ISwitchObject> switches = conn.getFramedGraph().getVertices("type", "switch", ISwitchObject.class);
	    return switches;
	}

	/**
	 * Get all inactive switch objects.
	 */
	@Override
	public Iterable<ISwitchObject> getInactiveSwitches() {
	    //System.out.println("getInactiveSwitches");
	    Iterable<ISwitchObject> switches = conn.getFramedGraph().getVertices("type", "switch", ISwitchObject.class);
	    List<ISwitchObject> inactiveSwitches = new ArrayList<ISwitchObject>();

	    for (ISwitchObject sw : switches) {
		if (sw.getState().equals(ISwitchStorage.SwitchState.INACTIVE.toString())) {
		    inactiveSwitches.add(sw);
		}
	    }
	    return inactiveSwitches;
	}

	/**
	 * Get all flow entries objects where their switches are not updated.
	 */
	@Override
	public Iterable<INetMapTopologyObjects.IFlowEntry> getAllSwitchNotUpdatedFlowEntries() {
	    //TODO: Should use an enum for flow_switch_state
	    return conn.getFramedGraph().getVertices("switch_state", "FE_SWITCH_NOT_UPDATED", INetMapTopologyObjects.IFlowEntry.class);

	}

	/**
	 * Remove specified switch.
	 * @param sw switch object to remove
	 */
	@Override
	public void removeSwitch(ISwitchObject sw) {
	    //System.out.println("removeSwitch");
	    conn.getFramedGraph().removeVertex(sw.asVertex());
	}

	@Override
	public IPortObject newPort(String dpid, Short portNum) {
	    //System.out.println("newPort");
	    IPortObject obj = (IPortObject) conn.getFramedGraph().addVertex(null, IPortObject.class);
	    if (obj != null) {
		obj.setType("port");
		String id = dpid + portNum.toString();
		obj.setPortId(id);
		obj.setNumber(portNum);
	    }
	    return obj;
	}

	/**
	* Create a port having specified port number.
	*
	* @param portNumber port number
	*/
	@Override
	@Deprecated
	public IPortObject newPort(Short portNumber) {
	    IPortObject obj = (IPortObject) conn.getFramedGraph().addVertex(null, IPortObject.class);
	    if (obj != null) {
		obj.setType("port");
		obj.setNumber(portNumber);
	    }
	    return obj;
	}

	/**
	 * Search and get a port object of specified switch and port number.
	 * @param dpid DPID of a switch
	 * @param number port number of the switch's port
	 */
	@Override
	public IPortObject searchPort(String dpid, Short number) {
	    FramedGraph fg = conn.getFramedGraph();
	    if ( fg == null ) return null;
	    String id = dpid + number.toString();
	    Iterator<IPortObject> it = fg.getVertices("port_id", id, IPortObject.class).iterator();
	    return (it.hasNext()) ? it.next() : null;

	}

	/**
	 * Remove the specified switch port.
	 * @param port switch port object to remove
	 */
	@Override
	public void removePort(IPortObject port) {
	    //System.out.println("removeProt");
	    if (conn.getFramedGraph() != null) {
		conn.getFramedGraph().removeVertex(port.asVertex());
	    }
	}

	/**
	 * Create and return a device object.
	 */
	@Override
	public IDeviceObject newDevice() {
	    //System.out.println("newDevice");
	    IDeviceObject obj = (IDeviceObject) conn.getFramedGraph().addVertex(null, IDeviceObject.class);
	    if (obj != null) {
		obj.setType("device");
	    }
	    return obj;
	}

	/**
	 * Get all devices.
	 */
	@Override
	public Iterable<IDeviceObject> getDevices() {
	    //System.out.println("getDeiveces");
	    return conn.getFramedGraph() != null ? conn.getFramedGraph().getVertices("type", "device", IDeviceObject.class) : null;
	}

	/**
	 * Remove the specified device.
	 * @param dev a device object to remove
	 */
	@Override
	public void removeDevice(IDeviceObject dev) {
	    //System.out.println("removeDevice");
	    if (conn.getFramedGraph() != null) {
		conn.getFramedGraph().removeVertex(dev.asVertex());
	    }
	}

	/**
	* Create and return a flow path object.
	*/
	@Override
	public IFlowPath newFlowPath() {
	    //System.out.println("newFlowPath");
	    IFlowPath flowPath = (IFlowPath)conn.getFramedGraph().addVertex(null, IFlowPath.class);
	    //System.out.println("flowPath : " + flowPath);
	    if (flowPath != null) {
		flowPath.setType("flow");
	    }
	    return flowPath;
	}

	/**
	 * Get a flow path object with a flow entry.
	 * @param flowEntry flow entry object
	 */
	@Override
	public IFlowPath getFlowPathByFlowEntry(INetMapTopologyObjects.IFlowEntry flowEntry) {
	    GremlinPipeline<Vertex, IFlowPath> pipe = new GremlinPipeline<Vertex, IFlowPath>();
	    pipe.start(flowEntry.asVertex());
	    pipe.out("flow");
	    FramedVertexIterable<IFlowPath> r = new FramedVertexIterable(conn.getFramedGraph(), pipe, IFlowPath.class);
	    return r.iterator().hasNext() ? r.iterator().next() : null;
	}


	/**
	* Search and get a switch object with DPID.
	*
	* @param dpid DPID of the switch
	*/
	@Override
	public ISwitchObject searchSwitch(final String dpid) {
	    FramedGraph fg = conn.getFramedGraph();
	    if ( fg == null ) return null;
	    Iterator<ISwitchObject> it = fg.getVertices("dpid", dpid, ISwitchObject.class).iterator();
	    return (it.hasNext()) ? it.next() : null;
	}

	/**
	 * Get all active switch objects.
	 */
	@Override
	public Iterable<ISwitchObject> getActiveSwitches() {
	    Iterable<ISwitchObject> switches = conn.getFramedGraph().getVertices("type", "switch", ISwitchObject.class);
	    List<ISwitchObject> activeSwitches = new ArrayList<ISwitchObject>();

	    for (ISwitchObject sw : switches) {
		if (sw.getState().equals(ISwitchStorage.SwitchState.ACTIVE.toString())) {
		    activeSwitches.add(sw);
		}
	    }
	    return activeSwitches;
	}

	/**
	 * Search and get a device object having specified MAC address.
	 * @param macAddr MAC address to search and get
	 */
	@Override
	public IDeviceObject searchDevice(String macAddr) {
	    FramedGraph fg = conn.getFramedGraph();
	    if ( fg == null ) return null;
	    Iterator<IDeviceObject> it = fg.getVertices("dl_addr", macAddr, IDeviceObject.class).iterator();
	    return (it.hasNext()) ? it.next() : null;
	}

	/**
	 * Search and get a flow path object with specified flow ID.
	 * @param flowId flow ID to search
	 */
	@Override
	public IFlowPath searchFlowPath(final FlowId flowId) {
	    FramedGraph fg = conn.getFramedGraph();
	    if ( fg == null ) return null;
	    Iterator<IFlowPath> it = fg.getVertices("flow_id", flowId.toString(), IFlowPath.class).iterator();
	    return (it.hasNext()) ? it.next() : null;
	}

	/**
	 * Get all flow path objects.
	 */
	@Override
	public Iterable<IFlowPath> getAllFlowPaths() {
	    //System.out.println("getAllFlowPaths");
	    Iterable<IFlowPath> flowPaths = conn.getFramedGraph().getVertices("type", "flow", IFlowPath.class);

	    List<IFlowPath> nonNullFlows = new ArrayList<IFlowPath>();

	    for (IFlowPath fp : flowPaths) {
		if (fp.getFlowId() != null) {
		    nonNullFlows.add(fp);
		}
	    }
	    return nonNullFlows;
	}

	/**
	 * Remove the specified flow path.
	 * @param flowPath flow path object to remove
	 */
	@Override
	public void removeFlowPath(IFlowPath flowPath) {
	    //System.out.println("removeFlowPath");
	    conn.getFramedGraph().removeVertex(flowPath.asVertex());
	}

	/**
	 * Search and get a flow entry object with flow entry ID.
	 * @param flowEntryId flow entry ID to search
	 */
	@Override
	public IFlowEntry searchFlowEntry(FlowEntryId flowEntryId) {
	    FramedGraph fg = conn.getFramedGraph();
	    if ( fg == null ) return null;
	    Iterator<IFlowEntry> it = fg.getVertices("flow_entry_id", flowEntryId.toString(), IFlowEntry.class).iterator();
	    return (it.hasNext()) ? it.next() : null;
	}

	/**
	 * Get all flow entry objects.
	 */
	@Override
	public Iterable<IFlowEntry> getAllFlowEntries() {
	    return conn.getFramedGraph().getVertices("type", "flow_entry", IFlowEntry.class);
	}

	/**
	 * Remove the specified flow entry.
	 * @param flowEntry flow entry object to remove
	 */
	@Override
	public void removeFlowEntry(IFlowEntry flowEntry) {
	    //System.out.println("removeFlowEntry");
	    conn.getFramedGraph().removeVertex(flowEntry.asVertex());
	}

	/**
	 * Create and return a flow entry object.
	 */
	@Override
	public IFlowEntry newFlowEntry() {
	    //System.out.println("newFlowEntry");
	    IFlowEntry flowEntry = (IFlowEntry) conn.getFramedGraph().addVertex(null, IFlowEntry.class);
	    if (flowEntry != null) {
		flowEntry.setType("flow_entry");
	    }
	    return flowEntry;
	}


	public IIpv4Address newIpv4Address() {
		return newVertex("ipv4Address", IIpv4Address.class);
	}

	private <T extends IBaseObject> T newVertex(String type, Class<T> vertexType) {
		T newVertex = (T) conn.getFramedGraph().addVertex(null, vertexType);
		if (newVertex != null) {
			newVertex.setType(type);
		}
		return newVertex;
	}

	public IIpv4Address searchIpv4Address(int intIpv4Address) {
		return searchForVertex("ipv4_address", intIpv4Address, IIpv4Address.class);
	}


	public IIpv4Address ensureIpv4Address(int intIpv4Address) {
		IIpv4Address ipv4Vertex = searchIpv4Address(intIpv4Address);
		if (ipv4Vertex == null) {
			ipv4Vertex = newIpv4Address();
			ipv4Vertex.setIpv4Address(intIpv4Address);
		}
		return ipv4Vertex;
	}


	private <T> T searchForVertex(String propertyName, Object propertyValue, Class<T> vertexType) {
		if (conn.getFramedGraph() != null) {
			Iterator<T> it = conn.getFramedGraph().getVertices(propertyName, propertyValue, vertexType).iterator();
			if (it.hasNext()) {
				return it.next();
			}
		}
		return null;
	}

	public void removeIpv4Address(IIpv4Address ipv4Address) {
		//System.out.println("removeIpv4Address");
		conn.getFramedGraph().removeVertex(ipv4Address.asVertex());
	}

	/**
	 * Get the instance of GraphDBConnection assigned to this class.
	 */
	@Override
	public IDBConnection getDBConnection() {
	    return conn;
	}

	@Override
	public void commit() {
	    conn.commit();
	}

	@Override
	public void rollback() {
	    conn.rollback();
	}

	@Override
	public void close() {
	    conn.close();
	}
}
