package net.onrc.onos.ofcontroller.core.internal;

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

import net.floodlightcontroller.routing.Link;
import net.onrc.onos.graph.DBOperation;
import net.onrc.onos.ofcontroller.core.ILinkStorage;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;

import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.pipes.PipeFunction;
import com.tinkerpop.pipes.transform.PathPipe;
import net.onrc.onos.graph.GraphDBManager;

/**
 * This is the class for storing the information of links into GraphDB
 */
public class LinkStorageImpl implements ILinkStorage {

	protected final static Logger log = LoggerFactory.getLogger(LinkStorageImpl.class);
	protected DBOperation dbop;

	/**
	 * Initialize the object. Open LinkStorage using given configuration file.
	 * @param conf Path (absolute path for now) to configuration file.
	 */
	@Override
	public void init(final String dbStore, final String conf) {
		//this.dbop = GraphDBManager.getDBOperation(dbStore, conf);
		this.dbop = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloudconf");

	}

	// Method designing policy:
	//  op.commit() and op.rollback() MUST called in public (first-class) methods.
	//  A first-class method MUST NOT call other first-class method.
	//  Routine process should be implemented in private method.
	//  A private method MUST NOT call commit or rollback.

	
	/**
	 * Update a record in the LinkStorage in a way provided by dmop.
	 * @param link Record of a link to be updated.
	 * @param linkinfo Meta-information of a link to be updated.
	 * @param dmop Operation to be done.
	 */
	@Override
	public boolean update(Link link, LinkInfo linkinfo, DM_OPERATION dmop) {
		boolean success = false;
		
		switch (dmop) {
		case CREATE:
		case INSERT:
			if (link != null) {
				try {
					if (addLinkImpl(link)) {
						dbop.commit();
						success = true;
					}
				} catch (Exception e) {
					dbop.rollback();
					e.printStackTrace();
		        	log.error("LinkStorageImpl:update {} link:{} failed", dmop, link);
				}
			}
			break;
		case UPDATE:
			if (link != null && linkinfo != null) {
				try {
					if (setLinkInfoImpl(link, linkinfo)) {
						dbop.commit();
						success = true;
					}
				} catch (Exception e) {
					dbop.rollback();
					e.printStackTrace();
		        	log.error("LinkStorageImpl:update {} link:{} failed", dmop, link);
				}
			}
			break;
		case DELETE:
			if (link != null) {
				try {
					if (deleteLinkImpl(link)) {
						dbop.commit();
						success = true;
		            	log.debug("LinkStorageImpl:update {} link:{} succeeded", dmop, link);
		            } else {
						dbop.rollback();
		            	log.debug("LinkStorageImpl:update {} link:{} failed", dmop, link);
					}
				} catch (Exception e) {
					dbop.rollback();
					e.printStackTrace();
					log.error("LinkStorageImpl:update {} link:{} failed", dmop, link);
				}
			}
			break;
		}
		
		return success;
	}

	@Override
	public boolean addLink(Link link) {
		return addLink(link, null);
	}

	private void deleteDeviceOnPort(Long dpid, Short number)
	{
		IPortObject srcPortObject = dbop.searchPort(HexString.toHexString(dpid), number);
		if (srcPortObject.getDevices().iterator().hasNext()) {
			for (IDeviceObject deviceObject: srcPortObject.getDevices()) {
				srcPortObject.removeDevice(deviceObject);
				log.debug("delete Device "+ deviceObject.getMACAddress() +
						" from sw: {} port: {} due to a new link added",
						dpid, number);
			}
		}
	}

	@Override
	public boolean addLink(Link link, LinkInfo linfo) {
		boolean success = false;
		
		try {
			//delete the Device attachment points for the related switch and port
			deleteDeviceOnPort(link.getSrc(),link.getSrcPort());
			deleteDeviceOnPort(link.getDst(),link.getDstPort());

		        long startLinkTime = System.nanoTime();
			if (addLinkImpl(link)) {
				// Set LinkInfo only if linfo is non-null.
				if (linfo != null && (! setLinkInfoImpl(link, linfo))) {
					log.debug("Adding linkinfo failed: {}", link);
					dbop.rollback();
				}
				dbop.commit();
                                long endLinkTime = System.nanoTime();
                                log.error("Performance ##add link total time {}", endLinkTime - startLinkTime);
				success = true;
			} else {
				// If we fail here that's because the ports aren't added
				// before we try to add the link
				log.debug("Adding link failed: {}", link);
				dbop.rollback();
			}
		} catch (Exception e) {
			dbop.rollback();
			e.printStackTrace();
			log.error("LinkStorageImpl:addLink link:{} linfo:{} failed", link, linfo);
		}
		
		return success;
	}
	
	/**
	 * Update multiple records in the LinkStorage in a way provided by op.
	 * @param links List of records to be updated.
	 * @param op Operation to be done.
	 */
	@Override
	public boolean addLinks(List<Link> links) {
		boolean success = false;
		
		for (Link lt: links) {
			if (! addLinkImpl(lt)) {
				return false;
			}
		}
		
		try {
			dbop.commit();
			success = true;
		} catch (Exception e) {
			dbop.rollback();
			e.printStackTrace();
			log.error("LinkStorageImpl:addLinks link:s{} failed", links);
		}
		
		return success;
	}

