/*
 *  Copyright 2016-present Open Networking Laboratory
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.onosproject.ui.model.topo;

import org.onosproject.cluster.NodeId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.region.RegionId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import static com.google.common.base.MoreObjects.toStringHelper;

/**
 * Represents the overall network topology.
 */
public class UiTopology extends UiElement {

    private static final String INDENT_1 = "  ";
    private static final String INDENT_2 = "    ";
    private static final String EOL = String.format("%n");

    private static final String E_UNMAPPED =
            "Attempting to retrieve unmapped {}: {}";

    private static final String DEFAULT_TOPOLOGY_ID = "TOPOLOGY-0";

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

    private static final Comparator<UiClusterMember> CLUSTER_MEMBER_COMPARATOR =
            (o1, o2) -> o1.idAsString().compareTo(o2.idAsString());


    // top level mappings of topology elements by ID
    private final Map<NodeId, UiClusterMember> cnodeLookup = new HashMap<>();
    private final Map<RegionId, UiRegion> regionLookup = new HashMap<>();
    private final Map<DeviceId, UiDevice> deviceLookup = new HashMap<>();
    private final Map<HostId, UiHost> hostLookup = new HashMap<>();
    private final Map<UiLinkId, UiLink> linkLookup = new HashMap<>();

    // a container for devices, hosts, etc. belonging to no region
    private final UiRegion nullRegion = new UiRegion(this, null);


    @Override
    public String toString() {
        return toStringHelper(this)
                .add("#cnodes", clusterMemberCount())
                .add("#regions", regionCount())
                .add("#devices", deviceLookup.size())
                .add("#hosts", hostLookup.size())
                .add("#links", linkLookup.size())
                .toString();
    }

    @Override
    public String idAsString() {
        return DEFAULT_TOPOLOGY_ID;
    }

    /**
     * Clears the topology state; that is, drops all regions, devices, hosts,
     * links, and cluster members.
     */
    public void clear() {
        log.debug("clearing topology model");
        cnodeLookup.clear();
        regionLookup.clear();
        deviceLookup.clear();
        hostLookup.clear();
        linkLookup.clear();

        nullRegion.destroy();
    }


    /**
     * Returns all the cluster members, sorted by their ID.
     *
     * @return all cluster members
     */
    public List<UiClusterMember> allClusterMembers() {
        List<UiClusterMember> members = new ArrayList<>(cnodeLookup.values());
        Collections.sort(members, CLUSTER_MEMBER_COMPARATOR);
        return members;
    }

    /**
     * Returns the cluster member with the given identifier, or null if no
     * such member exists.
     *
     * @param id cluster node identifier
     * @return corresponding UI cluster member
     */
    public UiClusterMember findClusterMember(NodeId id) {
        return cnodeLookup.get(id);
    }

    /**
     * Adds the given cluster member to the topology model.
     *
     * @param member cluster member to add
     */
    public void add(UiClusterMember member) {
        cnodeLookup.put(member.id(), member);
    }

    /**
     * Removes the given cluster member from the topology model.
     *
     * @param member cluster member to remove
     */
    public void remove(UiClusterMember member) {
        UiClusterMember m = cnodeLookup.remove(member.id());
        if (m != null) {
            m.destroy();
        }
    }

    /**
     * Returns the number of members in the cluster.
     *
     * @return number of cluster members
     */
    public int clusterMemberCount() {
        return cnodeLookup.size();
    }


    /**
     * Returns all regions in the model (except the
     * {@link #nullRegion() null region}).
     *
     * @return all regions
     */
    public Set<UiRegion> allRegions() {
        return new HashSet<>(regionLookup.values());
    }

    /**
     * Returns a reference to the null-region. That is, the container for
     * devices, hosts, and links that belong to no region.
     *
     * @return the null-region
     */
    public UiRegion nullRegion() {
        return nullRegion;
    }

    /**
     * Returns the region with the specified identifier, or null if
     * no such region exists.
     *
     * @param id region identifier
     * @return corresponding UI region
     */
    public UiRegion findRegion(RegionId id) {
        return UiRegion.NULL_ID.equals(id) ? nullRegion() : regionLookup.get(id);
    }

    /**
     * Adds the given region to the topology model.
     *
     * @param uiRegion region to add
     */
    public void add(UiRegion uiRegion) {
        regionLookup.put(uiRegion.id(), uiRegion);
    }

    /**
     * Removes the given region from the topology model.
     *
     * @param uiRegion region to remove
     */
    public void remove(UiRegion uiRegion) {
        UiRegion r = regionLookup.remove(uiRegion.id());
        if (r != null) {
            r.destroy();
        }
    }

    /**
     * Returns the number of regions configured in the topology.
     *
     * @return number of regions
     */
    public int regionCount() {
        return regionLookup.size();
    }

    /**
     * Returns all devices in the model.
     *
     * @return all devices
     */
    public Set<UiDevice> allDevices() {
        return new HashSet<>(deviceLookup.values());
    }

    /**
     * Returns the device with the specified identifier, or null if
     * no such device exists.
     *
     * @param id device identifier
     * @return corresponding UI device
     */
    public UiDevice findDevice(DeviceId id) {
        return deviceLookup.get(id);
    }

    /**
     * Adds the given device to the topology model.
     *
     * @param uiDevice device to add
     */
    public void add(UiDevice uiDevice) {
        deviceLookup.put(uiDevice.id(), uiDevice);
    }

