/*
 * Copyright 2015 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.topo;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import static org.onosproject.ui.JsonUtils.envelope;

/**
 * JSON utilities for the Topology View.
 */
public final class TopoJson {
    // package-private for unit test access
    static final String SHOW_HIGHLIGHTS = "showHighlights";

    static final String DEVICES = "devices";
    static final String HOSTS = "hosts";
    static final String LINKS = "links";
    static final String SUBDUE = "subdue";

    static final String ID = "id";
    static final String LABEL = "label";
    static final String CSS = "css";

    static final String TITLE = "title";
    static final String TYPE = "type";
    static final String PROP_ORDER = "propOrder";
    static final String PROPS = "props";
    static final String BUTTONS = "buttons";


    private static final ObjectMapper MAPPER = new ObjectMapper();

    private static ObjectNode objectNode() {
        return MAPPER.createObjectNode();
    }

    private static ArrayNode arrayNode() {
        return MAPPER.createArrayNode();
    }

    // non-instantiable
    private TopoJson() { }

    /**
     * Returns a formatted message ready to send to the topology view
     * to render highlights.
     *
     * @param highlights highlights model to transform
     * @return fully formatted "show highlights" message
     */
    public static ObjectNode highlightsMessage(Highlights highlights) {
        return envelope(SHOW_HIGHLIGHTS, json(highlights));
    }

    /**
     * Transforms the given highlights model into a JSON message payload.
     *
     * @param highlights the model to transform
     * @return JSON payload
     */
    public static ObjectNode json(Highlights highlights) {
        ObjectNode payload = objectNode();

        ArrayNode devices = arrayNode();
        ArrayNode hosts = arrayNode();
        ArrayNode links = arrayNode();

        payload.set(DEVICES, devices);
        payload.set(HOSTS, hosts);
        payload.set(LINKS, links);

        highlights.devices().forEach(dh -> devices.add(json(dh)));
        highlights.hosts().forEach(hh -> hosts.add(json(hh)));
        highlights.links().forEach(lh -> links.add(json(lh)));

        Highlights.Amount toSubdue = highlights.subdueLevel();
        if (!toSubdue.equals(Highlights.Amount.ZERO)) {
            payload.put(SUBDUE, toSubdue.toString());
        }
        return payload;
    }

    private static ObjectNode json(DeviceHighlight dh) {
        ObjectNode n = objectNode()
                .put(ID, dh.elementId());
        if (dh.subdued()) {
            n.put(SUBDUE, true);
        }
        return n;
    }

    private static ObjectNode json(HostHighlight hh) {
        ObjectNode n = objectNode()
                .put(ID, hh.elementId());
        if (hh.subdued()) {
            n.put(SUBDUE, true);
        }
        return n;
    }

    private static ObjectNode json(LinkHighlight lh) {
        ObjectNode n = objectNode()
                .put(ID, lh.elementId())
                .put(LABEL, lh.label())
                .put(CSS, lh.cssClasses());
        if (lh.subdued()) {
            n.put(SUBDUE, true);
        }
        return n;
    }

    /**
     * Translates the given property panel into JSON, for returning
     * to the client.
     *
     * @param pp the property panel model
     * @return JSON payload
     */
    public static ObjectNode json(PropertyPanel pp) {
        ObjectNode result = objectNode()
                .put(TITLE, pp.title())
                .put(TYPE, pp.typeId())
                .put(ID, pp.id());

        ObjectNode pnode = objectNode();
        ArrayNode porder = arrayNode();
        for (PropertyPanel.Prop p : pp.properties()) {
            porder.add(p.key());
            pnode.put(p.key(), p.value());
        }
        result.set(PROP_ORDER, porder);
        result.set(PROPS, pnode);

        ArrayNode buttons = arrayNode();
        for (ButtonId b : pp.buttons()) {
            buttons.add(b.id());
        }
        result.set(BUTTONS, buttons);
        return result;
    }

}