	/**
	 * Delete a record in the LinkStorage.
	 * @param lt Record to be deleted.
	 */
	@Override
	public boolean deleteLink(Link lt) {
		boolean success = false;
		
		log.debug("LinkStorageImpl:deleteLink(): {}", lt);
		
        try {
         	if (deleteLinkImpl(lt)) {
        		dbop.commit();
        		success = true;
            	log.debug("LinkStorageImpl:deleteLink(): deleted edges {}", lt);
            } else {
            	dbop.rollback();
            	log.error("LinkStorageImpl:deleteLink(): failed invalid vertices {}", lt);
            }
        } catch (Exception e) {
        	dbop.rollback();
        	log.error("LinkStorageImpl:deleteLink(): failed {} {}",
        			new Object[]{lt, e.toString()});
        	e.printStackTrace();
        }
        
        return success;
	}

	/**
	 * Delete multiple records in LinkStorage.
	 * @param links List of records to be deleted.
	 */
	@Override
	public boolean deleteLinks(List<Link> links) {
		boolean success = false;
		
		try {
			for (Link lt : links) {
				if (! deleteLinkImpl(lt)) {
					dbop.rollback();
					return false;
				}
			}
			dbop.commit();
			success = true;
		} catch (Exception e) {
        	dbop.rollback();
			e.printStackTrace();
        	log.error("LinkStorageImpl:deleteLinks failed invalid vertices {}", links);
		}
		
		return success;
	}

	/**
	 * Get list of all links connected to the port specified by given DPID and port number.
	 * @param dpid DPID of desired port.
	 * @param port Port number of desired port.
	 * @return List of links. Empty list if no port was found.
	 */
	@Override
	public List<Link> getLinks(Long dpid, short port) {
	    List<Link> links = new ArrayList<Link>();
	    IPortObject srcPort = dbop.searchPort(HexString.toHexString(dpid), port);
	    if (srcPort == null)
		return links;
	    ISwitchObject srcSw = srcPort.getSwitch();
	    if (srcSw == null)
		return links;
    	
	    for(IPortObject dstPort : srcPort.getLinkedPorts()) {
		ISwitchObject dstSw = dstPort.getSwitch();
		if (dstSw != null) {
		    Link link = new Link(dpid, port,
					 HexString.toLong(dstSw.getDPID()),
					 dstPort.getNumber());
		    links.add(link);
		}
	    }
	    return links;
	}

	/**
	 * Get list of all reverse links connected to the port specified by given DPID and port number.
	 * @param dpid DPID of desired port.
	 * @param port Port number of desired port.
	 * @return List of reverse links. Empty list if no port was found.
	 */
	@Override
	public List<Link> getReverseLinks(Long dpid, short port) {
	    List<Link> links = new ArrayList<Link>();
    	
	    IPortObject srcPort = dbop.searchPort(HexString.toHexString(dpid), port);
	    if (srcPort == null)
		return links;
	    ISwitchObject srcSw = srcPort.getSwitch();
	    if (srcSw == null)
		return links;
    	
	    for(IPortObject dstPort : srcPort.getReverseLinkedPorts()) {
		ISwitchObject dstSw = dstPort.getSwitch();
		if (dstSw != null) {
		    Link link = new Link(HexString.toLong(dstSw.getDPID()),
					 dstPort.getNumber(),
					 dpid, port);
		    links.add(link);
		}
	    }
	    return links;
	}
	
	/**
	 * Delete records of the links connected to the port specified by given DPID and port number.
	 * @param dpid DPID of desired port.
	 * @param port Port number of desired port.
	 */
	@Override
	public boolean deleteLinksOnPort(Long dpid, short port) {
		boolean success = false;
		
		List<Link> linksToDelete = getLinks(dpid, port);
		try {
			for(Link l : linksToDelete) {
				if (! deleteLinkImpl(l)) {
					dbop.rollback();
					log.error("LinkStorageImpl:deleteLinksOnPort dpid:{} port:{} failed", dpid, port);
					return false;
				}
			}
			dbop.commit();
			success = true;
		} catch (Exception e) {
        	dbop.rollback();
			e.printStackTrace();
        	log.error("LinkStorageImpl:deleteLinksOnPort dpid:{} port:{} failed", dpid, port);
		}
		
		return success;
	}

	/**
	 * Get list of all links connected to the switch specified by given DPID.
	 * @param dpid DPID of desired switch.
	 * @return List of links. Empty list if no port was found.
	 */
	@Override
	public List<Link> getLinks(String dpid) {
		List<Link> links = new ArrayList<Link>();
		ISwitchObject srcSw = dbop.searchSwitch(dpid);
		
		if(srcSw != null) {
			for(IPortObject srcPort : srcSw.getPorts()) {
				for(IPortObject dstPort : srcPort.getLinkedPorts()) {
					ISwitchObject dstSw = dstPort.getSwitch();
					if(dstSw != null) {
					    Link link = new Link(HexString.toLong(dpid),
		        				srcPort.getNumber(),
		        				HexString.toLong(dstSw.getDPID()),
							dstPort.getNumber());
		        		links.add(link);
					}
				}
			}
		}
		
		return links;
	}

