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.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);
	}

	@Override
	public boolean addLink(Link link, LinkInfo linfo) {
		boolean success = false;
		
		try {
			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();
				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();
		vportSrc = dbop.searchPort(dpid, port);
		
		// get dest port vertex
		dpid = HexString.toHexString(lt.getDst());
		port = lt.getDstPort();
		vportDst = dbop.searchPort(dpid, port);
		            
		if (vportSrc != null && vportDst != null) {
			IPortObject portExist = null;
			// check if the link exists
			for (IPortObject V : vportSrc.getLinkedPorts()) {
				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;
	}

	// TODO should be moved to TopoLinkServiceImpl (never used in this class)
	static class ExtractLink implements PipeFunction<PathPipe<Vertex>, Link> {
	
		@SuppressWarnings("unchecked")
		@Override
		public Link compute(PathPipe<Vertex> pipe ) {
			long s_dpid = 0;
			long d_dpid = 0;
			short s_port = 0;
			short d_port = 0;
			List<Vertex> V = new ArrayList<Vertex>();
			V = (List<Vertex>)pipe.next();
			Vertex src_sw = V.get(0);
			Vertex dest_sw = V.get(3);
			Vertex src_port = V.get(1);
			Vertex dest_port = V.get(2);
			s_dpid = HexString.toLong((String) src_sw.getProperty("dpid"));
			d_dpid = HexString.toLong((String) dest_sw.getProperty("dpid"));
			s_port = (Short) src_port.getProperty("number");
			d_port = (Short) dest_port.getProperty("number");
			
			Link l = new Link(s_dpid,s_port,d_dpid,d_port);
			
			return l;
		}
	}
}
