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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import net.floodlightcontroller.devicemanager.IDevice;
import net.floodlightcontroller.devicemanager.SwitchPort;
import net.floodlightcontroller.packet.IPv4;
import net.onrc.onos.graph.DBOperation;
import net.onrc.onos.graph.GraphDBManager;
import net.onrc.onos.ofcontroller.core.IDeviceStorage;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IIpv4Address;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;

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

import com.google.common.collect.Lists;
import com.google.common.net.InetAddresses;
import com.thinkaurelius.titan.core.TitanException;
/**
 * This is the class for storing the information of devices into CassandraDB
 *
 * @author Pankaj
 */
public class DeviceStorageImpl implements IDeviceStorage {

	private DBOperation ope;
	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) {
		try {
			ope = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloudconf");
			//ope = GraphDBManager.getDBOperation(dbStore, conf);
		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}

	/**
	* *
	* Finalize/close function. After you use this class, please call this
	* method. It will close the DB connection.
	*/
	@Override
	public void close() {
		ope.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 finalize() {
		close();
	}

	/**
	* *
	* This function is for adding the device into the DB.
	*
	* @param device The device you want to add into the DB.
	* @return IDeviceObject which was added in the DB.
	*/
	@Override
	public IDeviceObject addDevice(IDevice device) {
		IDeviceObject obj = null;
		for (int i = 0; i < 6; i++) {
	 		try {
	 			if (i > 0) {
	 				log.debug("Retrying add device: i is {}", i);
	 			}
	 			if ((obj = ope.searchDevice(device.getMACAddressString())) != null) {
	 				log.debug("Adding device {}: found existing device", device.getMACAddressString());
	            } else {
	            	obj = ope.newDevice();
	                log.debug("Adding device {}: creating new device", device.getMACAddressString());
	            }
	 			
	            if (obj == null) {
	            	return null;
	            }
	            
	            changeDeviceAttachments(device, obj);
		        
	            changeDeviceIpv4Addresses(device, obj);
	            
	 			obj.setMACAddress(device.getMACAddressString());
	 			obj.setType("device");
	 			obj.setState("ACTIVE");
	 			ope.commit();
	 			
	 			break;
	 			//log.debug("Adding device {}",device.getMACAddressString());
			} catch (TitanException e) {
				ope.rollback();
				log.error("Adding device {} failed", device.getMACAddressString(), e);
				obj = null;
			}
		}
 		
		return obj;		
	}
	/**
	* *
	* This function is for updating the Device properties.
	*
	* @param device The device you want to add into the DB.
	* @return IDeviceObject which was added in the DB.
	*/
	@Override
	public IDeviceObject updateDevice(IDevice device) {
		return addDevice(device);
	}

	/***
	 * This function is for removing the Device from the DB.
	 * @param device The device you want to delete from the DB.
	 */
	@Override
	public void removeDevice(IDevice device) {
		IDeviceObject dev;
		
		if ((dev = ope.searchDevice(device.getMACAddressString())) != null) {
			removeDevice(dev);
		}
	}
	
	public void removeDevice(IDeviceObject deviceObject) {
		String deviceMac = deviceObject.getMACAddress();

		removeDeviceImpl(deviceObject);

		try {
			ope.commit();
			log.debug("DeviceStorage:removeDevice mac:{} done", deviceMac);
		} catch (TitanException e) {
			ope.rollback();
			log.error("DeviceStorage:removeDevice mac:{} failed", deviceMac);
		}
	}
	
	public void removeDeviceImpl(IDeviceObject deviceObject) {
		for (IIpv4Address ipv4AddressVertex : deviceObject.getIpv4Addresses()) {
			ope.removeIpv4Address(ipv4AddressVertex);
		}
		
		ope.removeDevice(deviceObject);
	}
    /**
     * *
     * This function is for getting the Device from the DB by Mac address of the
     * device.
     *
     * @param mac The device mac address you want to get from the DB.
     * @return IDeviceObject you want to get.
     */
    @Override
    public IDeviceObject getDeviceByMac(String mac) {
        return ope.searchDevice(mac);
    }

	/***
	 * This function is for getting the Device from the DB by IP address of the device.
	 * @param ip The device ip address you want to get from the DB.
	 * @return IDeviceObject you want to get.
	 */
	@Override
	public IDeviceObject getDeviceByIP(int ipv4Address) {
		try {
			IIpv4Address ipv4AddressVertex = ope.searchIpv4Address(ipv4Address);
			if (ipv4AddressVertex != null) {
				return ipv4AddressVertex.getDevice();
			}
			return null;
		}
		catch (TitanException e) {
			log.error("DeviceStorage:getDeviceByIP:{} failed");
			return null;
		}
	}

	/**
	* *
	* This function is for changing the Device attachment point.
	*
	* @param device The device you want change the attachment point
	*/
	@Override
	public void changeDeviceAttachments(IDevice device) {
		IDeviceObject obj = null;
		try {
			if ((obj = ope.searchDevice(device.getMACAddressString())) != null) {
				log.debug("Changing device ports {}: found existing device", device.getMACAddressString());
				changeDeviceAttachments(device, obj);
				ope.commit();
			} else {
				log.debug("failed to search device...now adding {}", device.getMACAddressString());
				addDevice(device);
			}
		} catch (TitanException e) {
			ope.rollback();
			log.error(":addDevice mac:{} failed", device.getMACAddressString());
		}
	}
	
	/***
	 * This function is for changing the Device attachment point.
	 * @param device The new device you want change the attachment point
	 * @param obj The old device IDeviceObject that is going to change the attachment point.
	 */
	public void changeDeviceAttachments(IDevice device, IDeviceObject obj) {
		SwitchPort[] attachmentPoints = device.getAttachmentPoints();
		List<IPortObject> attachedPorts = Lists.newArrayList(obj.getAttachedPorts());

		for (SwitchPort ap : attachmentPoints) {
			//Check if there is the port
			IPortObject port = ope.searchPort(HexString.toHexString(ap.getSwitchDPID()),
					(short) ap.getPort());
			log.debug("New Switch Port is {},{}", 
					HexString.toHexString(ap.getSwitchDPID()), (short) ap.getPort());

			if (port != null){
				if (attachedPorts.contains(port)) {
					log.debug("This is the port you already attached {}: do nothing", device.getMACAddressString());
					//This port will be remained, so remove from the removed port lists.
					attachedPorts.remove(port);
				} else {
					log.debug("Adding device {}: attaching to port", device.getMACAddressString());
					port.setDevice(obj);  
				}

				log.debug("port number is {}", port.getNumber());
				log.debug("port desc is {}", port.getDesc());
			}
		}      		 

		for (IPortObject port: attachedPorts) {
			log.debug("Detaching the device {}: detaching from port", device.getMACAddressString());
			port.removeDevice(obj);
			
			if (!obj.getAttachedPorts().iterator().hasNext()) {
				// XXX If there are no more ports attached to the device,
				// delete it. Otherwise we have a situation where the
				// device remains forever with an IP address attached.
				// When we implement device probing we should get rid of this.
				removeDevice(obj);
			}
		}
	}

	/***
	 * This function is for changing the Device IPv4 address.
	 * @param device The new device you want change the ipaddress
	 */
	@Override
	public void changeDeviceIPv4Address(IDevice device) {
		log.debug("Changing IP address for {} to {}", device.getMACAddressString(),
				device.getIPv4Addresses());
		IDeviceObject obj;
		try {
			if ((obj = ope.searchDevice(device.getMACAddressString())) != null) {
				changeDeviceIpv4Addresses(device, obj);
				ope.commit();
			} else {
				log.error(":changeDeviceIPv4Address mac:{} failed", device.getMACAddressString());
			}
		} catch (TitanException e) {
			ope.rollback();
			log.error(":changeDeviceIPv4Address mac:{} failed due to exception {}", device.getMACAddressString(), e);
		}
	}
	
	private void changeDeviceIpv4Addresses(IDevice device, IDeviceObject deviceObject) {
		List<String> dbIpv4Addresses = new ArrayList<String>();
		List<Integer> intDbIpv4Addresses = new ArrayList<Integer>();
		for (IIpv4Address ipv4Vertex : deviceObject.getIpv4Addresses()) {
			dbIpv4Addresses.add(InetAddresses.fromInteger(ipv4Vertex.getIpv4Address()).getHostAddress());
			intDbIpv4Addresses.add(ipv4Vertex.getIpv4Address());
		}
		
		List<String> memIpv4Addresses = new ArrayList<String>();
		for (int addr : device.getIPv4Addresses()) {
			memIpv4Addresses.add(InetAddresses.fromInteger(addr).getHostAddress());
		}
		
		log.debug("Device IP addresses {}, database IP addresses {}",
				memIpv4Addresses, dbIpv4Addresses);
		
		for (int ipv4Address : device.getIPv4Addresses()) {
			//if (deviceObject.getIpv4Address(ipv4Address) == null) {
			if (!intDbIpv4Addresses.contains(ipv4Address)) {
				IIpv4Address dbIpv4Address = ope.ensureIpv4Address(ipv4Address);
				
				/*
				IDeviceObject oldDevice = dbIpv4Address.getDevice();
				if (oldDevice != null) {
					oldDevice.removeIpv4Address(dbIpv4Address);
				}
				*/
				
				log.debug("Adding IP address {}", 
						InetAddresses.fromInteger(ipv4Address).getHostAddress());
				deviceObject.addIpv4Address(dbIpv4Address);
			}
		}
			
		List<Integer> deviceIpv4Addresses = Arrays.asList(device.getIPv4Addresses());
		for (IIpv4Address dbIpv4Address : deviceObject.getIpv4Addresses()) {
			if (!deviceIpv4Addresses.contains(dbIpv4Address.getIpv4Address())) {
				log.debug("Removing IP address {}",
						InetAddresses.fromInteger(dbIpv4Address.getIpv4Address())
						.getHostAddress());
				deviceObject.removeIpv4Address(dbIpv4Address);
			}
		}
	}
	
	/**
	 * Takes an {@link OnosDevice} and adds it into the database. There is no
	 * checking of the database data and removing old data - an 
	 * {@link OnosDevice} basically corresponds to a packet we've just seen,
	 * and we need to add that information into the database.
	 */
	@Override
	public void addOnosDevice(OnosDevice onosDevice) {
		String macAddress = HexString.toHexString(onosDevice.getMacAddress().toBytes());
		
		//if the switch port we try to attach a new device already has a link, then stop adding device
		IPortObject portObject1 = ope.searchPort(HexString.toHexString(
				onosDevice.getSwitchDPID()), onosDevice.getSwitchPort());

		if ((portObject1 != null) && portObject1.getLinkedPorts().iterator().hasNext()) {
			if (log.isDebugEnabled()) {
				log.debug("stop adding OnosDevice: {} due to there is a link to: {}",
						onosDevice, portObject1.getLinkedPorts().iterator().next().getPortId());
			}
			return;
		}
		
		log.debug("addOnosDevice: {}", onosDevice);

		try {
			IDeviceObject device = ope.searchDevice(macAddress);
			
			if (device == null) {
				device = ope.newDevice();
				device.setType("device");
				device.setState("ACTIVE");
				device.setMACAddress(macAddress);
			}
			
			// Check if the device has the IP address, add it if it doesn't
			if (onosDevice.getIpv4Address() != null) {
				boolean hasIpAddress = false;
				for (IIpv4Address ipv4Address : device.getIpv4Addresses()) {
					if (ipv4Address.getIpv4Address() == onosDevice.getIpv4Address().intValue()) {
						hasIpAddress = true;
						break;
					}
				}
				
				if (!hasIpAddress) {
					IIpv4Address ipv4Address = ope.ensureIpv4Address(onosDevice.getIpv4Address().intValue());
					IDeviceObject oldDevice = ipv4Address.getDevice();
					if (oldDevice != null && oldDevice.getMACAddress() != macAddress) {
						oldDevice.removeIpv4Address(ipv4Address);
					}
					device.addIpv4Address(ipv4Address);
				}
			}
			
			// Check if the device has the attachment point, add it if not
			// TODO single attachment point for now, extend to multiple later
			String switchDpid = HexString.toHexString(onosDevice.getSwitchDPID());
			boolean hasAttachmentPoint = false;
			Iterator<IPortObject> it = device.getAttachedPorts().iterator();
			if (it.hasNext()) {
				IPortObject existingPort = it.next();
				if (existingPort != null) {
					ISwitchObject existingSwitch = existingPort.getSwitch();
					if (!existingSwitch.getDPID().equals(switchDpid) ||
							existingPort.getNumber() != onosDevice.getSwitchPort()) {
						existingPort.removeDevice(device);
					}
					else {
						hasAttachmentPoint = true;
					}
				}
			}
			
			/*
			for (IPortObject portObject : device.getAttachedPorts()) {
				ISwitchObject switchObject = portObject.getSwitch();
				if (switchObject.getDPID().equals(switchDpid)
						&& portObject.getNumber() == onosDevice.getSwitchPort()) {
					hasAttachmentPoint = true;
					break;
				}
			}
			*/
			
			if (!hasAttachmentPoint) {
				IPortObject portObject = ope.searchPort(switchDpid, onosDevice.getSwitchPort());
				if (portObject != null) {
					portObject.setDevice(device);
				}
			}
			
			ope.commit();
		}
		catch (TitanException e) {
			log.error("addOnosDevice {} failed:", macAddress, e);
			ope.rollback();
		}
	}

}