	/**
	 * Get list of all reverse links connected to the switch specified by
	 * given DPID.
	 * @param dpid DPID of desired switch.
	 * @return List of reverse links. Empty list if no port was found.
	 */
	@Override
	public List<Link> getReverseLinks(String dpid) {
		List<Link> links = new ArrayList<Link>();

		ISwitchObject srcSw = dbop.searchSwitch(dpid);
		
		if(srcSw != null) {
			for(IPortObject srcPort : srcSw.getPorts()) {
				for(IPortObject dstPort : srcPort.getReverseLinkedPorts()) {
					ISwitchObject dstSw = dstPort.getSwitch();
					if(dstSw != null) {
		        		Link link = new Link(
							HexString.toLong(dstSw.getDPID()),
							dstPort.getNumber(),
					
							HexString.toLong(dpid),
							srcPort.getNumber());
		        		links.add(link);
					}
				}
			}
		}
		
		return links;
	}

	/**
	 * Get list of all links whose state is ACTIVE.
	 * @return List of active links. Empty list if no port was found.
	 */
	public List<Link> getActiveLinks() {
		Iterable<ISwitchObject> switches = dbop.getActiveSwitches();

		List<Link> links = new ArrayList<Link>(); 
		
		for (ISwitchObject srcSw : switches) {
			for(IPortObject srcPort : srcSw.getPorts()) {
				for(IPortObject dstPort : srcPort.getLinkedPorts()) {
					ISwitchObject dstSw = dstPort.getSwitch();
					
					if(dstSw != null && dstSw.getState().equals("ACTIVE")) {
						links.add(new Link(HexString.toLong(srcSw.getDPID()),
								srcPort.getNumber(),
								HexString.toLong(dstSw.getDPID()),
								dstPort.getNumber()));
					}
				}
			}
		}
		
		return links;
	}
	
	@Override
	public LinkInfo getLinkInfo(Link link) {
		// TODO implement this
		return null;
	}

	/**
	 * Finalize the object.
	 */
	public void finalize() {
		close();
	}

	/**
	 * Close LinkStorage.
	 */
	@Override
	public void close() {
		// TODO Auto-generated method stub
//		graph.shutdown();		
	}

	/**
	 * Update a record of link with meta-information in the LinkStorage.
	 * @param link Record of a link to update.
	 * @param linkinfo Meta-information of a link to be updated.
	 */
	private boolean setLinkInfoImpl(Link link, LinkInfo linkinfo) {
		// TODO implement this
		
		return false;
	}

	private boolean addLinkImpl(Link lt) {
		boolean success = false;
		
		IPortObject vportSrc = null, vportDst = null;
		
		// get source port vertex
		String dpid = HexString.toHexString(lt.getSrc());
		short port = lt.getSrcPort();
		log.debug("addLinkImpl Src dpid : " + dpid + " port :" + port);
		vportSrc = dbop.searchPort(dpid, port);
		
		// get dest port vertex
		dpid = HexString.toHexString(lt.getDst());
		port = lt.getDstPort();
		log.debug("addLinkImpl Dst dpid : " + dpid + " port :" + port);
		vportDst = dbop.searchPort(dpid, port);
		
		log.debug("addLinkImpl vportSrc : " + vportSrc + " vportDst : " + vportDst);
		
		if (vportSrc != null && vportDst != null) {
			IPortObject portExist = null;
			// check if the link exists
			for (IPortObject V : vportSrc.getLinkedPorts()) {
			        log.debug("vportSrc.getLinkedPorts() :" + V);
				if (V.equals(vportDst)) {
					portExist = V;
					break;
				}
			}
		
			if (portExist == null) {
				vportSrc.setLinkPort(vportDst);
				success = true;
			} else {
				log.debug("LinkStorageImpl:addLinkImpl failed link exists {} {} src {} dst {}", 
						new Object[]{dbop, lt, vportSrc, vportDst});
			}
		}
		
		return success;
	}

	private boolean deleteLinkImpl(Link lt) {
		boolean success = false;
		IPortObject vportSrc = null, vportDst = null;
	
	    // get source port vertex
	 	String dpid = HexString.toHexString(lt.getSrc());
	 	short port = lt.getSrcPort();
	 	vportSrc = dbop.searchPort(dpid, port);
	    
	    // get dst port vertex
	 	dpid = HexString.toHexString(lt.getDst());
	 	port = lt.getDstPort();
	 	vportDst = dbop.searchPort(dpid, port);
	 	
		// FIXME: This needs to remove all edges
	 	if (vportSrc != null && vportDst != null) {
	 		vportSrc.removeLink(vportDst);
	    	log.debug("deleteLinkImpl(): deleted edges src {} dst {}", new Object[]{
	    			lt, vportSrc, vportDst});
	    	success = true;
	    }
	    
	 	return success;
	}
}
