/*
 * 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.segmentrouting.web;

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 javafx.util.Pair;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.segmentrouting.SegmentRoutingService;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
import org.onosproject.segmentrouting.pwaas.L2Tunnel;
import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static org.onlab.util.Tools.nullIsIllegal;
import static org.onlab.util.Tools.readTreeFromStream;

/**
 * Query, create and remove pseudowires.
 */
@Path("pseudowire")
public class PseudowireWebResource extends AbstractWebResource {

    private static final PseudowireCodec PSEUDOWIRE_CODEC = new PseudowireCodec();
    public static final String PWS = "pseudowires";
    private static final String PWS_KEY_ERROR = "Pseudowires key must be present.";

    private static Logger log = LoggerFactory
            .getLogger(PseudowireWebResource.class);

    /**
     * Get all pseudowires.
     * Returns an array of pseudowires.
     *
     * @return status of OK
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getPseudowire() {
        SegmentRoutingService srService = get(SegmentRoutingService.class);

        log.debug("Fetching pseudowires form rest api!");

        List<L2TunnelPolicy> policies = srService.getL2Policies();
        List<L2Tunnel> tunnels = srService.getL2Tunnels();
        List<DefaultL2TunnelDescription> pseudowires = tunnels.stream()
                .map(l2Tunnel -> {
                    L2TunnelPolicy policy = null;
                    for (L2TunnelPolicy l2Policy : policies) {
                        if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
                            policy = l2Policy;
                            break;
                        }
                    }

                    // return a copy
                    return new DefaultL2TunnelDescription(l2Tunnel, policy);
                })
                .collect(Collectors.toList());

        ObjectNode result = new ObjectMapper().createObjectNode();
        result.set("pseudowires", new PseudowireCodec().encode(pseudowires, this));

        return ok(result.toString()).build();
    }

    /**
     * Create a new pseudowire.
     *
     * @param input JSON stream for pseudowire to create
     * @return Response with appropriate status
     * @throws IOException Throws IO exception.
     * @onos.rsModel PseudowireCreate
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createPseudowire(InputStream input) throws IOException {

        ObjectMapper mapper = new ObjectMapper();
        ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
        SegmentRoutingService srService = get(SegmentRoutingService.class);

        DefaultL2TunnelDescription pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this);
        if (pseudowire == null) {
            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
        }

        long tunId = pseudowire.l2Tunnel().tunnelId();
        log.debug("Creating pseudowire {} from rest api!", tunId);

        L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
        switch (res) {
            case WRONG_PARAMETERS:
            case CONFIGURATION_ERROR:
            case PATH_NOT_FOUND:
            case INTERNAL_ERROR:
                log.error("Pseudowire {} could not be added : {}", tunId, res.getSpecificError());
                return Response.serverError().status(Response.Status.INTERNAL_SERVER_ERROR).build();
            case SUCCESS:
                log.info("Pseudowire {} succesfully deployed!", pseudowire.l2Tunnel().tunnelId());
                return Response.ok().build();
            default:
                return Response.ok().build();
        }
    }

    /**
     * Create a bulk of pseudowires.
     *
     * @param input JSON stream for pseudowires to create
     * @return Response with appropriate status
     * @throws IOException Throws IO exception.
     * @onos.rsModel PseudowireCreateBulk
     */
    @POST
    @Path("/bulk")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createPseudowiresBulk(InputStream input) throws IOException {

        ObjectMapper mapper = new ObjectMapper();
        ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
        SegmentRoutingService srService = get(SegmentRoutingService.class);
        List<DefaultL2TunnelDescription> pseudowires;

        try {
            ArrayNode pseudowiresArray = nullIsIllegal((ArrayNode) pseudowireJson.get(PWS), PWS_KEY_ERROR);
            pseudowires = PSEUDOWIRE_CODEC.decode(pseudowiresArray, this);
        } catch (ItemNotFoundException e) {
            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
        }

        log.debug("Creating pseudowires {} from rest api!", pseudowires);
        List<Pair<DefaultL2TunnelDescription, String>> failed = new ArrayList<>();

        for (DefaultL2TunnelDescription pw : pseudowires) {
            L2TunnelHandler.Result res = srService.addPseudowire(pw);
            if (!(res == L2TunnelHandler.Result.SUCCESS)) {
                log.trace("Could not create pseudowire {} : {}", pw.l2Tunnel().tunnelId(), res.getSpecificError());
                failed.add(new Pair<>(pw, res.getSpecificError()));
            }
        }

        if (failed.size() == 0) {
            // all pseudowires were instantiated
            return Response.ok().build();
        } else {
            PseudowireCodec pwCodec = new PseudowireCodec();
            // some failed, need to report them to user
            ObjectNode result = pwCodec.encodeFailedPseudowires(failed, this);
            return Response.serverError().entity(result).build();
        }
    }

    /**
     * Delete a pseudowire.
     *
     * @param input JSON stream for pseudowire to delete
     * @return Response with appropriate status
     * @throws IOException Throws IO exception.
     * @onos.rsModel PseudowireDelete
     */
    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
    public Response removePseudowire(InputStream input) throws IOException {

        ObjectMapper mapper = new ObjectMapper();
        ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
        SegmentRoutingService srService = get(SegmentRoutingService.class);

        Integer pseudowireId = PSEUDOWIRE_CODEC.decodeId(pseudowireJson);
        if (pseudowireId == null) {
            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
        }

        log.debug("Deleting pseudowire {} from rest api!", pseudowireId);

        L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
        switch (res) {
            case WRONG_PARAMETERS:
            case INTERNAL_ERROR:
                log.error("Pseudowire {} could not be removed : {}",
                          pseudowireId, res.getSpecificError());
                return Response.noContent().build();
            case SUCCESS:
                log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
                return Response.noContent().build();
            default:
                return Response.noContent().build();
        }
    }

    /**
     * Delete a bulk of pseudowires.
     *
     * @param input JSON stream for pseudowires to delete
     * @return Response with appropriate status
     * @throws IOException Throws IO exception.
     * @onos.rsModel PseudowireDeleteBulk
     */
    @DELETE
    @Path("/bulk")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response removePseudowiresBulk(InputStream input) throws IOException {

        ObjectMapper mapper = new ObjectMapper();
        ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
        SegmentRoutingService srService = get(SegmentRoutingService.class);

        List<Integer> ids = new ArrayList<>();

        // try to parse all ids, if key is not present, or if an id is not an int
        // throw an exception and stop process
        try {
            for (JsonNode node : pseudowireJson.withArray(PWS)) {
                Integer idToDelete = PseudowireCodec.decodeId((ObjectNode) node);
                if (idToDelete == null) {
                    log.error("Error when parsing pseudowire for deletion in REST API.");
                    throw new IllegalArgumentException("Id of pseudowire should be an integer!");
                }
                ids.add(idToDelete);
            }
        } catch (IllegalArgumentException e) {
            log.error("Pseudowire ID should be an integer.");
            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
        } catch (UnsupportedOperationException e) {
            log.error("Pseudowires for deletion should be an array of pseudowire ids.");
            return Response.serverError().status(Response.Status.BAD_REQUEST).build();
        }

        for (Integer pseudowireId : ids) {
            L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
            switch (res) {
                case WRONG_PARAMETERS:
                case INTERNAL_ERROR:
                    log.error("Pseudowire {} could not be removed, internal error : {}",
                              pseudowireId, res.getSpecificError());
                    break;
                case SUCCESS:
                    log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
                    break;
                default:
            }
        }

        return Response.noContent().build();
    }
}
