package net.onrc.onos.core.topology;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.annotation.concurrent.GuardedBy;

import net.floodlightcontroller.core.IFloodlightProviderService.Role;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.LinkTuple;
import net.onrc.onos.core.util.OnosInstanceId;
import net.onrc.onos.core.util.PortNumber;
import net.onrc.onos.core.util.SwitchPort;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;


// TODO add TopologyManager, etc. to populate Mastership information.
/**
 * Class to represent an instance of Topology Snapshot.
 */
public class TopologyImpl implements MutableTopology, MutableInternalTopology {

    private static final Logger log = LoggerFactory.getLogger(TopologyImpl.class);

    // TODO Revisit Map types after implementing CoW/lock-free

    // Mastership info
    // Dpid -> [ (InstanceID, Role) ]
    private final Map<Dpid, SortedSet<MastershipData>> mastership;

    // DPID -> Switch
    private final ConcurrentMap<Dpid, SwitchData> switches;
    private final ConcurrentMap<Dpid, ConcurrentMap<PortNumber, PortData>> ports;

    // Index from Port to Host
    private final Multimap<SwitchPort, HostData> hosts;
    private final ConcurrentMap<MACAddress, HostData> mac2Host;

    // SwitchPort -> (type -> Link)
    private final ConcurrentMap<SwitchPort, ConcurrentMap<String, LinkData>> outgoingLinks;
    private final ConcurrentMap<SwitchPort, ConcurrentMap<String, LinkData>> incomingLinks;

    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private final Lock readLock = readWriteLock.readLock();
    // TODO use the write lock after refactor
    private final Lock writeLock = readWriteLock.writeLock();

    /**
     * Create an empty Topology.
     */
    public TopologyImpl() {
        mastership = new HashMap<>();
        // TODO: Does these object need to be stored in Concurrent Collection?
        switches = new ConcurrentHashMap<>();
        ports = new ConcurrentHashMap<>();
        hosts = Multimaps.synchronizedMultimap(
                HashMultimap.<SwitchPort, HostData>create());
        mac2Host = new ConcurrentHashMap<>();
        outgoingLinks = new ConcurrentHashMap<>();
        incomingLinks = new ConcurrentHashMap<>();
    }

    /**
     * Create a shallow copy of given Topology.
     *
     * @param original Topology
     */
    public TopologyImpl(TopologyImpl original) {
        original.acquireReadLock();
        try {
            // shallow copy Set in Map
            this.mastership = new HashMap<>(original.mastership.size());
            for (Entry<Dpid, SortedSet<MastershipData>> e
                        : original.mastership.entrySet()) {
                this.mastership.put(e.getKey(), new TreeSet<>(e.getValue()));
            }

            this.switches = new ConcurrentHashMap<>(original.switches);

            // shallow copy Map in Map
            this.ports = new ConcurrentHashMap<>(original.ports.size());
            for (Entry<Dpid, ConcurrentMap<PortNumber, PortData>> entry
                    : original.ports.entrySet()) {
                this.ports.put(entry.getKey(), new ConcurrentHashMap<>(entry.getValue()));
            }

            this.hosts = Multimaps.synchronizedMultimap(
                    HashMultimap.<SwitchPort, HostData>create(original.hosts));
            this.mac2Host = new ConcurrentHashMap<>(original.mac2Host);

            // shallow copy Map in Map
            this.outgoingLinks = new ConcurrentHashMap<>(original.outgoingLinks.size());
            for (Entry<SwitchPort, ConcurrentMap<String, LinkData>> entry
                    : original.outgoingLinks.entrySet()) {
                this.outgoingLinks.put(entry.getKey(), new ConcurrentHashMap<>(entry.getValue()));
            }

            // shallow copy Map in Map
            this.incomingLinks = new ConcurrentHashMap<>(original.incomingLinks.size());
            for (Entry<SwitchPort, ConcurrentMap<String, LinkData>> entry
                    : original.incomingLinks.entrySet()) {
                this.incomingLinks.put(entry.getKey(), new ConcurrentHashMap<>(entry.getValue()));
            }
        } finally {
            original.releaseReadLock();
        }
    }

    @Override
    public Switch getSwitch(Dpid dpid) {
        final SwitchData sw = switches.get(dpid);
        if (sw != null) {
            return new SwitchImpl(this, dpid);
        } else {
            return null;
        }
    }

    @Override
    public Iterable<Switch> getSwitches() {
        List<Switch> list = new ArrayList<>(switches.size());
        for (SwitchData elm : switches.values()) {
            list.add(new SwitchImpl(this, elm.getDpid()));
        }
        return list;
    }

