package net.onrc.onos.ofcontroller.topology;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.onrc.onos.datagrid.IDatagridService;
import net.onrc.onos.graph.DBOperation;
import net.onrc.onos.graph.GraphDBManager;
import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
import net.onrc.onos.ofcontroller.topology.web.OnosTopologyWebRoutable;
import net.onrc.onos.ofcontroller.util.DataPath;
import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.FlowPath;
import net.onrc.onos.ofcontroller.util.Port;
import net.onrc.onos.ofcontroller.util.SwitchPort;

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

/**
 * A class for obtaining Topology Snapshot
 * and PathComputation.
 *
 * TODO: PathComputation part should be refactored out to separate class.
 */
public class TopologyManager implements IFloodlightModule,
					ITopologyNetService {
    private final static Logger log = LoggerFactory.getLogger(TopologyManager.class);
    protected IFloodlightProviderService floodlightProvider;

    protected static final String DBConfigFile = "dbconf";
    protected static final String GraphDBStore = "graph_db_store";

    protected DBOperation dbHandler;
    protected IRestApiService restApi;


    /**
     * Default constructor.
     */
    public TopologyManager() {
    }

    /**
     * Constructor for given database configuration file.
     *
     * @param config the database configuration file to use for
     * the initialization.
     */
    public TopologyManager(FloodlightModuleContext context) {
	Map<String, String> configMap = context.getConfigParams(this);
	String conf = configMap.get(DBConfigFile);
        String dbStore = configMap.get(GraphDBStore);
	this.init(dbStore,conf);
    }

    /**
     * Constructor for a given database operation handler.
     *
     * @param dbHandler the database operation handler to use for the
     * initialization.
     */
    public TopologyManager(DBOperation dbHandler) {
	this.dbHandler = dbHandler;
    }

    /**
     * Init the module.
     *
     * @param config the database configuration file to use for
     * the initialization.
     */
    public void init(final String dbStore, String config) {
	try {
	    dbHandler = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloud.conf");
	} catch (Exception e) {
	    log.error(e.getMessage());
	}
    }

    /**
     * Shutdown the Topology Manager operation.
     */
    @Override
    protected void finalize() {
	close();
    }

    /**
     * Close the service. It will close the corresponding database connection.
     */
    public void close() {
	dbHandler.close();
    }

    /**
     * Get the collection of offered module services.
     *
     * @return the collection of offered module services.
     */
    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        Collection<Class<? extends IFloodlightService>> l =
            new ArrayList<Class<? extends IFloodlightService>>();
        l.add(ITopologyNetService.class);
        return l;
    }

    /**
     * Get the collection of implemented services.
     *
     * @return the collection of implemented services.
     */
    @Override
    public Map<Class<? extends IFloodlightService>, IFloodlightService>
			       getServiceImpls() {
        Map<Class<? extends IFloodlightService>,
	    IFloodlightService> m =
            new HashMap<Class<? extends IFloodlightService>,
	    IFloodlightService>();
        m.put(ITopologyNetService.class, this);
        return m;
    }

    /**
     * Get the collection of modules this module depends on.
     *
     * @return the collection of modules this module depends on.
     */
    @Override
    public Collection<Class<? extends IFloodlightService>>
                                                    getModuleDependencies() {
	Collection<Class<? extends IFloodlightService>> l =
	    new ArrayList<Class<? extends IFloodlightService>>();
	l.add(IFloodlightProviderService.class);
	l.add(INetworkGraphService.class);
	l.add(IDatagridService.class);
        return l;
    }

    /**
     * Initialize the module.
     *
     * @param context the module context to use for the initialization.
     */
    @Override
    public void init(FloodlightModuleContext context)
	throws FloodlightModuleException {
	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
	restApi = context.getServiceImpl(IRestApiService.class);
	Map<String, String> configMap = context.getConfigParams(this);
	String conf = configMap.get(DBConfigFile);
        String dbStore = configMap.get(GraphDBStore);
	this.init(dbStore, conf);
    }

    /**
     * Startup module operation.
     *
     * @param context the module context to use for the startup.
     */
    @Override
    public void startUp(FloodlightModuleContext context) {
    	restApi.addRestletRoutable(new OnosTopologyWebRoutable());

    }

    /**
     * Fetch the Switch and Ports info from the Titan Graph
     * and return it for fast access during the shortest path
     * computation.
     *
     * After fetching the state, method @ref getTopologyShortestPath()
     * can be used for fast shortest path computation.
     *
     * Note: There is certain cost to fetch the state, hence it should
     * be used only when there is a large number of shortest path
     * computations that need to be done on the same topology.
     * Typically, a single call to @ref newDatabaseTopology()
     * should be followed by a large number of calls to
     * method @ref getTopologyShortestPath().
     * After the last @ref getTopologyShortestPath() call,
     * method @ref dropTopology() should be used to release
     * the internal state that is not needed anymore:
     *
     *       Topology topology = topologyManager.newDatabaseTopology();
     *       for (int i = 0; i < 10000; i++) {
     *           dataPath = topologyManager.getTopologyShortestPath(topology, ...);
     *           ...
     *        }
     *        topologyManager.dropTopology(shortestPathTopo);
     *
     * @return the allocated topology handler.
     */
    @Override
    public Topology newDatabaseTopology() {
	Topology topology = new Topology();
	topology.readFromDatabase(dbHandler);

	return topology;
    }

    /**
     * Release the topology that was populated by
     * method @ref newDatabaseTopology().
     *
     * See the documentation for method @ref newDatabaseTopology()
     * for additional information and usage.
     *
     * @param topology the topology to release.
     */
    @Override
    public void dropTopology(Topology topology) {
    // nothing to do
    }

    /**
     * Compute the network path for a Flow.
     *
     * @param topology the topology handler to use.
     * @param flowPath the Flow to compute the network path for.
     * @return the data path with the computed path if found, otherwise null.
     */
    public static DataPath computeNetworkPath(Topology topology,
					      FlowPath flowPath) {
	//
	// Compute the network path based on the desired Flow Path type
	//
	switch (flowPath.flowPathType()) {
	case FP_TYPE_SHORTEST_PATH: {
	    SwitchPort src = flowPath.dataPath().srcPort();
	    SwitchPort dest = flowPath.dataPath().dstPort();
	    return ShortestPath.getTopologyShortestPath(topology, src, dest);
	}

	case FP_TYPE_EXPLICIT_PATH:
	    return flowPath.dataPath();

	case FP_TYPE_UNKNOWN:
	    return null;
	}

	return null;
    }

    /**
     * Test whether two Flow Entries represent same points in a data path.
     *
     * NOTE: Two Flow Entries represent same points in a data path if
     * the Switch DPID, incoming port and outgoing port are same.
     *
     * NOTE: This method is specialized for shortest-path unicast paths,
     * and probably should be moved somewhere else.
     *
     * @param oldFlowEntry the first Flow Entry to compare.
     * @param newFlowEntry the second Flow Entry to compare.
     * @return true if the two Flow Entries represent same points in a
     * data path, otherwise false.
     */
    public static boolean isSameFlowEntryDataPath(FlowEntry oldFlowEntry,
						  FlowEntry newFlowEntry) {
	// Test the DPID
	if (oldFlowEntry.dpid().value() != newFlowEntry.dpid().value())
	    return false;

	// Test the inPort
	do {
	    Port oldPort = oldFlowEntry.inPort();
	    Port newPort = newFlowEntry.inPort();
	    if ((oldPort != null) && (newPort != null) &&
		(oldPort.value() == newPort.value())) {
		break;
	    }
	    if ((oldPort == null) && (newPort == null))
		break;
	    return false;		// inPort is different
	} while (false);

	// Test the outPort
	do {
	    Port oldPort = oldFlowEntry.outPort();
	    Port newPort = newFlowEntry.outPort();
	    if ((oldPort != null) && (newPort != null) &&
		(oldPort.value() == newPort.value())) {
		break;
	    }
	    if ((oldPort == null) && (newPort == null))
		break;
	    return false;		// outPort is different
	} while (false);

	return true;
    }

    /**
     * Get the shortest path from a source to a destination by
     * using the pre-populated local topology state prepared
     * by method @ref newDatabaseTopology().
     *
     * See the documentation for method @ref newDatabaseTopology()
     * for additional information and usage.
     *
     * @param topology the topology handler to use.
     * @param src the source in the shortest path computation.
     * @param dest the destination in the shortest path computation.
     * @return the data path with the computed shortest path if
     * found, otherwise null.
     */
    @Override
    public DataPath getTopologyShortestPath(Topology topology,
					    SwitchPort src, SwitchPort dest) {
	return ShortestPath.getTopologyShortestPath(topology, src, dest);
    }

    /**
     * Get the shortest path from a source to a destination by using
     * the underlying database.
     *
     * @param src the source in the shortest path computation.
     * @param dest the destination in the shortest path computation.
     * @return the data path with the computed shortest path if
     * found, otherwise null.
     */
    @Override
    public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
	return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
    }

    /**
     * Test whether a route exists from a source to a destination.
     *
     * @param src the source node for the test.
     * @param dest the destination node for the test.
     * @return true if a route exists, otherwise false.
     */
    @Override
    public Boolean routeExists(SwitchPort src, SwitchPort dest) {
	DataPath dataPath = getDatabaseShortestPath(src, dest);
	return (dataPath != null);
    }
}
