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

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.topology.ClusterId;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyCluster;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.rest.AbstractWebResource;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;

import static org.onlab.util.Tools.nullIsNotFound;

/**
 * Query network topology graph and its components.
 */
@Path("topology")
public class TopologyWebResource extends AbstractWebResource {

    public static final String CLUSTER_NOT_FOUND = "Cluster is not found";

    /**
     * Get overview of current topology.
     *
     * @return topology overview
     * @onos.rsModel Topology
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getTopology() {
        Topology topology = get(TopologyService.class).currentTopology();
        ObjectNode root = codec(Topology.class).encode(topology, this);
        return ok(root).build();
    }

    /**
     * Get overview of topology SCCs.
     *
     * @return topology clusters overview
     * @onos.rsModel TopologyClusters
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("clusters")
    public Response getClusters() {
        TopologyService service = get(TopologyService.class);
        Topology topology = service.currentTopology();
        Iterable<TopologyCluster> clusters = service.getClusters(topology);
        ObjectNode root = encodeArray(TopologyCluster.class, "clusters", clusters);
        return ok(root).build();
    }

    /**
     * Get details of a specific SCC.
     *
     * @param clusterId id of the cluster to query
     * @return topology cluster details
     * @onos.rsModel TopologyCluster
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("clusters/{id}")
    public Response getCluster(@PathParam("id") int clusterId) {
        Topology topology = get(TopologyService.class).currentTopology();
        TopologyCluster cluster = getTopologyCluster(clusterId, topology);
        ObjectNode root = codec(TopologyCluster.class).encode(cluster, this);
        return ok(root).build();
    }

    private TopologyCluster getTopologyCluster(int clusterId, Topology topology) {
        return nullIsNotFound(
                get(TopologyService.class)
                        .getCluster(topology, ClusterId.clusterId(clusterId)),
                CLUSTER_NOT_FOUND);
    }

    /**
     * Get devices in a specific SCC.
     *
     * @param clusterId id of the cluster to query
     * @return topology cluster devices
     * @onos.rsModel TopologyClustersDevices
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("clusters/{id}/devices")
    public Response getClusterDevices(@PathParam("id") int clusterId) {
        TopologyService service = get(TopologyService.class);
        Topology topology = service.currentTopology();
        TopologyCluster cluster = getTopologyCluster(clusterId, topology);

        List<DeviceId> deviceIds =
                Lists.newArrayList(service.getClusterDevices(topology, cluster));

        ObjectNode root = mapper().createObjectNode();
        ArrayNode devicesNode = root.putArray("devices");
        deviceIds.forEach(id -> devicesNode.add(id.toString()));
        return ok(root).build();
    }

    /**
     * Get links in specific SCC.
     *
     * @param clusterId id of the cluster to query
     * @return topology cluster links
     * @onos.rsModel LinksGet
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("clusters/{id}/links")
    public Response getClusterLinks(@PathParam("id") int clusterId) {
        Topology topology = get(TopologyService.class).currentTopology();
        TopologyCluster cluster = getTopologyCluster(clusterId, topology);

        List<Link> links =
                Lists.newArrayList(get(TopologyService.class)
                                           .getClusterLinks(topology, cluster));

        return ok(encodeArray(Link.class, "links", links)).build();
    }

    /**
     * Extracts the port number portion of the ConnectPoint.
     *
     * @param deviceString string representing the device/port
     * @return port number as a string, empty string if the port is not found
     */
    private static String getPortNumber(String deviceString) {
        int separator = deviceString.lastIndexOf(':');
        if (separator <= 0) {
            return "";
        }
        return deviceString.substring(separator + 1, deviceString.length());
    }

    /**
     * Extracts the device ID portion of the ConnectPoint.
     *
     * @param deviceString string representing the device/port
     * @return device ID string
     */
    private static String getDeviceId(String deviceString) {
        int separator = deviceString.lastIndexOf(':');
        if (separator <= 0) {
            return "";
        }
        return deviceString.substring(0, separator);
    }

    /**
     * Test if a connect point is in broadcast set.
     *
     * @param connectPointString deviceid:portnumber
     * @return JSON representation of true if the connect point is broadcast,
     * false otherwise
     * @onos.rsModel TopologyBroadcast
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("broadcast/{connectPoint}")
    public Response getConnectPointBroadcast(@PathParam("connectPoint") String connectPointString) {
        Topology topology = get(TopologyService.class).currentTopology();

        DeviceId deviceId = DeviceId.deviceId(getDeviceId(connectPointString));
        PortNumber portNumber = PortNumber.portNumber(getPortNumber(connectPointString));
        ConnectPoint connectPoint = new ConnectPoint(deviceId, portNumber);
        boolean isBroadcast = get(TopologyService.class).isBroadcastPoint(topology, connectPoint);

        return ok(mapper()
                          .createObjectNode()
                          .put("broadcast", isBroadcast))
                .build();
    }

    /**
     * Test if a connect point is infrastructure or edge.
     *
     * @param connectPointString deviceid:portnumber
     * @return JSON representation of true if the connect point is broadcast,
     * false otherwise
     * @onos.rsModel TopologyInfrastructure
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("infrastructure/{connectPoint}")
    public Response getConnectPointInfrastructure(@PathParam("connectPoint") String connectPointString) {
        Topology topology = get(TopologyService.class).currentTopology();

        DeviceId deviceId = DeviceId.deviceId(getDeviceId(connectPointString));
        PortNumber portNumber = PortNumber.portNumber(getPortNumber(connectPointString));
        ConnectPoint connectPoint = new ConnectPoint(deviceId, portNumber);
        boolean isInfrastructure = get(TopologyService.class).isInfrastructure(topology, connectPoint);

        return ok(mapper()
                          .createObjectNode()
                          .put("infrastructure", isInfrastructure))
                .build();
    }

}
