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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.rest.AbstractWebResource;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Query and Manage Virtual Network elements.
 */
@Path("vnets")
public class VirtualNetworkWebResource extends AbstractWebResource {

    private static final String MISSING_FIELD = "Missing ";
    private static final String INVALID_FIELD = "Invalid ";

    private final VirtualNetworkAdminService vnetAdminService = get(VirtualNetworkAdminService.class);
    private final VirtualNetworkService vnetService = get(VirtualNetworkService.class);

    @Context
    UriInfo uriInfo;

    // VirtualNetwork
    // TODO Query vnets by tenant

    /**
     * Returns all virtual networks.
     *
     * @return 200 OK
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getVirtualNetworks() {
        Set<TenantId> tenantIds = vnetAdminService.getTenantIds();
        List<VirtualNetwork> allVnets = tenantIds.stream()
                .map(tenantId -> vnetService.getVirtualNetworks(tenantId))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
        return ok(encodeArray(VirtualNetwork.class, "vnets", allVnets)).build();
    }

    /**
     * Creates a virtual network from the JSON input stream.
     *
     * @param stream TenantId JSON stream
     * @return status of the request - CREATED if the JSON is correct,
     * BAD_REQUEST if the JSON is invalid
     * @onos.rsModel TenantId
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createVirtualNetwork(InputStream stream) {
        try {
            final TenantId tid = TenantId.tenantId(getFromJsonStream(stream, "id").asText());
            VirtualNetwork newVnet = vnetAdminService.createVirtualNetwork(tid);
            UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
                    .path("vnets")
                    .path(newVnet.id().toString());
            return Response
                    .created(locationBuilder.build())
                    .build();
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Removes the virtual network with the specified network identifier.
     *
     * @param networkId network identifier
     * @return 200 OK, 404 not found
     */
    @DELETE
    @Path("{networkId}")
    public Response removeVirtualNetwork(@PathParam("networkId") long networkId) {
        final NetworkId nid = NetworkId.networkId(networkId);
        vnetAdminService.removeVirtualNetwork(nid);
        return Response.ok().build();
    }

    // VirtualDevice

