/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.impl.topo;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.incubator.net.PortStatisticsService;
import org.onosproject.incubator.net.tunnel.TunnelService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Annotated;
import org.onosproject.net.Annotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.region.Region;
import org.onosproject.net.statistic.StatisticService;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.ui.GlyphConstants;
import org.onosproject.ui.JsonUtils;
import org.onosproject.ui.UiExtensionService;
import org.onosproject.ui.UiPreferencesService;
import org.onosproject.ui.UiTopoMap;
import org.onosproject.ui.UiTopoMapFactory;
import org.onosproject.ui.model.topo.UiClusterMember;
import org.onosproject.ui.model.topo.UiDevice;
import org.onosproject.ui.model.topo.UiElement;
import org.onosproject.ui.model.topo.UiHost;
import org.onosproject.ui.model.topo.UiLink;
import org.onosproject.ui.model.topo.UiLinkId;
import org.onosproject.ui.model.topo.UiModelEvent;
import org.onosproject.ui.model.topo.UiNode;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiSynthLink;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.onosproject.ui.topo.LayoutLocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.AnnotationKeys.GRID_X;
import static org.onosproject.net.AnnotationKeys.GRID_Y;
import static org.onosproject.net.AnnotationKeys.LATITUDE;
import static org.onosproject.net.AnnotationKeys.LONGITUDE;
import static org.onosproject.ui.model.topo.UiNode.LAYER_DEFAULT;
import static org.onosproject.ui.topo.LayoutLocation.fromCompactListString;

/**
 * Facility for creating JSON messages to send to the topology view in the
 * Web client.
 */
public class Topo2Jsonifier {

    private static final String E_DEF_NOT_LAST =
            "UiNode.LAYER_DEFAULT not last in layer list";
    private static final String E_UNKNOWN_UI_NODE =
            "Unknown subclass of UiNode: ";

    private static final String CONTEXT_KEY_DELIM = "_";
    private static final String NO_CONTEXT = "";
    private static final String ZOOM_KEY = "layoutZoom";

    private static final String REGION = "region";
    private static final String DEVICE = "device";
    private static final String HOST = "host";
    private static final String TYPE = "type";
    private static final String SUBJECT = "subject";
    private static final String DATA = "data";
    private static final String MEMO = "memo";

    private static final String GEO = "geo";
    private static final String GRID = "grid";
    private static final String PEER_LOCATIONS = "peerLocations";
    private static final String LOCATION = "location";
    private static final String LOC_TYPE = "locType";
    private static final String LAT_OR_Y = "latOrY";
    private static final String LONG_OR_X = "longOrX";

    private final Logger log = LoggerFactory.getLogger(getClass());

    private final ObjectMapper mapper = new ObjectMapper();

    // preferences are stored per user name...
    private final String userName;

    private ServiceDirectory directory;
    private ClusterService clusterService;
    private DeviceService deviceService;
    private LinkService linkService;
    private HostService hostService;
    private MastershipService mastershipService;
    private IntentService intentService;
    private FlowRuleService flowService;
    private StatisticService flowStatsService;
    private PortStatisticsService portStatsService;
    private TopologyService topologyService;
    private TunnelService tunnelService;
    private UiExtensionService uiextService;
    private UiPreferencesService prefService;


    // NOTE: we'll stick this here for now, but maybe there is a better home?
    //       (this is not distributed across the cluster)
    private static Map<String, ObjectNode> metaUi = new ConcurrentHashMap<>();


    /**
     * Creates an instance with a reference to the services directory, so that
     * additional information about network elements may be looked up on
     * on the fly.
     *
     * @param directory service directory
     * @param userName  logged in user name
     */
    public Topo2Jsonifier(ServiceDirectory directory, String userName) {
        this.directory = checkNotNull(directory, "Directory cannot be null");
        this.userName = checkNotNull(userName, "User name cannot be null");

        clusterService = directory.get(ClusterService.class);
        deviceService = directory.get(DeviceService.class);
        linkService = directory.get(LinkService.class);
        hostService = directory.get(HostService.class);
        mastershipService = directory.get(MastershipService.class);
        intentService = directory.get(IntentService.class);
        flowService = directory.get(FlowRuleService.class);
        flowStatsService = directory.get(StatisticService.class);
        portStatsService = directory.get(PortStatisticsService.class);
        topologyService = directory.get(TopologyService.class);
        tunnelService = directory.get(TunnelService.class);
        uiextService = directory.get(UiExtensionService.class);
        prefService = directory.get(UiPreferencesService.class);
    }

