/*
 * Copyright 2016-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.pcerest;

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.util.Collection;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.LinkedList;

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 com.google.common.collect.ImmutableList;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.tunnel.TunnelService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.intent.Constraint;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.api.PceService;
import org.onosproject.pce.pceservice.PcePath;
import org.onosproject.pce.pceservice.DefaultPcePath;
import org.onosproject.pce.pceservice.LspType;
import org.onosproject.rest.AbstractWebResource;
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 pce path.
 */
@Path("path")
public class PcePathWebResource extends AbstractWebResource {

    private final Logger log = LoggerFactory.getLogger(PcePathWebResource.class);
    public static final String PCE_PATH_NOT_FOUND = "Path not found";
    public static final String PCE_PATH_ID_EXIST = "Path exists";
    public static final String PCE_PATH_ID_NOT_EXIST = "Path does not exist for the identifier";
    public static final String PCE_SETUP_PATH_FAILED = "PCE Setup path has failed.";

    /**
     * Retrieve details of all paths created.
     *
     * @return 200 OK
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response queryAllPath() {
        log.debug("Query all paths.");
        PceService pceService = get(PceService.class);
        Iterable<Tunnel> tunnels = pceService.queryAllPath();

        ObjectNode result = mapper().createObjectNode();
        ArrayNode pathEntry = result.putArray("paths");
        if (tunnels != null) {
            for (final Tunnel tunnel : tunnels) {
                PcePath path = DefaultPcePath.builder().of(tunnel, pceService.explicitPathInfoList(tunnel
                        .tunnelName().value()))
                        .build();
                pathEntry.add(codec(PcePath.class).encode(path, this));
            }
        }
        return ok(result.toString()).build();
    }

    /**
     * Retrieve details of a specified path id.
     *
     * @param id path id
     * @return 200 OK, 404 if given identifier does not exist
     */
    @GET
    @Path("{path_id}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response queryPath(@PathParam("path_id") String id) {
        log.debug("Query path by identifier {}.", id);
        PceService pceService = get(PceService.class);

        Tunnel tunnel = nullIsNotFound(pceService.queryPath(TunnelId.valueOf(id)),
                PCE_PATH_NOT_FOUND);
        PcePath path = DefaultPcePath.builder().of(tunnel, pceService.explicitPathInfoList(tunnel
                .tunnelName().value())).build();
        if (path == null) {
            return Response.status(OK).entity(PCE_SETUP_PATH_FAILED).build();
        }
        ObjectNode result = mapper().createObjectNode();
        result.set("path", codec(PcePath.class).encode(path, this));
        return ok(result.toString()).build();
    }

    /**
     * Creates a new path.
     *
     * @param stream pce path from json
     * @return status of the request
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response setupPath(InputStream stream) {
        log.debug("Setup path.");
        try {
            ObjectNode jsonTree = readTreeFromStream(mapper(), stream);
            JsonNode port = jsonTree.get("path");
            TunnelService tunnelService = get(TunnelService.class);
            PcePath path = codec(PcePath.class).decode((ObjectNode) port, this);
            if (path == null) {
                return Response.status(OK).entity(PCE_SETUP_PATH_FAILED).build();
            }

            //Validating tunnel name, duplicated tunnel names not allowed
            Collection<Tunnel> existingTunnels = tunnelService.queryTunnel(Tunnel.Type.MPLS);
            if (existingTunnels != null) {
                for (Tunnel t : existingTunnels) {
                    if (t.tunnelName().toString().equals(path.name())) {
                        return Response.status(OK).entity(PCE_SETUP_PATH_FAILED).build();
                    }
                }
            }

            DeviceId srcDevice = DeviceId.deviceId(path.source());
            DeviceId dstDevice = DeviceId.deviceId(path.destination());
            LspType lspType = path.lspType();
            List<Constraint> listConstrnt = new LinkedList<Constraint>();

            // Add bandwidth
            listConstrnt.add(path.bandwidthConstraint());

            // Add cost
            listConstrnt.add(path.costConstraint());

            List<ExplicitPathInfo> explicitPathInfoList = null;
            if (path.explicitPathInfo() != null) {
                explicitPathInfoList = ImmutableList.copyOf(path.explicitPathInfo());
            }

            Boolean issuccess = nullIsNotFound(get(PceService.class)
                                               .setupPath(srcDevice, dstDevice, path.name(), listConstrnt,
                                                       lspType, explicitPathInfoList),
                                               PCE_SETUP_PATH_FAILED);
            return Response.status(OK).entity(issuccess.toString()).build();
        } catch (IOException e) {
            log.error("Exception while creating path {}.", e.toString());
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Update details of a specified path id.
     *
     * @param id path id
     * @param stream pce path from json
     * @return 200 OK, 404 if given identifier does not exist
     */
    @PUT
    @Path("{path_id}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response updatePath(@PathParam("path_id") String id,
            final InputStream stream) {
        log.debug("Update path by identifier {}.", id);
        try {
            ObjectNode jsonTree = readTreeFromStream(mapper(), stream);
            JsonNode pathNode = jsonTree.get("path");
            PcePath path = codec(PcePath.class).decode((ObjectNode) pathNode, this);
            if (path == null) {
                return Response.status(OK).entity(PCE_SETUP_PATH_FAILED).build();
            }
            List<Constraint> constrntList = new LinkedList<Constraint>();
            // Assign bandwidth
            if (path.bandwidthConstraint() != null) {
                constrntList.add(path.bandwidthConstraint());
            }

            // Assign cost
            if (path.costConstraint() != null) {
                constrntList.add(path.costConstraint());
            }

            Boolean result = nullIsNotFound(get(PceService.class).updatePath(TunnelId.valueOf(id), constrntList),
                                            PCE_PATH_NOT_FOUND);
            return Response.status(OK).entity(result.toString()).build();
        } catch (IOException e) {
            log.error("Update path failed because of exception {}.", e.toString());
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Release a specified path.
     *
     * @param id path id
     * @return 200 OK, 404 if given identifier does not exist
     */
    @DELETE
    @Path("{path_id}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response releasePath(@PathParam("path_id") String id) {
        log.debug("Deletes path by identifier {}.", id);

        Boolean isSuccess = nullIsNotFound(get(PceService.class).releasePath(TunnelId.valueOf(id)),
                                           PCE_PATH_NOT_FOUND);
        if (!isSuccess) {
            log.debug("Path identifier {} does not exist", id);
        }

        return Response.status(OK).entity(isSuccess.toString()).build();
    }
}
