package net.onrc.onos.graph;

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

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.SwitchState;
import net.onrc.onos.ofcontroller.util.FlowEntryId;
import net.onrc.onos.ofcontroller.util.FlowId;

import com.thinkaurelius.titan.core.TitanGraph;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.FramedGraph;
import com.tinkerpop.frames.structures.FramedVertexIterable;
import com.tinkerpop.gremlin.java.GremlinPipeline;

public class GraphDBOperation implements IDBOperation {
	private GraphDBConnection conn;

	/**
	 * Create a GraphDBOperation instance from specified GraphDBConnection's instance.
	 * @param dbConnection an instance of GraphDBConnection
	 */
	public GraphDBOperation(GraphDBConnection dbConnection) {
		this.conn = dbConnection;
	}

	/**
	 * Create a GraphDBOperation instance from database configuration path.
	 * @param dbConfPath a path for database configuration file.
	 */
	public GraphDBOperation(final String dbConfPath) {
		this.conn = GraphDBConnection.getInstance(dbConfPath);
	}

	/**
	 * Create a new switch and return the created switch object.
	 * @param dpid DPID of the switch
	 */
	public ISwitchObject newSwitch(String dpid) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		ISwitchObject obj = fg.addVertex(null,ISwitchObject.class);
		if (obj != null) {
			obj.setType("switch");
			obj.setDPID(dpid);
		}
		return obj;
	}

	/**
	 * Search and get a switch object with DPID.
	 * @param dpid DPID of the switch 
	 */
	public ISwitchObject searchSwitch(String dpid) {

		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		if ( fg == null ) return null;
		Iterator<ISwitchObject> it = fg.getVertices("dpid",dpid,ISwitchObject.class).iterator();
		return (it.hasNext()) ? it.next() : null;

	}

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

	/**
	 * Get all switch objects.
	 */
	public Iterable<ISwitchObject> getAllSwitches() {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
		return switches;
	}

	/**
	 * Get all active switch objects.
	 */
	public Iterable<ISwitchObject> getActiveSwitches() {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
		List<ISwitchObject> activeSwitches = new ArrayList<ISwitchObject>();
	
		for (ISwitchObject sw: switches) {
			if(sw.getState().equals(SwitchState.ACTIVE.toString())) {
				activeSwitches.add(sw);
			}
		}
		return activeSwitches;
	}

	/**
	 * Get all inactive switch objects.
	 */
	public Iterable<ISwitchObject> getInactiveSwitches() {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
		List<ISwitchObject> inactiveSwitches = new ArrayList<ISwitchObject>();
	
		for (ISwitchObject sw: switches) {
			if(sw.getState().equals(SwitchState.INACTIVE.toString())) {
				inactiveSwitches.add(sw);
			}
		}
		return inactiveSwitches;
	}

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

	/**
	 * Remove specified switch.
	 * @param sw switch object to remove
	 */
	public void removeSwitch(ISwitchObject sw) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		fg.removeVertex(sw.asVertex());		
	}
	
	@Override
	public IPortObject newPort(String dpid, Short portNumber) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		IPortObject obj = fg.addVertex(null,IPortObject.class);
		if (obj != null) {
			obj.setType("port");
			String id = dpid + portNumber.toString();
			obj.setPortId(id);
			obj.setNumber(portNumber);
		}
		return obj;	
		
	}

	/**
	 * Create a port having specified port number.
	 * @param portNumber port number
	 */
	@Deprecated
	public IPortObject newPort(Short portNumber) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		IPortObject obj = fg.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
	 */
	public IPortObject searchPort(String dpid, Short number) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		if ( fg == null ) return null;
		String id = dpid + number.toString();
		Iterator<IPortObject> ports =  fg.getVertices("port_id",id,IPortObject.class).iterator();
		if ( ports.hasNext() ) {
			return ports.next();
		} else {
			return null;
		}
	}

	/**
	 * Remove the specified switch port.
	 * @param port switch port object to remove
	 */
	public void removePort(IPortObject port) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