    @Override
    public Port getPort(Dpid dpid, PortNumber number) {
        ConcurrentMap<PortNumber, PortData> portMap = ports.get(dpid);
        if (portMap != null) {
            final PortData port = portMap.get(number);
            if (port != null) {
                return new PortImpl(this, port.getSwitchPort());
            }
        }
        return null;
    }

    @Override
    public Port getPort(SwitchPort port) {
        return getPort(port.getDpid(), port.getPortNumber());
    }

    @Override
    public Collection<Port> getPorts(Dpid dpid) {
        ConcurrentMap<PortNumber, PortData> portMap = ports.get(dpid);
        if (portMap == null) {
            return Collections.emptyList();
        }
        List<Port> list = new ArrayList<>(portMap.size());
        for (PortData elm : portMap.values()) {
            list.add(new PortImpl(this, elm.getSwitchPort()));
        }
        return list;
    }

    @Override
    public Link getOutgoingLink(Dpid dpid, PortNumber number) {
        return getOutgoingLink(new SwitchPort(dpid, number));
    }

    @Override
    public Link getOutgoingLink(SwitchPort port) {
        Map<String, LinkData> links = outgoingLinks.get(port);
        return getPacketLinkIfExists(links);
    }

    // TODO remove when we no longer need packet fall back behavior
    /**
     * Gets the "packet" link if such exists,
     * if not return whichever link is found first.
     *
     * @param links Collection of links to search from
     * @return Link instance found or null if no link exists
     */
    private Link getPacketLinkIfExists(Map<String, LinkData> links) {

        if (links == null) {
            return null;
        }

        LinkData link = links.get(TopologyElement.TYPE_PACKET_LAYER);
        if (link != null) {
            // return packet link
            return new LinkImpl(this, link.getLinkTuple());
        } else {
            // return whatever found
            Iterator<LinkData> it = links.values().iterator();
            if (it.hasNext()) {
                return new LinkImpl(this, it.next().getLinkTuple());
            }
        }
        return null;
    }

    @Override
    public Link getOutgoingLink(Dpid dpid, PortNumber number, String type) {
        return getOutgoingLink(new SwitchPort(dpid, number), type);
    }

    @Override
    public Link getOutgoingLink(SwitchPort port, String type) {
        Map<String, LinkData> links = outgoingLinks.get(port);
        final LinkData link = links.get(type);
        if (link != null) {
            return new LinkImpl(this, link.getLinkTuple());
        }
        return null;
    }

    @Override
    public Collection<Link> getOutgoingLinks(SwitchPort port) {
        ConcurrentMap<String, LinkData> typeMap = outgoingLinks.get(port);
        if (typeMap == null) {
            return Collections.emptyList();
        }
        return toLinkImpls(typeMap.values());
    }

    /**
     * Converts collection of LinkData to collection of LinkImpls.
     *
     * @param links collection of LinkData
     * @return collection of LinkImpls
     */
    private Collection<Link> toLinkImpls(final Collection<LinkData> links) {
        if (links == null) {
            return Collections.emptyList();
        }
        List<Link> list = new ArrayList<>(links.size());
        for (LinkData elm : links) {
            list.add(new LinkImpl(this, elm.getLinkTuple()));
        }
        return list;
    }

    @Override
    public Link getIncomingLink(Dpid dpid, PortNumber number) {
        return getIncomingLink(new SwitchPort(dpid, number));
    }

    @Override
    public Link getIncomingLink(SwitchPort port) {
        Map<String, LinkData> links = incomingLinks.get(port);
        return getPacketLinkIfExists(links);
    }

    @Override
    public Link getIncomingLink(Dpid dpid, PortNumber number, String type) {
        return getIncomingLink(new SwitchPort(dpid, number), type);
    }

    @Override
    public Link getIncomingLink(SwitchPort port, String type) {
        Map<String, LinkData> links = incomingLinks.get(port);
        final LinkData link = links.get(type);
        if (link != null) {
            return new LinkImpl(this, link.getLinkTuple());
        }
        return null;
    }

    @Override
    public Collection<Link> getIncomingLinks(SwitchPort port) {
        ConcurrentMap<String, LinkData> typeMap = incomingLinks.get(port);
        if (typeMap == null) {
            return Collections.emptyList();
        }
        return toLinkImpls(typeMap.values());
    }