    /**
     * Returns all virtual network devices in a virtual network.
     *
     * @param networkId network identifier
     * @return 200 OK
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{networkId}/devices")
    public Response getVirtualDevices(@PathParam("networkId") long networkId) {
        final NetworkId nid = NetworkId.networkId(networkId);
        Set<VirtualDevice> vdevs  = vnetService.getVirtualDevices(nid);
        return ok(encodeArray(VirtualDevice.class, "devices", vdevs)).build();
    }

    /**
     * Creates a virtual device from the JSON input stream.
     *
     * @param networkId network identifier
     * @param stream Virtual device JSON stream
     * @return status of the request - CREATED if the JSON is correct,
     * BAD_REQUEST if the JSON is invalid
     * @onos.rsModel VirtualDevice
     */
    @POST
    @Path("{networkId}/devices/")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createVirtualDevice(@PathParam("networkId") long networkId,
                                        InputStream stream) {
        try {
            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
            final VirtualDevice vdevReq = codec(VirtualDevice.class).decode(jsonTree, this);
            JsonNode specifiedRegionId = jsonTree.get("networkId");
            if (specifiedRegionId != null &&
                    specifiedRegionId.asLong() != (networkId)) {
                throw new IllegalArgumentException(INVALID_FIELD + "networkId");
            }
            final VirtualDevice vdevRes = vnetAdminService.createVirtualDevice(vdevReq.networkId(),
                                                                               vdevReq.id());
            UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
                    .path("vnets").path(specifiedRegionId.asText())
                    .path("devices").path(vdevRes.id().toString());
            return Response
                    .created(locationBuilder.build())
                    .build();
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Removes the virtual network device from the virtual network.
     *
     * @param networkId network identifier
     * @param deviceId device identifier
     * @return 200 OK, 404 not found
     */
    @DELETE
    @Path("{networkId}/devices/{deviceId}")
    public Response removeVirtualDevice(@PathParam("networkId") long networkId,
            @PathParam("deviceId") String deviceId) {
        final NetworkId nid = NetworkId.networkId(networkId);
        final DeviceId did = DeviceId.deviceId(deviceId);
        vnetAdminService.removeVirtualDevice(nid, did);
        return Response.ok().build();
    }

    // VirtualPort

    /**
     * Returns all virtual network ports in a virtual device in a virtual network.
     *
     * @param networkId network identifier
     * @param deviceId virtual device identifier
     * @return 200 OK
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{networkId}/devices/{deviceId}/ports")
    public Response getVirtualPorts(@PathParam("networkId") long networkId,
            @PathParam("deviceId") String deviceId) {
        final NetworkId nid = NetworkId.networkId(networkId);
        Iterable<VirtualPort> vports  = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId));
        return ok(encodeArray(VirtualPort.class, "ports", vports)).build();
    }

    /**
     * Creates a virtual network port in a virtual device in a virtual network.
     *
     * @param networkId network identifier
     * @param virtDeviceId virtual device identifier
     * @param stream Virtual device JSON stream
     * @return status of the request - CREATED if the JSON is correct,
     * BAD_REQUEST if the JSON is invalid
     * @onos.rsModel VirtualPort
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{networkId}/devices/{deviceId}/ports")
    public Response createVirtualPort(@PathParam("networkId") long networkId,
            @PathParam("deviceId") String virtDeviceId,
            InputStream stream) {
        try {
            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
//            final VirtualPort vportReq = codec(VirtualPort.class).decode(jsonTree, this);
            JsonNode specifiedNetworkId = jsonTree.get("networkId");
            JsonNode specifiedDeviceId = jsonTree.get("deviceId");
            if (specifiedNetworkId != null &&
                    specifiedNetworkId.asLong() != (networkId)) {
                throw new IllegalArgumentException(INVALID_FIELD + "networkId");
            }
            if (specifiedDeviceId != null &&
                    !specifiedDeviceId.asText().equals(virtDeviceId)) {
                throw new IllegalArgumentException(INVALID_FIELD + "deviceId");
            }
            JsonNode specifiedPortNum = jsonTree.get("portNum");
            JsonNode specifiedPhysDeviceId = jsonTree.get("physDeviceId");
            JsonNode specifiedPhysPortNum = jsonTree.get("physPortNum");
            final NetworkId nid = NetworkId.networkId(networkId);
            DeviceId vdevId = DeviceId.deviceId(virtDeviceId);
            DefaultAnnotations annotations = DefaultAnnotations.builder().build();
            Device physDevice = new DefaultDevice(null, DeviceId.deviceId(specifiedPhysDeviceId.asText()),
                    null, null, null, null, null, null, annotations);
            Port realizedBy = new DefaultPort(physDevice,
                    PortNumber.portNumber(specifiedPhysPortNum.asText()), true);
            VirtualPort vport = vnetAdminService.createVirtualPort(nid, vdevId,
                    PortNumber.portNumber(specifiedPortNum.asText()), realizedBy);
            UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
                    .path("vnets").path(specifiedNetworkId.asText())
                    .path("devices").path(specifiedDeviceId.asText())
                    .path("ports").path(vport.number().toString());
            return Response
                    .created(locationBuilder.build())
                    .build();
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Removes the virtual network port from the virtual device in a virtual network.
     *
     * @param networkId network identifier
     * @param deviceId virtual device identifier
     * @param portNum virtual port number
     * @return 200 OK, 404 not found
     */
    @DELETE
    @Path("{networkId}/devices/{deviceId}/ports/{portNum}")
    public Response removeVirtualPort(@PathParam("networkId") long networkId,
            @PathParam("deviceId") String deviceId,
            @PathParam("portNum") long portNum) {
        final NetworkId nid = NetworkId.networkId(networkId);
        vnetAdminService.removeVirtualPort(nid, DeviceId.deviceId(deviceId),
                PortNumber.portNumber(portNum));
        return Response.ok().build();
    }

    // TODO VirtualLink

    /**
     * Get the tenant identifier from the JSON stream.
     *
     * @param stream TenantId JSON stream
     * @param jsonFieldName field name
     * @return JsonNode
     * @throws IOException
     */
    private JsonNode getFromJsonStream(InputStream stream, String jsonFieldName) throws IOException {
        ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
        JsonNode jsonNode = jsonTree.get(jsonFieldName);

        if (jsonNode == null) {
            throw new IllegalArgumentException(MISSING_FIELD + jsonFieldName);
        }
        return jsonNode;
    }
}