    // for unit testing
    Topo2Jsonifier() {
        userName = "(unit-test)";
    }

    private ObjectNode objectNode() {
        return mapper.createObjectNode();
    }

    private ArrayNode arrayNode() {
        return mapper.createArrayNode();
    }

    private String nullIsEmpty(Object o) {
        return o == null ? "" : o.toString();
    }


    /**
     * Returns a JSON representation of the cluster members (ONOS instances).
     *
     * @param instances the instance model objects
     * @return a JSON representation of the data
     */
    ObjectNode instances(List<UiClusterMember> instances) {
        NodeId local = clusterService.getLocalNode().id();
        ObjectNode payload = objectNode();

        ArrayNode members = arrayNode();
        payload.set("members", members);
        for (UiClusterMember member : instances) {
            members.add(json(member, member.id().equals(local)));
        }

        return payload;
    }

    private ObjectNode json(UiClusterMember member, boolean isUiAttached) {
        int switchCount = mastershipService.getDevicesOf(member.id()).size();
        ControllerNode.State state = clusterService.getState(member.id());
        return objectNode()
                .put("id", member.id().toString())
                .put("ip", member.ip().toString())
                .put("online", state.isActive())
                .put("ready", state.isReady())
                .put("uiAttached", isUiAttached)
                .put("switches", switchCount);
    }

    /**
     * Returns a JSON representation of the layout to use for displaying in
     * the topology view. The identifiers and names of regions from the
     * current to the root is included, so that the bread-crumb widget can
     * be rendered.
     *
     * @param layout the layout to transform
     * @param crumbs list of layouts in bread-crumb order
     * @return a JSON representation of the data
     */
    ObjectNode layout(UiTopoLayout layout, List<UiTopoLayout> crumbs) {
        ObjectNode result = objectNode()
                .put("id", layout.id().toString())
                .put("parent", nullIsEmpty(layout.parent()))
                .put("region", nullIsEmpty(layout.regionId()))
                .put("regionName", UiRegion.safeName(layout.region()));
        addCrumbs(result, crumbs);
        addBgRef(result, layout);
        return result;
    }

    private void addBgRef(ObjectNode result, UiTopoLayout layout) {
        String mapId = layout.geomap();
        String sprId = layout.sprites();

        if (mapId != null) {
            result.put("bgType", GEO).put("bgId", mapId);
            addMapParameters(result, mapId);
        } else if (sprId != null) {
            result.put("bgType", GRID).put("bgId", sprId);
        }

        attachZoomData(result, layout);
    }

    private void attachZoomData(ObjectNode result, UiTopoLayout layout) {

        ObjectNode zoomData = objectNode();

        // first, set configured scale and offset
        addCfgZoomData(zoomData, layout);

        // next, retrieve user-set zoom data, if we have it
        String rid = layout.regionId().toString();
        ObjectNode userZoom = metaUi.get(contextKey(rid, ZOOM_KEY));
        if (userZoom != null) {
            zoomData.set("usr", userZoom);
        }
        result.set("bgZoom", zoomData);
    }

    private void addCfgZoomData(ObjectNode data, UiTopoLayout layout) {
        ObjectNode zoom = objectNode();
        zoom.put("scale", layout.scale());
        zoom.put("offsetX", layout.offsetX());
        zoom.put("offsetY", layout.offsetY());
        data.set("cfg", zoom);
    }

    private void addMapParameters(ObjectNode result, String mapId) {

        // TODO: This ought to be written more efficiently.

        // ALSO: Should retrieving a UiTopoMap by ID be something that
        //       the UiExtensionService provides, along with other
        //       useful lookups?
        //
        //       Or should it remain very basic / general?
        //
        //       return uiextService.getTopoMap(String mapId);

        final UiTopoMap[] map = {null};

        uiextService.getExtensions().forEach(ext -> {
            UiTopoMapFactory factory = ext.topoMapFactory();

            // TODO: use .stream().filter(...) here
            if (map[0] == null && factory != null) {
                List<UiTopoMap> topoMaps = factory.geoMaps();

                topoMaps.forEach(m -> {
                    if (map[0] == null && m.id().equals(mapId)) {
                        map[0] = m;
                    }
                });
            }
        });

        UiTopoMap m = map[0];
        if (m != null) {
            result.put("bgDesc", m.description())
                    .put("bgFilePath", m.filePath())
                    .put("bgDefaultScale", m.scale());
        } else {
            result.put("bgWarn", "no map registered with id: " + mapId);
        }
    }

