/*
 * 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 com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Sets;
import org.onlab.packet.IpAddress;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.vtnrsc.DefaultFloatingIp;
import org.onosproject.vtnrsc.FloatingIp;
import org.onosproject.vtnrsc.FloatingIp.Status;
import org.onosproject.vtnrsc.FloatingIpId;
import org.onosproject.vtnrsc.RouterId;
import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.TenantNetworkId;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.floatingip.FloatingIpService;
import org.onosproject.vtnweb.web.FloatingIpCodec;
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.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static javax.ws.rs.core.Response.Status.CONFLICT;
import static javax.ws.rs.core.Response.Status.CREATED;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
import static org.onlab.util.Tools.readTreeFromStream;

@Path("floatingips")
public class FloatingIpWebResource extends AbstractWebResource {
    private final Logger log = LoggerFactory
            .getLogger(FloatingIpWebResource.class);
    public static final String CREATE_FAIL = "Floating IP is failed to create!";
    public static final String UPDATE_FAIL = "Floating IP is failed to update!";
    public static final String DELETE_FAIL = "Floating IP is failed to delete!";
    public static final String GET_FAIL = "Floating IP is failed to get!";
    public static final String NOT_EXIST = "Floating IP does not exist!";
    public static final String DELETE_SUCCESS = "Floating IP delete success!";
    public static final String JSON_NOT_NULL = "JsonNode can not be null";

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response listFloatingIps() {
        Collection<FloatingIp> floatingIps = get(FloatingIpService.class)
                .getFloatingIps();
        ObjectNode result = new ObjectMapper().createObjectNode();
        result.set("floatingips",
                   new FloatingIpCodec().encode(floatingIps, this));
        return ok(result.toString()).build();
    }

    @GET
    @Path("{floatingIpUUID}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response getFloatingIp(@PathParam("floatingIpUUID") String id,
                                  @QueryParam("fields") List<String> fields) {

        if (!get(FloatingIpService.class).exists(FloatingIpId.of(id))) {
            return Response.status(NOT_FOUND).entity(NOT_EXIST).build();
        }
        FloatingIp sub = nullIsNotFound(get(FloatingIpService.class)
                .getFloatingIp(FloatingIpId.of(id)), GET_FAIL);

        ObjectNode result = new ObjectMapper().createObjectNode();
        if (!fields.isEmpty()) {
            result.set("floatingip",
                       new FloatingIpCodec().extracFields(sub, this, fields));
        } else {
            result.set("floatingip", new FloatingIpCodec().encode(sub, this));
        }
        return ok(result.toString()).build();
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createFloatingIp(final InputStream input) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode subnode = readTreeFromStream(mapper, input);
            Collection<FloatingIp> floatingIps = createOrUpdateByInputStream(subnode);
            Boolean result = nullIsNotFound((get(FloatingIpService.class)
                                                    .createFloatingIps(floatingIps)),
                                            CREATE_FAIL);
            if (!result) {
                return Response.status(CONFLICT).entity(CREATE_FAIL).build();
            }
            return Response.status(CREATED).entity(result.toString()).build();

        } catch (Exception e) {
            return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
        }
    }

    @PUT
    @Path("{floatingIpUUID}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response updateFloatingIp(@PathParam("floatingIpUUID") String id,
                                     final InputStream input) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode subnode = readTreeFromStream(mapper, input);
            Collection<FloatingIp> floatingIps = createOrUpdateByInputStream(subnode);
            Boolean result = nullIsNotFound(get(FloatingIpService.class)
                    .updateFloatingIps(floatingIps), UPDATE_FAIL);
            if (!result) {
                return Response.status(CONFLICT).entity(UPDATE_FAIL).build();
            }
            return ok(result.toString()).build();
        } catch (Exception e) {
            return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
        }
    }

    @DELETE
    @Path("{floatingIpUUID}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response deleteSingleFloatingIp(@PathParam("floatingIpUUID") String id)
            throws IOException {
        try {
            FloatingIpId floatingIpId = FloatingIpId.of(id);
            Set<FloatingIpId> floatingIpIds = Sets.newHashSet(floatingIpId);
            Boolean result = nullIsNotFound(get(FloatingIpService.class)
                    .removeFloatingIps(floatingIpIds), DELETE_FAIL);
            if (!result) {
                return Response.status(CONFLICT).entity(DELETE_FAIL).build();
            }
            return Response.noContent().entity(DELETE_SUCCESS).build();
        } catch (Exception e) {
            return Response.status(NOT_FOUND).entity(e.getMessage()).build();
        }
    }

    private Collection<FloatingIp> createOrUpdateByInputStream(JsonNode subnode) {
        checkNotNull(subnode, JSON_NOT_NULL);
        Collection<FloatingIp> floatingIps = null;
        JsonNode floatingIpNodes = subnode.get("floatingips");
        if (floatingIpNodes == null) {
            floatingIpNodes = subnode.get("floatingip");
        }
        log.debug("floatingNodes is {}", floatingIpNodes.toString());

        if (floatingIpNodes.isArray()) {
            throw new IllegalArgumentException("only singleton requests allowed");
        } else {
            floatingIps = changeJsonToSub(floatingIpNodes);
        }
        return floatingIps;
    }

    /**
     * Returns a collection of floatingIps from floatingIpNodes.
     *
     * @param floatingIpNodes the floatingIp json node
     * @return floatingIps a collection of floatingIp
     */
    public Collection<FloatingIp> changeJsonToSub(JsonNode floatingIpNodes) {
        checkNotNull(floatingIpNodes, JSON_NOT_NULL);
        Map<FloatingIpId, FloatingIp> subMap = new HashMap<FloatingIpId, FloatingIp>();
        if (!floatingIpNodes.hasNonNull("id")) {
            throw new IllegalArgumentException("id should not be null");
        } else if (floatingIpNodes.get("id").asText().isEmpty()) {
            throw new IllegalArgumentException("id should not be empty");
        }
        FloatingIpId id = FloatingIpId.of(floatingIpNodes.get("id")
                .asText());

        if (!floatingIpNodes.hasNonNull("tenant_id")) {
            throw new IllegalArgumentException("tenant_id should not be null");
        } else if (floatingIpNodes.get("tenant_id").asText().isEmpty()) {
            throw new IllegalArgumentException("tenant_id should not be empty");
        }
        TenantId tenantId = TenantId.tenantId(floatingIpNodes.get("tenant_id")
                .asText());

        if (!floatingIpNodes.hasNonNull("floating_network_id")) {
            throw new IllegalArgumentException(
                                          "floating_network_id should not be null");
        } else if (floatingIpNodes.get("floating_network_id").asText()
                .isEmpty()) {
            throw new IllegalArgumentException(
                                          "floating_network_id should not be empty");
        }
        TenantNetworkId networkId = TenantNetworkId.networkId(floatingIpNodes
                .get("floating_network_id").asText());

        VirtualPortId portId = null;
        if (floatingIpNodes.hasNonNull("port_id")) {
            portId = VirtualPortId.portId(floatingIpNodes.get("port_id")
                    .asText());
        }

        RouterId routerId = null;
        if (floatingIpNodes.hasNonNull("router_id")) {
            routerId = RouterId.valueOf(floatingIpNodes.get("router_id")
                    .asText());
        }

        IpAddress fixedIp = null;
        if (floatingIpNodes.hasNonNull("fixed_ip_address")) {
            fixedIp = IpAddress.valueOf(floatingIpNodes.get("fixed_ip_address")
                    .asText());
        }

        if (!floatingIpNodes.hasNonNull("floating_ip_address")) {
            throw new IllegalArgumentException(
                                          "floating_ip_address should not be null");
        } else if (floatingIpNodes.get("floating_ip_address").asText()
                .isEmpty()) {
            throw new IllegalArgumentException(
                                          "floating_ip_address should not be empty");
        }
        IpAddress floatingIp = IpAddress.valueOf(floatingIpNodes
                .get("floating_ip_address").asText());

        if (!floatingIpNodes.hasNonNull("status")) {
            throw new IllegalArgumentException("status should not be null");
        } else if (floatingIpNodes.get("status").asText().isEmpty()) {
            throw new IllegalArgumentException("status should not be empty");
        }
        Status status = Status.valueOf(floatingIpNodes.get("status").asText());

        DefaultFloatingIp floatingIpObj = new DefaultFloatingIp(id, tenantId,
                                                                networkId,
                                                                portId,
                                                                routerId,
                                                                floatingIp,
                                                                fixedIp, status);
        subMap.put(id, floatingIpObj);
        return Collections.unmodifiableCollection(subMap.values());
    }

    /**
     * Returns the specified item if that items is null; otherwise throws not
     * found exception.
     *
     * @param item item to check
     * @param <T> item type
     * @param message not found message
     * @return item if not null
     * @throws org.onlab.util.ItemNotFoundException if item is null
     */
    protected <T> T nullIsNotFound(T item, String message) {
        if (item == null) {
            throw new ItemNotFoundException(message);
        }
        return item;
    }
}
