/*
 * Copyright 2015-present Open Networking Foundation
 *
 * 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.vtnweb.resources;

import static javax.ws.rs.core.Response.Status.OK;
import static org.onlab.util.Tools.nullIsNotFound;
import static org.onlab.util.Tools.readTreeFromStream;

import java.io.IOException;
import java.io.InputStream;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
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 org.onosproject.rest.AbstractWebResource;
import org.onosproject.vtnrsc.PortPair;
import org.onosproject.vtnrsc.PortPairId;
import org.onosproject.vtnrsc.portpair.PortPairService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * Query and program port pair.
 */
@Path("port_pairs")
public class PortPairWebResource extends AbstractWebResource {

    private final Logger log = LoggerFactory.getLogger(PortPairWebResource.class);
    public static final String PORT_PAIR_NOT_FOUND = "Port pair not found";
    public static final String PORT_PAIR_ID_EXIST = "Port pair exists";
    public static final String PORT_PAIR_ID_NOT_EXIST = "Port pair does not exist with identifier";

    /**
     * Get details of all port pairs created.
     *
     * @return 200 OK
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response getPortPairs() {
        Iterable<PortPair> portPairs = get(PortPairService.class).getPortPairs();
        ObjectNode result = mapper().createObjectNode();
        ArrayNode portPairEntry = result.putArray("port_pairs");
        if (portPairs != null) {
            for (final PortPair portPair : portPairs) {
                portPairEntry.add(codec(PortPair.class).encode(portPair, this));
            }
        }
        return ok(result.toString()).build();
    }

    /**
     * Get details of a specified port pair id.
     *
     * @param id port pair id
     * @return 200 OK, 404 if given identifier does not exist
     */
    @GET
    @Path("{pair_id}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response getPortPair(@PathParam("pair_id") String id) {
        PortPair portPair = nullIsNotFound(get(PortPairService.class).getPortPair(PortPairId.of(id)),
                                           PORT_PAIR_NOT_FOUND);
        ObjectNode result = mapper().createObjectNode();
        result.set("port_pair", codec(PortPair.class).encode(portPair, this));
        return ok(result.toString()).build();
    }

    /**
     * Creates a new port pair.
     *
     * @param stream port pair from JSON
     * @return status of the request - CREATED if the JSON is correct,
     * BAD_REQUEST if the JSON is invalid
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createPortPair(InputStream stream) {
        try {
            ObjectNode jsonTree = readTreeFromStream(mapper(), stream);
            JsonNode port = jsonTree.get("port_pair");
            PortPair portPair = codec(PortPair.class).decode((ObjectNode) port, this);
            Boolean isSuccess = nullIsNotFound(get(PortPairService.class).createPortPair(portPair),
                                               PORT_PAIR_NOT_FOUND);
            return Response.status(OK).entity(isSuccess.toString()).build();
        } catch (IOException e) {
            log.error("Exception while creating port pair {}.", e.toString());
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Update details of a specified port pair id.
     *
     * @param id port pair id
     * @param stream port pair from json
     * @return 200 OK, 404 if the given identifier does not exist
     */
    @PUT
    @Path("{pair_id}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response updatePortPair(@PathParam("pair_id") String id,
                                   final InputStream stream) {
        try {
            ObjectNode jsonTree = readTreeFromStream(mapper(), stream);
            JsonNode port = jsonTree.get("port_pair");
            PortPair portPair = codec(PortPair.class).decode((ObjectNode) port, this);
            Boolean isSuccess = nullIsNotFound(get(PortPairService.class).updatePortPair(portPair),
                                               PORT_PAIR_NOT_FOUND);
            return Response.status(OK).entity(isSuccess.toString()).build();
        } catch (IOException e) {
            log.error("Update port pair failed because of exception {}.", e.toString());
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Delete details of a specified port pair id.
     *
     * @param id port pair id
     * @return 204 NO CONTENT
     */
    @Path("{pair_id}")
    @DELETE
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response deletePortPair(@PathParam("pair_id") String id) {

        PortPairId portPairId = PortPairId.of(id);
        Boolean isSuccess = nullIsNotFound(get(PortPairService.class).removePortPair(portPairId), PORT_PAIR_NOT_FOUND);
        if (!isSuccess) {
            log.debug("Port pair identifier {} does not exist", id);
        }
        return Response.noContent().build();
    }
}
