/*
 * 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 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 = (ObjectNode) mapper().readTree(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 = (ObjectNode) mapper().readTree(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();
    }
}