    @Override
    public Link getLink(Dpid srcDpid, PortNumber srcNumber,
                        Dpid dstDpid, PortNumber dstNumber) {

        final SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstNumber);
        Collection<Link> links = getOutgoingLinks(new SwitchPort(srcDpid, srcNumber));
        for (Link link : links) {
            if (link == null) {
                continue;
            }
            if (link.getDstPort().getSwitchPort().equals(dstSwitchPort)) {
                return link;
            }
        }
        return null;
    }

    @Override
    public Link getLink(Dpid srcDpid, PortNumber srcNumber,
                        Dpid dstDpid, PortNumber dstNumber,
                        String type) {

        Link link = getOutgoingLink(srcDpid, srcNumber, type);
        if (link == null) {
            return null;
        }
        if (!link.getDstSwitch().getDpid().equals(dstDpid)) {
            return null;
        }
        if (!link.getDstPort().getNumber().equals(dstNumber)) {
            return null;
        }
        return link;
    }

    @Override
    public Iterable<Link> getLinks() {
        List<Link> links = new ArrayList<>();

        for (Map<String, LinkData> portLinks : outgoingLinks.values()) {
            if (portLinks == null) {
                continue;
            }
            for (LinkData elm : portLinks.values()) {
                links.add(new LinkImpl(this, elm.getLinkTuple()));
            }
        }
        return links;
    }

    @Override
    public Host getHostByMac(MACAddress address) {
        HostData host = mac2Host.get(address);
        if (host != null) {
            return new HostImpl(this, address);
        }
        return null;
    }

    @Override
    public Iterable<Host> getHosts() {
        return toHostImpls(mac2Host.values());
    }

    /**
     * Converts collection of HostData to collection of HostImpl.
     *
     * @param events collection of HostData
     * @return collection of HostImpl
     */
    private List<Host> toHostImpls(Collection<HostData> events) {
        if (events == null) {
            return Collections.emptyList();
        }
        List<Host> list = new ArrayList<>(events.size());
        for (HostData elm : events) {
            list.add(new HostImpl(this, elm.getMac(), elm.getIp()));
        }
        return list;
    }

    @Override
    public Collection<Host> getHosts(SwitchPort port) {
        return toHostImpls(hosts.get(port));
    }

    @Override
    public SwitchData getSwitchData(final Dpid dpid) {
        return this.switches.get(dpid);
    }

    @Override
    public Collection<SwitchData> getAllSwitchDataEntries() {
        return Collections.unmodifiableCollection(switches.values());
    }

    @Override
    public PortData getPortData(final SwitchPort port) {
        return getPortData(port.getDpid(), port.getPortNumber());
    }

    @Override
    public PortData getPortData(final Dpid dpid, PortNumber portNumber) {
        ConcurrentMap<PortNumber, PortData> portMap = this.ports.get(dpid);
        if (portMap != null) {
            return portMap.get(portNumber);
        }
        return null;
    }

    @Override
    public Collection<PortData> getPortDataEntries(final Dpid dpid) {
        ConcurrentMap<PortNumber, PortData> portList = ports.get(dpid);
        if (portList == null) {
            return Collections.emptyList();
        }
        return Collections.unmodifiableCollection(portList.values());
    }

    @Override
    public Collection<PortData> getAllPortDataEntries() {
        List<PortData> events = new LinkedList<>();
        for (ConcurrentMap<PortNumber, PortData> cm : ports.values()) {
            events.addAll(cm.values());
        }
        return Collections.unmodifiableCollection(events);
    }

    @Override
    public LinkData getLinkData(final LinkTuple linkId) {
        ConcurrentMap<String, LinkData> links = this.outgoingLinks.get(linkId.getSrc());
        if (links == null) {
            return null;
        }

        // TODO Should we look for Packet link first?
        //  Not unless invariant is broken.

        for (LinkData link : links.values()) {
            if (link.getDst().equals(linkId.getDst())) {
                return link;
            }
        }
        return null;
    }

    @Override
    public LinkData getLinkData(final LinkTuple linkId, final String type) {
        ConcurrentMap<String, LinkData> links = this.outgoingLinks.get(linkId.getSrc());
        if (links == null) {
            return null;
        }
        LinkData link = links.get(type);
        if (link.getDst().equals(linkId.getDst())) {
            return link;
        }
        return null;
    }

    @Override
    public Collection<LinkData> getLinkDataEntriesFrom(SwitchPort srcPort) {
        ConcurrentMap<String, LinkData> links = this.outgoingLinks.get(srcPort);
        if (links == null) {
            return Collections.emptyList();
        }
        return Collections.unmodifiableCollection(links.values());
    }

    @Override
    public Collection<LinkData> getLinkDataEntriesTo(SwitchPort dstPort) {
        ConcurrentMap<String, LinkData> links = this.incomingLinks.get(dstPort);
        if (links == null) {
            return Collections.emptyList();
        }
        return Collections.unmodifiableCollection(links.values());
    }

    @Override
    public Collection<LinkData> getLinkDataEntries(final LinkTuple linkId) {
        ConcurrentMap<String, LinkData> links = this.outgoingLinks.get(linkId.getSrc());
        if (links == null) {
            return Collections.emptyList();
        }

        List<LinkData> linkDataEntries = new ArrayList<>();
        for (LinkData e : links.values()) {
            if (e.getDst().equals(linkId.getDst())) {
                linkDataEntries.add(e);
            }
        }

        // unless invariant is broken, this should contain at most 1 element.
        return linkDataEntries;
    }

    @Override
    public Collection<LinkData> getAllLinkDataEntries() {
        List<LinkData> events = new LinkedList<>();
        for (ConcurrentMap<String, LinkData> cm : outgoingLinks.values()) {
            events.addAll(cm.values());
        }
        return Collections.unmodifiableCollection(events);
    }

    @Override
    public HostData getHostData(final MACAddress mac) {
        return this.mac2Host.get(mac);
    }

    @Override
    public Collection<HostData> getHostDataEntries(SwitchPort port) {
        return Collections.unmodifiableCollection(hosts.get(port));
    }

    @Override
    public Collection<HostData> getAllHostDataEntries() {
        return Collections.unmodifiableCollection(mac2Host.values());
    }

    @Override
    public OnosInstanceId getSwitchMaster(Dpid dpid) {
        final SortedSet<MastershipData> candidates = mastership.get(dpid);
        if (candidates == null) {
            return null;
        }
        for (MastershipData candidate : candidates) {
            if (candidate.getRole() == Role.MASTER) {
                return candidate.getOnosInstanceId();
            }
        }
        return null;
    }

    /**
     * Puts a SwitchData.
     *
     * @param sw Switch to add. (Will be frozen if not already)
     */
    @GuardedBy("writeLock")
    protected void putSwitch(SwitchData sw) {
        // TODO isFrozen check once we implement CoW/lock-free
        switches.put(sw.getDpid(), sw.freeze());
        ports.putIfAbsent(sw.getDpid(), new ConcurrentHashMap<PortNumber, PortData>());
    }

    /**
     * Removes a SwitchData from this snapshot.
     * <p/>
     * Will also remove ports, if it has not been removed already.
     *
     * @param dpid Switch DPID
     */
    @GuardedBy("writeLock")
    protected void removeSwitch(Dpid dpid) {
        // TODO isFrozen check once we implement CoW/lock-free
        switches.remove(dpid);
        ConcurrentMap<PortNumber, PortData> removedPorts = ports.remove(dpid);
        if (removedPorts != null && !removedPorts.isEmpty()) {
            log.warn("Some ports were removed as side-effect of #removeSwitch({})", dpid);
        }
    }

    /**
     * Puts a PortData.
     *
     * @param port Port to add. (Will be frozen if not already)
     */
    @GuardedBy("writeLock")
    protected void putPort(PortData port) {

        ConcurrentMap<PortNumber, PortData> portMap = ports.get(port.getDpid());
        if (portMap == null) {
            portMap = new ConcurrentHashMap<>();
            ConcurrentMap<PortNumber, PortData> existing
                = ports.putIfAbsent(port.getDpid(), portMap);
            if (existing != null) {
                // port map was added concurrently, using theirs
                portMap = existing;
            }
        }
        portMap.put(port.getPortNumber(), port.freeze());
    }

    /**
     * Removes a PortData from this snapshot.
     *
     * @param port SwitchPort to remove
     */
    @GuardedBy("writeLock")
    protected void removePort(SwitchPort port) {
        removePort(port.getDpid(), port.getPortNumber());
    }

    /**
     * Removes a PortData from this snapshot.
     * <p/>
     * Will also remove ports, if it has not been removed already.
     *
     * @param dpid Switch DPID
     * @param number PortNumber
     */
    @GuardedBy("writeLock")
    protected void removePort(Dpid dpid, PortNumber number) {
        // TODO sanity check Host attachment point.
        ConcurrentMap<PortNumber, PortData> portMap = ports.get(dpid);
        if (portMap != null) {
            portMap.remove(number);
        }
    }

    /**
     * Puts a LinkData.
     *
     * @param link LinkData
     */
    @GuardedBy("writeLock")
    protected void putLink(LinkData link) {
        // TODO Do sanity check?
        //   - There cannot be 2 links in same direction between a port pair.
        putLinkMap(outgoingLinks, link.getSrc(), link);
        putLinkMap(incomingLinks, link.getDst(), link);
    }

    /**
     * Helper method to update outgoingLinks, incomingLinks.
     *
     * @param linkMap outgoingLinks or incomingLinks to update
     * @param port {@code linkMap} key to update
     * @param link Link to add
     */
    @GuardedBy("writeLock")
    private void putLinkMap(ConcurrentMap<SwitchPort, ConcurrentMap<String, LinkData>> linkMap,
                            SwitchPort port, LinkData link) {

        ConcurrentMap<String, LinkData> linksOnPort = linkMap.get(port);
        if (linksOnPort == null) {
            linksOnPort = new ConcurrentHashMap<>(4);
            ConcurrentMap<String, LinkData> existing
                = linkMap.putIfAbsent(
                    port,
                    linksOnPort);

            if (existing != null) {
                linksOnPort = existing;
            }
        }
        linksOnPort.put(link.getType(), link);
    }

    /**
     * Removes a LinkData from this snapshot.
     *
     * @param link Link to remove
     * @param type type of link to remove
     */
    @GuardedBy("writeLock")
    protected void removeLink(LinkTuple link, String type) {
        ConcurrentMap<String, LinkData> portLinks
            = outgoingLinks.get(link.getSrc());
        if (portLinks != null) {
            // no conditional update here
            portLinks.remove(type);
        }
        portLinks
            = incomingLinks.get(link.getDst());
        if (portLinks != null) {
            // no conditional update here
            portLinks.remove(type);
        }
    }

    /**
     * Removes a LinkData from this snapshot.
     *
     * @param link Link to remove
     */
    @GuardedBy("writeLock")
    protected void removeLink(LinkTuple link) {
        Collection<LinkData> links = getLinkDataEntries(link);
        for (LinkData l : links) {
            removeLink(link, l.getType());
        }
    }

    /**
     * Puts a HostData.
     * <p/>
     * Removes attachment points for previous HostData and update
     * them with new HostData
     *
     * @param host HostData
     */
    @GuardedBy("writeLock")
    protected void putHost(HostData host) {
        // Host cannot be simply put() to replace instance since it has mobility.
        // Simply remove -> put for now.

        // remove old attachment points
        removeHost(host.getMac());

        // add new attachment points
        for (SwitchPort port : host.getAttachmentPoints()) {
            hosts.put(port, host);
        }
        mac2Host.put(host.getMac(), host);
    }

    /**
     * Removes a HostData from this snapshot.
     *
     * @param mac MACAddress of the Host to remove
     */
    @GuardedBy("writeLock")
    protected void removeHost(MACAddress mac) {
        HostData host = mac2Host.remove(mac);
        if (host != null) {
            for (SwitchPort port : host.getAttachmentPoints()) {
                hosts.remove(port, host);
            }
        }
    }

    /**
     * Puts a mastership change event.
     *
     * @param master MastershipData
     */
    @GuardedBy("writeLock")
    protected void putSwitchMastershipData(MastershipData master) {
        checkNotNull(master);

        SortedSet<MastershipData> candidates
            = mastership.get(master.getDpid());
        if (candidates == null) {
            // SortedSet, customized so that MASTER MastershipData appear
            // earlier during iteration.
            candidates = new TreeSet<>(new MastershipData.MasterFirstComparator());
        }

        // always replace
        candidates.remove(master);
        candidates.add(master);
    }

    /**
     * Removes a mastership change event.
     * <p>
     * Note: Only Dpid and OnosInstanceId will be used to identify the
     * {@link MastershipData} to remove.
     *
     * @param master {@link MastershipData} to remove. (Role is ignored)
     */
    @GuardedBy("writeLock")
    protected void removeSwitchMastershipData(MastershipData master) {
        checkNotNull(master);

        SortedSet<MastershipData> candidates
            = mastership.get(master.getDpid());
        if (candidates == null) {
            // nothing to do
            return;
        }
        candidates.remove(master);
    }


    @Override
    public void acquireReadLock() {
        readLock.lock();
    }

    @Override
    public void releaseReadLock() {
        readLock.unlock();
    }

    protected void acquireWriteLock() {
        writeLock.lock();
    }

    protected void releaseWriteLock() {
        writeLock.unlock();
    }
}