    private void addCrumbs(ObjectNode result, List<UiTopoLayout> crumbs) {
        ArrayNode trail = arrayNode();
        crumbs.forEach(c -> {
            ObjectNode n = objectNode()
                    .put("id", c.regionId().toString())
                    .put("name", UiRegion.safeName(c.region()));
            trail.add(n);
        });
        result.set("crumbs", trail);
    }

    /**
     * Returns a JSON representation of the region to display in the topology
     * view.
     *
     * @param region     the region to transform to JSON
     * @param subRegions the subregions within this region
     * @param links      the links within this region
     * @return a JSON representation of the data
     */
    ObjectNode region(UiRegion region, Set<UiRegion> subRegions,
                      List<UiSynthLink> links) {
        ObjectNode payload = objectNode();
        if (region == null) {
            payload.put("note", "no-region");
            return payload;
        }

        String ridStr = region.idAsString();

        payload.put("id", ridStr);
        payload.set("subregions", jsonSubRegions(ridStr, subRegions));
        payload.set("links", jsonLinks(links));

        List<String> layerTags = region.layerOrder();
        List<Set<UiNode>> splitDevices = splitByLayer(layerTags, region.devices());
        List<Set<UiNode>> splitHosts = splitByLayer(layerTags, region.hosts());

        payload.set("devices", jsonGrouped(ridStr, splitDevices));
        payload.set("hosts", jsonGrouped(ridStr, splitHosts));
        payload.set("layerOrder", jsonStrings(layerTags));

        if (!region.isRoot()) {
            addPeerLocations(payload, region.backingRegion());
        }

        return payload;
    }

    private ArrayNode jsonSubRegions(String ridStr, Set<UiRegion> subregions) {
        ArrayNode kids = arrayNode();
        subregions.forEach(s -> kids.add(jsonClosedRegion(ridStr, s)));
        return kids;
    }

    protected JsonNode jsonLinks(List<UiSynthLink> links) {
        return collateSynthLinks(links);
    }

    private ArrayNode jsonStrings(List<String> strings) {
        ArrayNode array = arrayNode();
        strings.forEach(array::add);
        return array;
    }

    private ArrayNode jsonGrouped(String ridStr, List<Set<UiNode>> groupedNodes) {
        ArrayNode result = arrayNode();
        groupedNodes.forEach(g -> {
            ArrayNode subset = arrayNode();
            g.forEach(n -> subset.add(json(ridStr, n)));
            result.add(subset);
        });
        return result;
    }

    /**
     * Creates a JSON representation of a UI element.
     *
     * @param element the source element
     * @return a JSON representation of that element
     */
    public ObjectNode jsonUiElement(UiElement element) {
        if (element instanceof UiNode) {
            return json(NO_CONTEXT, (UiNode) element);
        }
        if (element instanceof UiLink) {
            return json((UiLink) element);
        }
        if (element instanceof UiClusterMember) {
            return json((UiClusterMember) element);
        }

        // Unrecognized UiElement class
        return objectNode()
                .put("warning", "unknown UiElement... cannot encode")
                .put("javaclass", element.getClass().toString());
    }

    /**
     * Creates a JSON representation of a UI model event.
     *
     * @param modelEvent the source model event
     * @return a JSON representation of that event
     */
    public ObjectNode jsonEvent(UiModelEvent modelEvent) {
        ObjectNode payload = objectNode();
        payload.put(TYPE, enumToString(modelEvent.type()));
        payload.put(SUBJECT, modelEvent.subject().idAsString());
        payload.set(DATA, modelEvent.data());
        payload.put(MEMO, modelEvent.memo());
        return payload;
    }

    // TODO: Investigate why we can't do this inline
    private String enumToString(Enum<?> e) {
        return e.toString();
    }

    // Returns the name of the master node for the specified device id.
    private String master(DeviceId deviceId) {
        NodeId master = mastershipService.getMasterFor(deviceId);
        return master != null ? master.toString() : "";
    }

    private ObjectNode json(String ridStr, UiNode node) {
        if (node instanceof UiRegion) {
            return jsonClosedRegion(ridStr, (UiRegion) node);
        }
        if (node instanceof UiDevice) {
            return json(ridStr, (UiDevice) node);
        }
        if (node instanceof UiHost) {
            return json(ridStr, (UiHost) node);
        }
        throw new IllegalStateException(E_UNKNOWN_UI_NODE + node.getClass());
    }