//		EventGraph<TitanGraph> eg = conn.getEventGraph();
		if (fg != null) fg.removeVertex(port.asVertex());		
	}

	/**
	 * Create and return a device object.
	 */
	public IDeviceObject newDevice() {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		IDeviceObject obj = fg.addVertex(null,IDeviceObject.class);
		if (obj != null) obj.setType("device");
		return obj;
	}

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

	/**
	 * Get all devices.
	 */
	public Iterable<IDeviceObject> getDevices() {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		return fg != null ? fg.getVertices("type","device",IDeviceObject.class) : null;
	}

	/**
	 * Remove the specified device.
	 * @param dev a device object to remove
	 */
	public void removeDevice(IDeviceObject dev) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		if (fg != null) fg.removeVertex(dev.asVertex());		
	}
	
	public IIpv4Address newIpv4Address() {
		return newVertex("ipv4Address", IIpv4Address.class);
	}
	
	private <T extends IBaseObject> T newVertex(String type, Class<T> vertexType) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		T newVertex = fg.addVertex(null, vertexType);
		if (newVertex != null) {
			newVertex.setType(type);
		}
		return newVertex;
	}
	
	public IIpv4Address searchIpv4Address(int intIpv4Address) {
		return searchForVertex("ipv4_address", intIpv4Address, IIpv4Address.class);
	}
	
	private <T> T searchForVertex(String propertyName, Object propertyValue, Class<T> vertexType) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		if (fg != null) {
			Iterator<T> it = 
					fg.getVertices(propertyName, propertyValue, vertexType).iterator();
			if (it.hasNext()) {
				return it.next();
			}
		}
		return null;
	}
	
	public IIpv4Address ensureIpv4Address(int intIpv4Address) {
		IIpv4Address ipv4Vertex = searchIpv4Address(intIpv4Address);
		if (ipv4Vertex == null) {
			ipv4Vertex = newIpv4Address();
			ipv4Vertex.setIpv4Address(intIpv4Address);
		}
		return ipv4Vertex;
	}
	
	public void removeIpv4Address(IIpv4Address ipv4Address) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		fg.removeVertex(ipv4Address.asVertex());
	}

	/**
	 * Create and return a flow path object.
	 */
	public IFlowPath newFlowPath() {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		IFlowPath flowPath = fg.addVertex(null, IFlowPath.class);
		if (flowPath != null) flowPath.setType("flow");
		return flowPath;
	}

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

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

	/**
	 * Get all flow path objects.
	 */
    public Iterable<IFlowPath> getAllFlowPaths() {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		Iterable<IFlowPath> flowPaths = fg.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
     */
	public void removeFlowPath(IFlowPath flowPath) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		fg.removeVertex(flowPath.asVertex());
	}

	/**
	 * Create and return a flow entry object.
	 */
	public IFlowEntry newFlowEntry() {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
		IFlowEntry flowEntry = fg.addVertex(null, IFlowEntry.class);
		if (flowEntry != null) flowEntry.setType("flow_entry");
		return flowEntry;
	}

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

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

	/**
	 * Remove the specified flow entry.
	 * @param flowEntry flow entry object to remove
	 */
	public void removeFlowEntry(IFlowEntry flowEntry) {
		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
		fg.removeVertex(flowEntry.asVertex());
	}
	
	/**
	 * Get the instance of GraphDBConnection assigned to this class.
	 */
	public IDBConnection getDBConnection() {
		return conn;
	}
	
	/**
	 * Commit changes for the graph.
	 */
	public void commit() {
		conn.commit();
	}

	/**
	 * Rollback changes for the graph.
	 */
	public void rollback() {
		conn.rollback();
	}

	/**
	 * Close the connection of the assigned GraphDBConnection.
	 */
	public void close() {
		conn.close();
	}


}
