package net.onrc.onos.core.topology;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Switch Object stored in In-memory Topology.
 *
 * TODO REMOVE following design memo: This object itself may hold the DBObject,
 * but this Object itself will not issue any read/write to the DataStore.
 */
public class SwitchImpl extends NetworkGraphObject implements Switch {

	private Long dpid;
	// These needs to be ConcurrentCollecton if allowing Graph to be accessed Concurrently
	private final Map<Long, Port> ports;

	public SwitchImpl(NetworkGraph graph, Long dpid) {
		super(graph);
		this.dpid = dpid;
		ports = new HashMap<Long, Port>();
	}

	@Override
	public Long getDpid() {
		return dpid;
	}

	@Override
	public Collection<Port> getPorts() {
		return Collections.unmodifiableCollection(ports.values());
	}

	@Override
	public Port getPort(Long number) {
		return ports.get(number);
	}

	@Override
	public Iterable<Switch> getNeighbors() {
		Set<Switch> neighbors = new HashSet<>();
		for (Link link : getOutgoingLinks()) {
		    neighbors.add(link.getDstSwitch());
		}
		// XXX should incoming considered neighbor?
		for (Link link : getIncomingLinks()) {
		    neighbors.add(link.getSrcSwitch());
		}
		return neighbors;
	}

	@Override
	public Link getLinkToNeighbor(Long neighborDpid) {
		for (Link link : getOutgoingLinks()) {
			if (link.getDstSwitch().getDpid().equals(neighborDpid) ) {
				return link;
			}
		}
		return null;
	}

	@Override
	public Collection<Device> getDevices() {
		// TODO Should switch also store a list of attached devices to avoid
		// calculating this every time?
		List<Device> devices = new ArrayList<Device>();

		for (Port port : ports.values()) {
			for (Device device : port.getDevices()) {
				devices.add(device);
			}
		}

		return devices;
	}

	public void addPort(Port port) {
		this.ports.put(port.getNumber(), port);
	}

	public Port removePort(Port port) {
	    Port p = this.ports.remove(port.getNumber());
	    return p;
	}

	public Port addPort(Long portNumber) {
		PortImpl port = new PortImpl(graph, this, portNumber);
		ports.put(port.getNumber(), port);
		return port;
	}

	@Override
	public Iterable<Link> getOutgoingLinks() {
		LinkedList<Link> links = new LinkedList<Link>();
		for (Port port: getPorts()) {
			Link link = port.getOutgoingLink();
			if (link != null) {
				links.add(link);
			}
		}
		return links;
	}

	@Override
	public Iterable<Link> getIncomingLinks() {
		LinkedList<Link> links = new LinkedList<Link>();
		for (Port port: getPorts()) {
			Link link = port.getIncomingLink();
			if (link != null) {
				links.add(link);
			}
		}
		return links;
	}
}