    private ObjectNode json(String ridStr, UiDevice device) {
        ObjectNode node = objectNode()
                .put("id", device.idAsString())
                .put("nodeType", DEVICE)
                .put("type", device.type())
                .put("online", deviceService.isAvailable(device.id()))
                .put("master", master(device.id()))
                .put("layer", device.layer());
        Device d = device.backingDevice();
        if (d != null) {
            addProps(node, d);
            addGeoGridLocation(node, d);
        }
        addMetaUi(node, ridStr, device.idAsString());

        return node;
    }

    private void addProps(ObjectNode node, Annotated a) {
        Annotations annot = a.annotations();
        ObjectNode props = objectNode();
        if (annot != null) {
            annot.keys().forEach(k -> props.put(k, annot.value(k)));
        }
        node.set("props", props);
    }

    private void addMetaUi(ObjectNode node, String ridStr, String metaInstanceId) {
        String key = contextKey(ridStr, metaInstanceId);
        ObjectNode meta = metaUi.get(key);
        if (meta != null) {
            node.set("metaUi", meta);
        }
    }

    private void addGeoGridLocation(ObjectNode node, Annotated a) {
        List<String> latLongData = getAnnotValues(a, LATITUDE, LONGITUDE);
        List<String> gridYXdata = getAnnotValues(a, GRID_Y, GRID_X);

        if (latLongData != null) {
            attachLocation(node, GEO, latLongData);
        } else if (gridYXdata != null) {
            attachLocation(node, GRID, gridYXdata);
        }
    }

    private void attachLocation(ObjectNode node, String locType,
                                List<String> values) {
        try {
            double latOrY = Double.parseDouble(values.get(0));
            double longOrX = Double.parseDouble(values.get(1));
            ObjectNode loc = objectNode()
                    .put(LOC_TYPE, locType)
                    .put(LAT_OR_Y, latOrY)
                    .put(LONG_OR_X, longOrX);
            node.set(LOCATION, loc);

        } catch (NumberFormatException e) {
            log.warn("Invalid {} data: lat/Y={}, long/X={}",
                     locType, values.get(0), values.get(1));
        }
    }

    private void addPeerLocations(ObjectNode node, Region r) {
        String compact = r.annotations().value(PEER_LOCATIONS);
        if (!Strings.isNullOrEmpty(compact)) {
            List<LayoutLocation> locs = fromCompactListString(compact);

            ObjectNode o = objectNode();
            for (LayoutLocation ll : locs) {
                ObjectNode lnode = objectNode()
                        .put(LOC_TYPE, ll.locType().toString())
                        .put(LAT_OR_Y, ll.latOrY())
                        .put(LONG_OR_X, ll.longOrX());
                o.set(ll.id(), lnode);
            }

            node.set(PEER_LOCATIONS, o);
        }
    }

    private void addIps(ObjectNode node, Host h) {
        Set<IpAddress> ips = h.ipAddresses();

        ArrayNode a = arrayNode();
        for (IpAddress ip : ips) {
            a.add(ip.toString());
        }

        node.set("ips", a);
    }

    // return list of string values from annotated instance, for given keys
    // return null if any keys are not present
    List<String> getAnnotValues(Annotated a, String... annotKeys) {
        List<String> result = new ArrayList<>(annotKeys.length);
        for (String k : annotKeys) {
            String v = a.annotations().value(k);
            if (v == null) {
                return null;
            }
            result.add(v);
        }
        return result;
    }

    // derive JSON object from annotations
    private ObjectNode props(Annotations annotations) {
        ObjectNode p = objectNode();
        if (annotations != null) {
            annotations.keys().forEach(k -> p.put(k, annotations.value(k)));
        }
        return p;
    }

    private ObjectNode json(String ridStr, UiHost host) {
        ObjectNode node = objectNode()
                .put("id", host.idAsString())
                .put("nodeType", HOST)
                .put("layer", host.layer());
        // TODO: complete host details
        Host h = host.backingHost();

        // h will be null, for example, after a HOST_REMOVED event
        if (h != null) {
            addIps(node, h);
            addProps(node, h);
            addGeoGridLocation(node, h);
            node.put("configured", h.configured());
        }
        addMetaUi(node, ridStr, host.idAsString());

        return node;
    }

    private ArrayNode collateSynthLinks(List<UiSynthLink> links) {
        Map<UiLinkId, Set<UiSynthLink>> collation = new HashMap<>();

        // first, group together the synthlinks into sets per ID...
        for (UiSynthLink sl : links) {
            UiLinkId id = sl.link().id();
            Set<UiSynthLink> rollup =
                    collation.computeIfAbsent(id, k -> new HashSet<>());
            rollup.add(sl);
        }

        // now add json nodes per set, and return the array of them
        ArrayNode array = arrayNode();
        for (UiLinkId id : collation.keySet()) {
            array.add(json(collation.get(id)));
        }
        return array;
    }

