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

import net.onrc.onos.graph.GraphDBConnection;
import net.onrc.onos.graph.GraphDBOperation;
import net.onrc.onos.ofcontroller.core.ISwitchStorage;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;

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 CassandraDB
 */
public class SwitchStorageImpl implements ISwitchStorage {
	protected GraphDBOperation op;
	protected 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(String conf) {
		GraphDBConnection conn = GraphDBConnection.getInstance(conf);
		op = new GraphDBOperation(conn);
	}

	/***
	 * 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 gabage collection.
	 */
	@Override
	public void close() {
		op.close();		
	}
	
	private void setStatus(String dpid, SwitchState state) {
		ISwitchObject sw = op.searchSwitch(dpid);
		
		try {
			if (sw != null) {
				sw.setState(state.toString());
				op.commit();
				log.info("SwitchStorage:setStatus dpid:{} state: {} done", dpid, state);
			}
		} catch(Exception e) {
			e.printStackTrace();
			op.rollback();
			log.info("SwitchStorage:setStatus dpid:{} state: {} failed: switch not found", dpid, state);	
		}
	}

	/***
	 * This function is for adding the switch into the DB.
	 * @param dpid The switch dpid you want to add into the DB.
	 */
	@Override
	public void addSwitch(String dpid) {
		
		log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
		try {
			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);
				sw.setState(SwitchState.ACTIVE.toString());
				op.commit();
			} else {
				sw = op.newSwitch(dpid);

				if (sw != null) {
					sw.setState(SwitchState.ACTIVE.toString());
					op.commit();
					log.info("SwitchStorage:addSwitch dpid:{} added", dpid);
				} else {
					log.error("switchStorage:addSwitch dpid:{} failed -> newSwitch failed", dpid);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			op.rollback();
			log.info("SwitchStorage:addSwitch dpid:{} failed", dpid);
		}
	}
	
	/***
	 * 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
	 */
	@Override
	public void update(String dpid, SwitchState state, DM_OPERATION dmope) {
		log.info("SwitchStorage:update dpid:{} state: {} ", dpid, state);
        switch(dmope) {
        	case UPDATE:
        	case INSERT:
        	case CREATE:
                addSwitch(dpid);
                if (state != SwitchState.ACTIVE) {
                	setStatus(dpid, state);
                }
                break;
        	case DELETE:
                deleteSwitch(dpid);
                break;
        	default:
        }
	}

	/***
	 * This function is for deleting the switch into the DB.
	 * @param dpid The switch dpid you want to delete from the DB.
	 */
	@Override
	public void deleteSwitch(String dpid) {
		try {
			ISwitchObject sw = op.searchSwitch(dpid);
            if (sw  != null) {
            	op.removeSwitch(sw);
            	op.commit();
            	log.info("SwitchStorage:DeleteSwitch dpid:{} done", dpid);
            }
		} catch (Exception e) {
			e.printStackTrace();
			op.rollback();			
			log.error("SwitchStorage:deleteSwitch {} failed", dpid);
		}

	}

	/***
	 * This function is for adding the switch port into the DB.
	 * @param dpid The switch dpid that has the port.
	 * @param port The port you want to add the switch.
	 */
	@Override
	public void addPort(String dpid, OFPhysicalPort port) {
		
       if(((OFPortConfig.OFPPC_PORT_DOWN.getValue() & port.getConfig()) > 0) ||
        					((OFPortState.OFPPS_LINK_DOWN.getValue() & port.getState()) > 0)) {
    	     deletePort(dpid, port.getPortNumber());
             return;  
       }

		try {
			ISwitchObject sw = op.searchSwitch(dpid);

            if (sw != null) {
            	IPortObject p = op.searchPort(dpid, port.getPortNumber());
            	log.info("SwitchStorage:addPort dpid:{} port:{}", dpid, port.getPortNumber());
            	if (p != null) {
            		log.error("SwitchStorage:addPort dpid:{} port:{} exists", dpid, port.getPortNumber());
            	} else {
            		p = op.newPort(port.getPortNumber());
            		p.setState("ACTIVE");
            		p.setPortState(port.getState());
            		p.setDesc(port.getName());
            		sw.addPort(p);
            		op.commit();
            	}
            } else {
        		log.error("SwitchStorage:addPort dpid:{} port:{} : failed switch does not exist", dpid, port.getPortNumber());
            }
		} catch (Exception e) {
			e.printStackTrace();
			op.rollback();
			log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, port.getPortNumber());
		}	

	}
	
	/***
	 * 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 void deletePort(String dpid, short port) {
		try {
			ISwitchObject sw = op.searchSwitch(dpid);

            if (sw != null) {
            	IPortObject p = op.searchPort(dpid, port);
                if (p != null) {
            		log.info("SwitchStorage:deletePort dpid:{} port:{} found and deleted", dpid, port);
            		sw.removePort(p);
            		op.removePort(p);
            		op.commit();
            	}
            }
		} catch (Exception e) {
			e.printStackTrace();
			op.rollback();
			log.info("SwitchStorage:deletePort dpid:{} port:{} failed", dpid, port);
		}	
	}
}