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.impls.ramcloud.PerfMon;
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;
	private static PerfMon pm = PerfMon.getInstance();

	/**
	 * 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 == null)
		    return;
		Iterable<IDeviceObject> devices = srcPortObject.getDevices();
		if (devices == null)
		    return;
		if (devices.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();
			pm.addlink_start();
			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();
				pm.addlink_end();
                                long endLinkTime = System.nanoTime();
                                log.error("Performance ##add link total time {}", endLinkTime - startLinkTime);
				success = true;
			} else {
				pm.addlink_end();
				// 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.
	 */
	@Override
	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.
	 */
	@Override
	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 : {} port : {}", dpid, port);
		vportSrc = dbop.searchPort(dpid, port);

		// get dest port vertex
		dpid = HexString.toHexString(lt.getDst());
		port = lt.getDstPort();
		log.debug("addLinkImpl Dst dpid : {} port : {}", dpid, port);
		vportDst = dbop.searchPort(dpid, port);

		log.debug("addLinkImpl vportSrc : {} vportDst : {}", vportSrc, 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.error("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 edge {} src {} dst {}", new Object[]{
				lt, vportSrc, vportDst});
			success = true;
		}

		return success;
	}
}
