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

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

import net.floodlightcontroller.core.IOFSwitch;
import net.onrc.onos.graph.DBOperation;
import net.onrc.onos.graph.GraphDBManager;
import net.onrc.onos.ofcontroller.core.ISwitchStorage;
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.core.ISwitchStorage;

import org.openflow.protocol.OFPhysicalPort;
import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
import org.openflow.protocol.OFPhysicalPort.OFPortState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is the class for storing the information of switches into GraphDB
 */
public class SwitchStorageImpl implements ISwitchStorage {

	protected DBOperation op;
	protected final static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);

	/**
	* *
	* Initialize function. Before you use this class, please call this method
	*
	* @param conf configuration file for Cassandra DB
	*/
	@Override
	public void init(final String dbStore, final String conf) {
		op = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloudconf");
		//op = GraphDBManager.getDBOperation(dbStore, conf);
	}


	/***
	 * Finalize/close function. After you use this class, please call this method.
	 * It will close the DB connection.
	 */
	public void finalize() {
		close();
	}
	
	/***
	 * Finalize/close function. After you use this class, please call this method.
	 * It will close the DB connection. This is for Java garbage collection.
	 */
	@Override
	public void close() {
		op.close();		
	}
	
	// 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.
	
	/***
	 * This function is for updating the switch into the DB.
	 * @param dpid The switch dpid you want to update from the DB
	 * @param state The state of the switch like ACTIVE, INACTIVE
	 * @param dmope	The DM_OPERATION of the switch
	 */
	/*
	 * Jono, 11/8/2013
	 * We don't need this update method that demultiplexes DM_OPERATIONS,
	 * we can have clients just call the required methods directly.
	 * We especially don't need this update method to re-implement 
	 * the functions of other methods.
	 */
	@Deprecated
	@Override
	public boolean updateSwitch(String dpid, SwitchState state, DM_OPERATION dmope) {
		boolean success = false;
		ISwitchObject sw = null;
		
		log.info("SwitchStorage:update {} dpid:{}", dmope, dpid);
	    switch(dmope) {
	    	case UPDATE:
            	try {
		    		sw = op.searchSwitch(dpid);
		    		if (sw != null) {
			            	setSwitchStateImpl(sw, state);
							op.commit();
							success = true;
		    		}
				} catch (Exception e) {
					op.rollback();
					e.printStackTrace();
					log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
				}
	    		break;
	    	case INSERT:
	    	case CREATE:
            	try {
		            sw = addSwitchImpl(dpid);
		            if (sw != null) {
			            if (state != SwitchState.ACTIVE) {
			            	setSwitchStateImpl(sw, state);
			            }
						op.commit();
						success = true;
		            }
				} catch (Exception e) {
					op.rollback();
					e.printStackTrace();
					log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
				}
	            break;
	    	case DELETE:
	            try {
		    		sw = op.searchSwitch(dpid);
		    		if (sw != null) {
				            deleteSwitchImpl(sw);
							op.commit();
							success = true;
		    		}
				} catch (Exception e) {
					op.rollback();
					e.printStackTrace();
					log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
				}
	            break;
	    	default:
	    }
	    
	    return success;
	}
	
	@Override
	public boolean addSwitch(IOFSwitch sw) {
		boolean success = false;
		
		String dpid = sw.getStringId();
		log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
		
		try {
		        op = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloudconf");
			ISwitchObject curr = op.searchSwitch(dpid);
			if (curr != null) {
				//If existing the switch. set The SW state ACTIVE. 
				log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
				setSwitchStateImpl(curr, SwitchState.ACTIVE);
			} else {
				curr = addSwitchImpl(dpid);
			}
	
			for (OFPhysicalPort port: sw.getPorts()) {
				//addPort(dpid, port);
				addPortImpl(curr, port);

			}
			
			// XXX for now delete devices when we change a port to prevent
			// having stale devices.
			DeviceStorageImpl deviceStorage = new DeviceStorageImpl();
			deviceStorage.init("","");
			for (IPortObject portObject : curr.getPorts()) {
				for (IDeviceObject deviceObject : portObject.getDevices()) {
					// The deviceStorage has to remove on the object gained by its own
					// FramedGraph, it can't use our objects from here
					deviceStorage.removeDeviceImpl(deviceStorage.getDeviceByMac(deviceObject.getMACAddress()));
				}
			}
			
			op.commit();
			success = true;
		} catch (Exception e) {
			op.rollback();
			log.error("SwitchStorage:addSwitch dpid:{} failed", dpid, e);
		}
		
		return success;
	}

	/***
	 * This function is for adding the switch into the DB.
	 * @param dpid The switch dpid you want to add into the DB.
	 */
	// This method is only called by tests, so we probably don't need it.
	// If we need both addSwitch interfaces, one should call the other
	// rather than implementing the same logic twice.
	@Deprecated 
	@Override
	public boolean addSwitch(String dpid) {
		boolean success = false;
		
		log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
		try {
			op = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloudconf");
			ISwitchObject sw = op.searchSwitch(dpid);
			if (sw != null) {
				//If existing the switch. set The SW state ACTIVE. 
				log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
				setSwitchStateImpl(sw, SwitchState.ACTIVE);
			} else {
				addSwitchImpl(dpid);
			}
			op.commit();
			success = true;
		} catch (Exception e) {
			op.rollback();
			e.printStackTrace();
			log.error("SwitchStorage:addSwitch dpid:{} failed", dpid, e);
		}
		
		return success;
	}

	/***
	 * This function is for deleting the switch into the DB.
	 * @param dpid The switch dpid you want to delete from the DB.
	 */
	@Override
	public boolean deleteSwitch(String dpid) {
		boolean success = false;
		
		try {
			ISwitchObject sw = op.searchSwitch(dpid);
			if (sw != null) {
				deleteSwitchImpl(sw);
	        	op.commit();
			}
			success = true;
		} catch (Exception e) {
			op.rollback();
			e.printStackTrace();
			log.error("SwitchStorage:deleteSwitch {} failed", dpid);
		}
	
		return success;
	}
	
	public boolean deactivateSwitch(String dpid) {
		boolean success = false;
		
		try {
			ISwitchObject switchObject = op.searchSwitch(dpid);
			if (switchObject != null) {
				setSwitchStateImpl(switchObject, SwitchState.INACTIVE);
				
				for (IPortObject portObject : switchObject.getPorts()) {
					portObject.setState("INACTIVE");
				}
				op.commit();
				success = true;
			}
			else {
				log.warn("Switch {} not found when trying to deactivate", dpid);
			}
		} catch (Exception e) {
			// TODO what type of exception is thrown when we can't commit?
			op.rollback();
			log.error("SwitchStorage:deactivateSwitch {} failed", dpid, e);
		}
		
		return success;
	}

	public boolean updatePort(String dpid, short portNum, int state, String desc) {
		boolean success = false;
		
		try {
			ISwitchObject sw = op.searchSwitch(dpid);
	
	        if (sw != null) {
	        	IPortObject p = sw.getPort(portNum);
	        	log.info("SwitchStorage:updatePort dpid:{} port:{}", dpid, portNum);
	        	if (p != null) {
	        		setPortStateImpl(p, state, desc);
				op.commit();
	        	}
        		success = true;
	        } else {
	    		log.error("SwitchStorage:updatePort dpid:{} port:{} : failed switch does not exist", dpid, portNum);
	        }
		} catch (Exception e) {
			op.rollback();
			e.printStackTrace();
			log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, portNum);
		}	

		return success;
	}

	/***
	 * This function is for adding the switch port into the DB.
	 * @param dpid The switch dpid that has the port.
	 * @param phport The port you want to add the switch.
	 */
	@Override
	public boolean addPort(String dpid, OFPhysicalPort phport) {
		boolean success = false;
		
		if(((OFPortConfig.OFPPC_PORT_DOWN.getValue() & phport.getConfig()) > 0) ||
				((OFPortState.OFPPS_LINK_DOWN.getValue() & phport.getState()) > 0)) {
			// just dispatch to deletePort()
			// TODO This is wrong. We need to make sure the port is in the
			// DB with the correct info and port state.
			return deletePort(dpid, phport.getPortNumber());
		}
	
		try {
			ISwitchObject sw = op.searchSwitch(dpid);
	
	        if (sw != null) {
	        	IPortObject portObject = addPortImpl(sw, phport);
	        	
	        	// XXX for now delete devices when we change a port to prevent
	    		// having stale devices.
	    		DeviceStorageImpl deviceStorage = new DeviceStorageImpl();
	    		deviceStorage.init("","");
	    		
	    		for (IDeviceObject deviceObject : portObject.getDevices()) {
	    			deviceStorage.removeDevice(deviceObject);
	    		}
	        	
        		op.commit();
        		success = true;
	        } else {
	    		log.error("SwitchStorage:addPort dpid:{} port:{} : failed switch does not exist", dpid, phport.getPortNumber());
	        }
		} catch (Exception e) {
			op.rollback();
			e.printStackTrace();
			log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, phport.getPortNumber());
		}
		
		return success;
	}

	/***
	 * This function is for deleting the switch port from the DB.
	 * @param dpid The switch dpid that has the port.
	 * @param port The port you want to delete the switch.
	 */
	@Override
	public boolean deletePort(String dpid, short port) {
		boolean success = false;
		
		DeviceStorageImpl deviceStorage = new DeviceStorageImpl();
		deviceStorage.init("","");
		
		try {
			ISwitchObject sw = op.searchSwitch(dpid);
	
	        if (sw != null) {
	        	IPortObject p = sw.getPort(port);
	            if (p != null) {
	        		log.info("SwitchStorage:deletePort dpid:{} port:{} found and set INACTIVE", dpid, port);
	        		//deletePortImpl(p);
	        		p.setState("INACTIVE");
	        		
	        		// XXX for now delete devices when we change a port to prevent
	        		// having stale devices.
	        		for (IDeviceObject d : p.getDevices()) {
	        			deviceStorage.removeDevice(d);
	        		}
	        		op.commit();
	        	}
	        }
	        
	        success = true;
		} catch (Exception e) {
			op.rollback();
			e.printStackTrace();
			log.error("SwitchStorage:deletePort dpid:{} port:{} failed", dpid, port);
		}

		return success;
	}

	/**
	 * Get list of all ports on the switch specified by given DPID.
	 *
	 * @param dpid DPID of desired switch.
	 * @return List of port IDs. Empty list if no port was found.
	 */
	@Override
	public List<Short> getPorts(String dpid) {
	    List<Short> ports = new ArrayList<Short>();

	    ISwitchObject srcSw = op.searchSwitch(dpid);
	    if (srcSw != null) {
		for (IPortObject srcPort : srcSw.getPorts()) {
		    ports.add(srcPort.getNumber());
		}
	    }

	    return ports;
	}

	private ISwitchObject addSwitchImpl(String dpid) {
		if (dpid != null) {
			ISwitchObject sw = op.newSwitch(dpid);
			sw.setState(SwitchState.ACTIVE.toString());
			log.info("SwitchStorage:addSwitchImpl dpid:{} added", dpid);
			return sw;
		} else {
			return null;
		}
	}
	
	private void setSwitchStateImpl(ISwitchObject sw, SwitchState state) {
		if (sw != null && state != null) {
			sw.setState(state.toString());
			log.info("SwitchStorage:setSwitchStateImpl dpid:{} updated {}",
					sw.getDPID(), state.toString());
		}
	}
	
	private void deleteSwitchImpl(ISwitchObject sw) {
        if (sw  != null) {
        	op.removeSwitch(sw);
        	log.info("SwitchStorage:DeleteSwitchImpl dpid:{} done",
        			sw.getDPID());
        }
	}

	
	private IPortObject addPortImpl(ISwitchObject sw, OFPhysicalPort phport) {
		IPortObject portObject = op.searchPort(sw.getDPID(), phport.getPortNumber());
		
    	log.info("SwitchStorage:addPort dpid:{} port:{}", 
    			sw.getDPID(), phport.getPortNumber());
    	
    	if (portObject != null) {
    		setPortStateImpl(portObject, phport.getState(), phport.getName());
    		portObject.setState("ACTIVE");
    		
    		// This a convoluted way of checking if the port is attached
    		// or not, but doing it this way avoids using the 
    		// ISwitchObject.getPort method which uses GremlinGroovy query
    		// and takes forever.
    		boolean attached = false;
    		for (IPortObject portsOnSwitch : sw.getPorts()) {
    			if (portsOnSwitch.getPortId() == portObject.getPortId()) {
    				attached = true;
    				break;
    			}
    		}
    		
    		if (!attached) {
    			sw.addPort(portObject);
    		}
    		
    		/*
    		if (sw.getPort(phport.getPortNumber()) == null) {
    			// The port exists but the switch has no "on" link to it
    			sw.addPort(portObject);
    		}*/
    		
    		log.info("SwitchStorage:addPort dpid:{} port:{} exists setting as ACTIVE", 
    				sw.getDPID(), phport.getPortNumber());
    	} else {
    		//addPortImpl(sw, phport.getPortNumber());
    		portObject = op.newPort(sw.getDPID(), phport.getPortNumber());
    		portObject.setState("ACTIVE");
    		setPortStateImpl(portObject, phport.getState(), phport.getName());
    		sw.addPort(portObject);
        	log.info("SwitchStorage:addPort dpid:{} port:{} done",
        			sw.getDPID(), phport.getPortNumber());
    	}
    	
    	return portObject;
	}
	// TODO There's an issue here where a port with that ID could already
	// exist when we try to add this one (because it's left over from an
	// old topology). We need to remove an old port with the same ID when
	// we add the new port. Also it seems that old ports like this are 
	// never cleaned up and will remain in the DB in the ACTIVE state forever.
	/*private IPortObject addPortImpl(ISwitchObject sw, short portNum) {
		IPortObject p = op.newPort(sw.getDPID(), portNum);
		p.setState("ACTIVE");
		sw.addPort(p);
    	log.info("SwitchStorage:addPortImpl dpid:{} port:{} done",
    			sw.getDPID(), portNum);
		
		return p;
	}*/

	private void setPortStateImpl(IPortObject port, Integer state, String desc) {
		if (port != null) {
			if (state != null) {
				port.setPortState(state);
			}
			if (desc != null) {
				port.setDesc(desc);
			}
			
	    	log.info("SwitchStorage:setPortStateImpl port:{} state:{} desc:{} done",
	    			new Object[] {port.getPortId(), state, desc});
		}
	}
	
	private void deletePortImpl(IPortObject port) {
		if (port != null) {
			op.removePort(port);
	    	log.info("SwitchStorage:deletePortImpl port:{} done",
	    			port.getPortId());
		}
	}

}