/*
 * 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 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.impl.topo.model.UiModelEvent;
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.UiNode;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiSynthLink;
import org.onosproject.ui.model.topo.UiTopoLayout;
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;

/**
 * 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 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
     * @param rid    current region id
     * @return a JSON representation of the data
     */
    ObjectNode layout(UiTopoLayout layout, List<UiTopoLayout> crumbs, String rid) {
        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, rid);
        return result;
    }

    private void addBgRef(ObjectNode result, UiTopoLayout layout, String rid) {
        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, rid);
    }

    private void attachZoomData(ObjectNode result, UiTopoLayout layout, String rid) {

        ObjectNode zoomData = objectNode();

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

        // next, retrieve user-set zoom data, if we have it
        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));

        return payload;
    }

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

    private JsonNode jsonLinks(List<UiSynthLink> links) {
        ArrayNode synthLinks = arrayNode();
        links.forEach(l -> synthLinks.add(json(l)));
        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> lngLat = getAnnotValues(a, LONGITUDE, LATITUDE);
        List<String> gridYX = getAnnotValues(a, GRID_Y, GRID_X);

        if (lngLat != null) {
            attachLocation(node, "geo", "lng", "lat", lngLat);
        } else if (gridYX != null) {
            attachLocation(node, "grid", "gridY", "gridX", gridYX);
        }
    }

    private void attachLocation(ObjectNode node, String locType,
                                String keyA, String keyB, List<String> values) {
        try {
            double valA = Double.parseDouble(values.get(0));
            double valB = Double.parseDouble(values.get(1));
            ObjectNode loc = objectNode()
                    .put("type", locType)
                    .put(keyA, valA)
                    .put(keyB, valB);
            node.set("location", loc);

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

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

    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 descendent subregions.

        Region r = region.backingRegion();
        // this is location data, as 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);
    }
}