    private ObjectNode json(Set<UiSynthLink> memberSet) {
        ArrayNode rollup = arrayNode();
        ObjectNode node = null;

        boolean first = true;
        for (UiSynthLink member : memberSet) {
            UiLink link = member.link();
            if (first) {
                node = json(link);
                first = false;
            }
            rollup.add(json(member.original()));
        }
        if (node != null) {
            node.set("rollup", rollup);
        }
        return node;
    }

    private ObjectNode json(UiLink link) {
        ObjectNode data = objectNode()
                .put("id", link.idAsString())
                .put("epA", link.endPointA())
                .put("epB", link.endPointB())
                .put("type", link.type());
        String pA = link.endPortA();
        String pB = link.endPortB();
        if (pA != null) {
            data.put("portA", pA);
        }
        if (pB != null) {
            data.put("portB", pB);
        }
        return data;
    }

    private ObjectNode json(UiClusterMember member) {
        ControllerNode.State state = clusterService.getState(member.id());
        return objectNode()
                .put("id", member.idAsString())
                .put("ip", member.ip().toString())
                .put("online", state.isActive())
                .put("ready", state.isReady())
                .put(GlyphConstants.UI_ATTACHED,
                     member.backingNode().equals(clusterService.getLocalNode()));
    }

    private ObjectNode jsonClosedRegion(String ridStr, UiRegion region) {
        ObjectNode node = objectNode()
                .put("id", region.idAsString())
                .put("name", region.name())
                .put("nodeType", REGION)
                .put("nDevs", region.deviceCount())
                .put("nHosts", region.hostCount());
        // TODO: device and host counts should take into account any nested
        //       subregions. i.e. should be the sum of all devices/hosts in
        //       all descendant subregions.

        Region r = region.backingRegion();
        if (r != null) {
            // add data injected via network configuration script
            addGeoGridLocation(node, r);
            addProps(node, r);
        }

        // this may contain location data, as dragged by user
        // (which should take precedence, over configured data)
        addMetaUi(node, ridStr, region.idAsString());
        return node;
    }

    /**
     * Returns a JSON array representation of a set of regions/devices. Note
     * that the information is sufficient for showing regions as nodes.
     * THe region ID string defines the context (which region) the node is
     * being displayed in.
     *
     * @param ridStr region-id string
     * @param nodes  the nodes
     * @return a JSON representation of the nodes
     */
    public ArrayNode closedNodes(String ridStr, Set<UiNode> nodes) {
        ArrayNode array = arrayNode();
        for (UiNode node : nodes) {
            if (node instanceof UiRegion) {
                array.add(jsonClosedRegion(ridStr, (UiRegion) node));
            } else if (node instanceof UiDevice) {
                array.add(json(ridStr, (UiDevice) node));
            } else {
                log.warn("Unexpected node instance: {}", node.getClass());
            }
        }
        return array;
    }

    // package-private for unit testing
    List<Set<UiNode>> splitByLayer(List<String> layerTags,
                                   Set<? extends UiNode> nodes) {
        final int nLayers = layerTags.size();
        if (!layerTags.get(nLayers - 1).equals(LAYER_DEFAULT)) {
            throw new IllegalArgumentException(E_DEF_NOT_LAST);
        }

        List<Set<UiNode>> splitList = new ArrayList<>(layerTags.size());
        Map<String, Set<UiNode>> byLayer = new HashMap<>(layerTags.size());

        for (String tag : layerTags) {
            Set<UiNode> set = new HashSet<>();
            byLayer.put(tag, set);
            splitList.add(set);
        }

        for (UiNode n : nodes) {
            String which = n.layer();
            if (!layerTags.contains(which)) {
                which = LAYER_DEFAULT;
            }
            byLayer.get(which).add(n);
        }

        return splitList;
    }


    private String contextKey(String context, String key) {
        return context + CONTEXT_KEY_DELIM + key;
    }

    /**
     * Stores the memento for an element.
     * This method assumes the payload has an id String, memento ObjectNode.
     * The region-id string is used as a context within which to store the
     * memento.
     *
     * @param ridStr  region ID string
     * @param payload event payload
     */
    void updateMeta(String ridStr, ObjectNode payload) {

        String id = JsonUtils.string(payload, "id");
        String key = contextKey(ridStr, id);
        metaUi.put(key, JsonUtils.node(payload, "memento"));

        log.debug("Storing metadata for {}", key);
    }
}