    /**
     * Removes the given device from the topology model.
     *
     * @param uiDevice device to remove
     */
    public void remove(UiDevice uiDevice) {
        UiDevice d = deviceLookup.remove(uiDevice.id());
        if (d != null) {
            d.destroy();
        }
    }

    /**
     * Returns the number of devices configured in the topology.
     *
     * @return number of devices
     */
    public int deviceCount() {
        return deviceLookup.size();
    }

    /**
     * Returns all links in the model.
     *
     * @return all links
     */
    public Set<UiLink> allLinks() {
        return new HashSet<>(linkLookup.values());
    }

    /**
     * Returns the link with the specified identifier, or null if no such
     * link exists.
     *
     * @param id the canonicalized link identifier
     * @return corresponding UI link
     */
    public UiLink findLink(UiLinkId id) {
        return linkLookup.get(id);
    }

    /**
     * Adds the given UI link to the topology model.
     *
     * @param uiLink link to add
     */
    public void add(UiLink uiLink) {
        linkLookup.put(uiLink.id(), uiLink);
    }

    /**
     * Removes the given UI link from the model.
     *
     * @param uiLink link to remove
     */
    public void remove(UiLink uiLink) {
        UiLink link = linkLookup.remove(uiLink.id());
        if (link != null) {
            link.destroy();
        }
    }

    /**
     * Returns the number of links configured in the topology.
     *
     * @return number of links
     */
    public int linkCount() {
        return linkLookup.size();
    }

    /**
     * Returns all hosts in the model.
     *
     * @return all hosts
     */
    public Set<UiHost> allHosts() {
        return new HashSet<>(hostLookup.values());
    }

    /**
     * Returns the host with the specified identifier, or null if no such
     * host exists.
     *
     * @param id host identifier
     * @return corresponding UI host
     */
    public UiHost findHost(HostId id) {
        return hostLookup.get(id);
    }

    /**
     * Adds the given host to the topology model.
     *
     * @param uiHost host to add
     */
    public void add(UiHost uiHost) {
        hostLookup.put(uiHost.id(), uiHost);
    }

    /**
     * Removes the given host from the topology model.
     *
     * @param uiHost host to remove
     */
    public void remove(UiHost uiHost) {
        UiHost h = hostLookup.remove(uiHost.id());
        if (h != null) {
            h.destroy();
        }
    }

    /**
     * Returns the number of hosts configured in the topology.
     *
     * @return number of hosts
     */
    public int hostCount() {
        return hostLookup.size();
    }


    // ==
    // package private methods for supporting linkage amongst topology entities
    // ==

    /**
     * Returns the set of UI devices with the given identifiers.
     *
     * @param deviceIds device identifiers
     * @return set of matching UI device instances
     */
    Set<UiDevice> deviceSet(Set<DeviceId> deviceIds) {
        Set<UiDevice> uiDevices = new HashSet<>();
        for (DeviceId id : deviceIds) {
            UiDevice d = deviceLookup.get(id);
            if (d != null) {
                uiDevices.add(d);
            } else {
                log.warn(E_UNMAPPED, "device", id);
            }
        }
        return uiDevices;
    }

    /**
     * Returns the set of UI hosts with the given identifiers.
     *
     * @param hostIds host identifiers
     * @return set of matching UI host instances
     */
    Set<UiHost> hostSet(Set<HostId> hostIds) {
        Set<UiHost> uiHosts = new HashSet<>();
        for (HostId id : hostIds) {
            UiHost h = hostLookup.get(id);
            if (h != null) {
                uiHosts.add(h);
            } else {
                log.warn(E_UNMAPPED, "host", id);
            }
        }
        return uiHosts;
    }

    /**
     * Returns the set of UI links with the given identifiers.
     *
     * @param uiLinkIds link identifiers
     * @return set of matching UI link instances
     */
    Set<UiLink> linkSet(Set<UiLinkId> uiLinkIds) {
        Set<UiLink> uiLinks = new HashSet<>();
        for (UiLinkId id : uiLinkIds) {
            UiLink link = linkLookup.get(id);
            if (link != null) {
                uiLinks.add(link);
            } else {
                log.warn(E_UNMAPPED, "link", id);
            }
        }
        return uiLinks;
    }

    /**
     * Returns a detailed (multi-line) string showing the contents of the
     * topology.
     *
     * @return detailed string
     */
    public String dumpString() {
        StringBuilder sb = new StringBuilder("Topology:").append(EOL);

        sb.append(INDENT_1).append("Cluster Members").append(EOL);
        for (UiClusterMember m : cnodeLookup.values()) {
            sb.append(INDENT_2).append(m).append(EOL);
        }

        sb.append(INDENT_1).append("Regions").append(EOL);
        for (UiRegion r : regionLookup.values()) {
            sb.append(INDENT_2).append(r).append(EOL);
        }

        sb.append(INDENT_1).append("Devices").append(EOL);
        for (UiDevice d : deviceLookup.values()) {
            sb.append(INDENT_2).append(d).append(EOL);
        }

        sb.append(INDENT_1).append("Hosts").append(EOL);
        for (UiHost h : hostLookup.values()) {
            sb.append(INDENT_2).append(h).append(EOL);
        }

        sb.append(INDENT_1).append("Links").append(EOL);
        for (UiLink link : linkLookup.values()) {
            sb.append(INDENT_2).append(link).append(EOL);
        }
        sb.append("------").append(EOL);

        return sb.toString();
    }

}
