/*
 * 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.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.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.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.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();
        return objectNode()
                .put("id", member.id().toString())
                .put("ip", member.ip().toString())
                .put("online", member.isOnline())
                .put("ready", member.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) {
        ArrayNode synthLinks = arrayNode();
        links.forEach(l -> synthLinks.add(json(l)));

        // TODO: implement the following........
//        collateSynthLinks(synthLinks, links);

        return synthLinks;
    }

    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);
        }

        // TODO: UiClusterMember

        // 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();

        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();

        addIps(node, h);
        addProps(node, h);
        addGeoGridLocation(node, h);
        addMetaUi(node, ridStr, host.idAsString());

        return node;
    }

    // TODO: add method to JSONify an aggregated collection of synth links

    private void collateSynthLinks(ArrayNode array,
                                   List<UiSynthLink> links) {
        // TODO - combine via link id
    }

    private ObjectNode json(UiSynthLink sLink) {
        return json(sLink.link());
    }

    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 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);
    }
}
