/*
 *  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.PortNumber;
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.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onosproject.ui.model.topo.UiLinkId.uiLinkId;

/**
 * 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, UiDeviceLink> devLinkLookup = new HashMap<>();
    private final Map<UiLinkId, UiEdgeLink> edgeLinkLookup = new HashMap<>();

    // a cache of the computed synthetic links
    private final List<UiSynthLink> synthLinks = new ArrayList<>();

    // 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("#dev-links", devLinkLookup.size())
                .add("#edge-links", edgeLinkLookup.size())
                .add("#synth-links", synthLinks.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();
        devLinkLookup.clear();
        edgeLinkLookup.clear();

        synthLinks.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 device links in the model.
     *
     * @return all device links
     */
    public Set<UiDeviceLink> allDeviceLinks() {
        return new HashSet<>(devLinkLookup.values());
    }

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

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

    /**
     * Adds the given UI device link to the topology model.
     *
     * @param uiDeviceLink link to add
     */
    public void add(UiDeviceLink uiDeviceLink) {
        devLinkLookup.put(uiDeviceLink.id(), uiDeviceLink);
    }

    /**
     * Adds the given UI edge link to the topology model.
     *
     * @param uiEdgeLink link to add
     */
    public void add(UiEdgeLink uiEdgeLink) {
        edgeLinkLookup.put(uiEdgeLink.id(), uiEdgeLink);
    }

    /**
     * Removes the given UI device link from the model.
     *
     * @param uiDeviceLink link to remove
     */
    public void remove(UiDeviceLink uiDeviceLink) {
        UiDeviceLink link = devLinkLookup.remove(uiDeviceLink.id());
        if (link != null) {
            link.destroy();
        }
    }

    /**
     * Removes the given UI edge link from the model.
     *
     * @param uiEdgeLink link to remove
     */
    public void remove(UiEdgeLink uiEdgeLink) {
        UiEdgeLink link = edgeLinkLookup.remove(uiEdgeLink.id());
        if (link != null) {
            link.destroy();
        }
    }

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

    /**
     * Returns the number of edge links configured in the topology.
     *
     * @return number of edge links
     */
    public int edgeLinkCount() {
        return edgeLinkLookup.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 device links with the given identifiers.
     *
     * @param uiLinkIds link identifiers
     * @return set of matching UI device link instances
     */
    Set<UiDeviceLink> linkSet(Set<UiLinkId> uiLinkIds) {
        Set<UiDeviceLink> result = new HashSet<>();
        for (UiLinkId id : uiLinkIds) {
            UiDeviceLink link = devLinkLookup.get(id);
            if (link != null) {
                result.add(link);
            } else {
                log.warn(E_UNMAPPED, "device link", id);
            }
        }
        return result;
    }

    /**
     * Uses the device-device links and data about the regions to compute the
     * set of synthetic links that are required per region.
     */
    public void computeSynthLinks() {
        List<UiSynthLink> slinks = new ArrayList<>();
        allDeviceLinks().forEach((link) -> {
            UiSynthLink synthetic = inferSyntheticLink(link);
            slinks.add(synthetic);
            log.debug("Synthetic link: {}", synthetic);
        });


        synthLinks.clear();
        synthLinks.addAll(slinks);

        // TODO : compute and add host-device links to synthLinks...

    }

    private UiSynthLink inferSyntheticLink(UiDeviceLink link) {
        /*
          Look at the containment hierarchy of each end of the link. Find the
          common ancestor region R. A synthetic link will be added to R, based
          on the "next" node back down the branch...

                S1 --- S2       * in the same region ...
                :      :
                R      R          return S1 --- S2 (same link instance)


                S1 --- S2       * in different regions (R1, R2) at same level
                :      :
                R1     R2         return R1 --- R2
                :      :
                R      R

                S1 --- S2       * in different regions at different levels
                :      :
                R1     R2         return R1 --- R3
                :      :
                R      R3
                       :
                       R

                S1 --- S2       * in different regions at different levels
                :      :
                R      R2         return S1 --- R2
                       :
                       R

         */
        DeviceId a = link.deviceA();
        DeviceId b = link.deviceB();
        List<RegionId> aBranch = ancestors(a);
        List<RegionId> bBranch = ancestors(b);
        if (aBranch == null || bBranch == null) {
            return null;
        }

        return makeSynthLink(link, aBranch, bBranch);
    }

    // package private for unit testing
    UiSynthLink makeSynthLink(UiDeviceLink orig,
                              List<RegionId> aBranch,
                              List<RegionId> bBranch) {

        final int aSize = aBranch.size();
        final int bSize = bBranch.size();
        final int min = Math.min(aSize, bSize);

        int index = 0;
        RegionId commonRegion = aBranch.get(index);

        while (true) {
            int next = index + 1;
            if (next == min) {
                // no more pairs of regions left to test
                break;
            }
            RegionId rA = aBranch.get(next);
            RegionId rB = bBranch.get(next);
            if (rA.equals(rB)) {
                commonRegion = rA;
                index++;
            } else {
                break;
            }
        }


        int endPointIndex = index + 1;
        UiLinkId linkId;
        UiLink link;

        if (endPointIndex < aSize) {
            // the A endpoint is a subregion
            RegionId aRegion = aBranch.get(endPointIndex);

            if (endPointIndex < bSize) {
                // the B endpoint is a subregion
                RegionId bRegion = bBranch.get(endPointIndex);

                linkId = uiLinkId(aRegion, bRegion);
                link = new UiRegionLink(this, linkId);

            } else {
                // the B endpoint is the device
                DeviceId dB = orig.deviceB();
                PortNumber pB = orig.portB();

                linkId = uiLinkId(aRegion, dB, pB);
                link = new UiRegionDeviceLink(this, linkId);
            }

        } else {
            // the A endpoint is the device
            DeviceId dA = orig.deviceA();
            PortNumber pA = orig.portA();

            if (endPointIndex < bSize) {
                // the B endpoint is a subregion
                RegionId bRegion = bBranch.get(endPointIndex);

                linkId = uiLinkId(bRegion, dA, pA);
                link = new UiRegionDeviceLink(this, linkId);

            } else {
                // the B endpoint is the device
                // (so, we can just use the original device-device link...)

                link = orig;
            }
        }
        return new UiSynthLink(commonRegion, link);
    }

    private List<RegionId> ancestors(DeviceId id) {
        // return the ancestor chain from this device to root region
        UiDevice dev = findDevice(id);
        if (dev == null) {
            log.warn("Unable to find cached device with ID %s", id);
            return null;
        }

        UiRegion r = dev.uiRegion();
        List<RegionId> result = new ArrayList<>();
        while (r != null && !r.isRoot()) {
            result.add(0, r.id());
            r = r.parentRegion();
        }
        // finally add root region, since this is the grand-daddy of them all
        result.add(0, UiRegion.NULL_ID);
        return result;
    }


    /**
     * Returns the synthetic links associated with the specified region.
     *
     * @param regionId the region ID
     * @return synthetic links for this region
     */
    public List<UiSynthLink> findSynthLinks(RegionId regionId) {
        return synthLinks.stream()
                .filter(s -> Objects.equals(regionId, s.regionId()))
                .collect(Collectors.toList());
    }


    /**
     * Returns the number of synthetic links in the topology.
     *
     * @return the synthetic link count
     */
    public int synthLinkCount() {
        return synthLinks.size();
    }

    /**
     * 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("Device Links").append(EOL);
        for (UiLink link : devLinkLookup.values()) {
            sb.append(INDENT_2).append(link).append(EOL);
        }

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

        sb.append(INDENT_1).append("Synth Links").append(EOL);
        for (UiSynthLink link : synthLinks) {
            sb.append(INDENT_2).append(link).append(EOL);
        }
        sb.append("------").append(EOL);

        return sb.toString();
    }
}
