/*
 * 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.Maps;
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.DefaultRouter;
import org.onosproject.vtnrsc.FixedIp;
import org.onosproject.vtnrsc.Router;
import org.onosproject.vtnrsc.Router.Status;
import org.onosproject.vtnrsc.RouterGateway;
import org.onosproject.vtnrsc.RouterId;
import org.onosproject.vtnrsc.RouterInterface;
import org.onosproject.vtnrsc.SubnetId;
import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.TenantNetworkId;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.router.RouterService;
import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
import org.onosproject.vtnweb.web.RouterCodec;
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.ArrayList;
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 java.util.concurrent.ConcurrentMap;

import static com.google.common.base.Preconditions.checkArgument;
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;

@Path("routers")
public class RouterWebResource extends AbstractWebResource {
    private final Logger log = LoggerFactory.getLogger(RouterWebResource.class);
    public static final String CREATE_FAIL = "Router is failed to create!";
    public static final String UPDATE_FAIL = "Router is failed to update!";
    public static final String GET_FAIL = "Router is failed to get!";
    public static final String NOT_EXIST = "Router does not exist!";
    public static final String DELETE_SUCCESS = "Router delete success!";
    public static final String JSON_NOT_NULL = "JsonNode can not be null";
    public static final String INTFACR_ADD_SUCCESS = "Interface add success";
    public static final String INTFACR_DEL_SUCCESS = "Interface delete success";

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response listRouters() {
        Collection<Router> routers = get(RouterService.class).getRouters();
        ObjectNode result = new ObjectMapper().createObjectNode();
        result.set("routers", new RouterCodec().encode(routers, this));
        return ok(result.toString()).build();
    }

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

        if (!get(RouterService.class).exists(RouterId.valueOf(id))) {
            return Response.status(NOT_FOUND)
                    .entity("The Router does not exists").build();
        }
        Router sub = nullIsNotFound(get(RouterService.class)
                .getRouter(RouterId.valueOf(id)), NOT_EXIST);

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

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createRouter(final InputStream input) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode subnode = mapper.readTree(input);
            Collection<Router> routers = createOrUpdateByInputStream(subnode);

            Boolean result = nullIsNotFound((get(RouterService.class)
                    .createRouters(routers)), CREATE_FAIL);
            if (!result) {
                return Response.status(CONFLICT).entity(CREATE_FAIL).build();
            }
            return Response.status(CREATED).entity(result.toString()).build();

        } catch (IllegalArgumentException | IOException e) {
            return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
        }
    }

    @PUT
    @Path("{routerUUID}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response updateRouter(@PathParam("routerUUID") String id,
                                 final InputStream input) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode subnode = mapper.readTree(input);
            Collection<Router> routers = changeUpdateJsonToSub(subnode, id);
            Boolean result = nullIsNotFound(get(RouterService.class)
                    .updateRouters(routers), 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("{routerUUID}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response deleteSingleRouter(@PathParam("routerUUID") String id)
            throws IOException {
        try {
            RouterId routerId = RouterId.valueOf(id);
            Set<RouterId> routerIds = Sets.newHashSet(routerId);
            get(RouterService.class).removeRouters(routerIds);
            return Response.noContent().entity(DELETE_SUCCESS).build();
        } catch (Exception e) {
            return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
        }
    }

    @PUT
    @Path("{routerUUID}/add_router_interface")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response addRouterInterface(@PathParam("routerUUID") String id,
                                       final InputStream input) {
        if (!get(RouterService.class).exists(RouterId.valueOf(id))) {
            return Response.status(NOT_FOUND).entity(NOT_EXIST).build();
        }
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode subnode = mapper.readTree(input);
            if (!subnode.hasNonNull("id")) {
                throw new IllegalArgumentException("id should not be null");
            } else if (subnode.get("id").asText().isEmpty()) {
                throw new IllegalArgumentException("id should not be empty");
            }
            RouterId routerId = RouterId.valueOf(id);
            if (!subnode.hasNonNull("subnet_id")) {
                throw new IllegalArgumentException("subnet_id should not be null");
            } else if (subnode.get("subnet_id").asText().isEmpty()) {
                throw new IllegalArgumentException("subnet_id should not be empty");
            }
            SubnetId subnetId = SubnetId
                    .subnetId(subnode.get("subnet_id").asText());
            if (!subnode.hasNonNull("tenant_id")) {
                throw new IllegalArgumentException("tenant_id should not be null");
            } else if (subnode.get("tenant_id").asText().isEmpty()) {
                throw new IllegalArgumentException("tenant_id should not be empty");
            }
            TenantId tenentId = TenantId
                    .tenantId(subnode.get("tenant_id").asText());
            if (!subnode.hasNonNull("port_id")) {
                throw new IllegalArgumentException("port_id should not be null");
            } else if (subnode.get("port_id").asText().isEmpty()) {
                throw new IllegalArgumentException("port_id should not be empty");
            }
            VirtualPortId portId = VirtualPortId
                    .portId(subnode.get("port_id").asText());
            RouterInterface routerInterface = RouterInterface
                    .routerInterface(subnetId, portId, routerId, tenentId);
            get(RouterInterfaceService.class)
                    .addRouterInterface(routerInterface);
            return ok(INTFACR_ADD_SUCCESS).build();
        } catch (Exception e) {
            return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
        }
    }

    @PUT
    @Path("{routerUUID}/remove_router_interface")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response removeRouterInterface(@PathParam("routerUUID") String id,
                                          final InputStream input) {
        if (!get(RouterService.class).exists(RouterId.valueOf(id))) {
            return Response.status(NOT_FOUND).entity(NOT_EXIST).build();
        }
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode subnode = mapper.readTree(input);
            if (!subnode.hasNonNull("id")) {
                throw new IllegalArgumentException("id should not be null");
            } else if (subnode.get("id").asText().isEmpty()) {
                throw new IllegalArgumentException("id should not be empty");
            }
            RouterId routerId = RouterId.valueOf(id);
            if (!subnode.hasNonNull("subnet_id")) {
                throw new IllegalArgumentException("subnet_id should not be null");
            } else if (subnode.get("subnet_id").asText().isEmpty()) {
                throw new IllegalArgumentException("subnet_id should not be empty");
            }
            SubnetId subnetId = SubnetId
                    .subnetId(subnode.get("subnet_id").asText());
            if (!subnode.hasNonNull("port_id")) {
                throw new IllegalArgumentException("port_id should not be null");
            } else if (subnode.get("port_id").asText().isEmpty()) {
                throw new IllegalArgumentException("port_id should not be empty");
            }
            VirtualPortId portId = VirtualPortId
                    .portId(subnode.get("port_id").asText());
            if (!subnode.hasNonNull("tenant_id")) {
                throw new IllegalArgumentException("tenant_id should not be null");
            } else if (subnode.get("tenant_id").asText().isEmpty()) {
                throw new IllegalArgumentException("tenant_id should not be empty");
            }
            TenantId tenentId = TenantId
                    .tenantId(subnode.get("tenant_id").asText());
            RouterInterface routerInterface = RouterInterface
                    .routerInterface(subnetId, portId, routerId, tenentId);
            get(RouterInterfaceService.class)
                    .removeRouterInterface(routerInterface);
            return ok(INTFACR_DEL_SUCCESS).build();
        } catch (Exception e) {
            return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
        }
    }

    private Collection<Router> createOrUpdateByInputStream(JsonNode subnode) {
        checkNotNull(subnode, JSON_NOT_NULL);
        JsonNode routerNode = subnode.get("routers");
        if (routerNode == null) {
            routerNode = subnode.get("router");
        }
        log.debug("routerNode is {}", routerNode.toString());

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

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

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

        VirtualPortId gwPortId = null;
        if (routerNode.hasNonNull("gw_port_id")) {
            gwPortId = VirtualPortId
                    .portId(routerNode.get("gw_port_id").asText());
        }

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

        String routerName = null;
        if (routerNode.hasNonNull("name")) {
            routerName = routerNode.get("name").asText();
        }

        boolean adminStateUp = true;
        checkArgument(routerNode.get("admin_state_up").isBoolean(),
                      "admin_state_up should be boolean");
        if (routerNode.hasNonNull("admin_state_up")) {
            adminStateUp = routerNode.get("admin_state_up").asBoolean();
        }
        boolean distributed = false;
        if (routerNode.hasNonNull("distributed")) {
            distributed = routerNode.get("distributed").asBoolean();
        }
        RouterGateway gateway = null;
        if (routerNode.hasNonNull("external_gateway_info")) {
            gateway = jsonNodeToGateway(routerNode
                    .get("external_gateway_info"));
        }
        List<String> routes = new ArrayList<String>();
        DefaultRouter routerObj = new DefaultRouter(id, routerName,
                                                    adminStateUp, status,
                                                    distributed, gateway,
                                                    gwPortId, tenantId, routes);
        subMap.put(id, routerObj);
        return Collections.unmodifiableCollection(subMap.values());
    }

    /**
     * Returns a collection of floatingIps from floatingIpNodes.
     *
     * @param subnode the router json node
     * @param routerId the router identify
     * @return routers a collection of router
     */
    public Collection<Router> changeUpdateJsonToSub(JsonNode subnode,
                                                    String routerId) {
        checkNotNull(subnode, JSON_NOT_NULL);
        checkNotNull(routerId, "routerId should not be null");
        Map<RouterId, Router> subMap = new HashMap<RouterId, Router>();
        JsonNode routerNode = subnode.get("router");
        RouterId id = RouterId.valueOf(routerId);
        Router sub = nullIsNotFound(get(RouterService.class).getRouter(id),
                                    NOT_EXIST);
        TenantId tenantId = sub.tenantId();

        VirtualPortId gwPortId = null;
        if (routerNode.hasNonNull("gw_port_id")) {
            gwPortId = VirtualPortId
                    .portId(routerNode.get("gw_port_id").asText());
        }
        Status status = sub.status();

        String routerName = routerNode.get("name").asText();

        checkArgument(routerNode.get("admin_state_up").isBoolean(),
                      "admin_state_up should be boolean");
        boolean adminStateUp = routerNode.get("admin_state_up").asBoolean();

        boolean distributed = sub.distributed();
        if (routerNode.hasNonNull("distributed")) {
            distributed = routerNode.get("distributed").asBoolean();
        }
        RouterGateway gateway = sub.externalGatewayInfo();
        if (routerNode.hasNonNull("external_gateway_info")) {
            gateway = jsonNodeToGateway(routerNode
                    .get("external_gateway_info"));
        }
        List<String> routes = new ArrayList<String>();
        DefaultRouter routerObj = new DefaultRouter(id, routerName,
                                                    adminStateUp, status,
                                                    distributed, gateway,
                                                    gwPortId, tenantId, routes);
        subMap.put(id, routerObj);
        return Collections.unmodifiableCollection(subMap.values());
    }

    /**
     * Changes JsonNode Gateway to the Gateway.
     *
     * @param gateway the gateway JsonNode
     * @return gateway
     */
    private RouterGateway jsonNodeToGateway(JsonNode gateway) {
        checkNotNull(gateway, JSON_NOT_NULL);
        if (!gateway.hasNonNull("network_id")) {
            throw new IllegalArgumentException("network_id should not be null");
        } else if (gateway.get("network_id").asText().isEmpty()) {
            throw new IllegalArgumentException("network_id should not be empty");
        }
        TenantNetworkId networkId = TenantNetworkId
                .networkId(gateway.get("network_id").asText());

        if (!gateway.hasNonNull("enable_snat")) {
            throw new IllegalArgumentException("enable_snat should not be null");
        } else if (gateway.get("enable_snat").asText().isEmpty()) {
            throw new IllegalArgumentException("enable_snat should not be empty");
        }
        checkArgument(gateway.get("enable_snat").isBoolean(),
                      "enable_snat should be boolean");
        boolean enableSnat = gateway.get("enable_snat").asBoolean();

        if (!gateway.hasNonNull("external_fixed_ips")) {
            throw new IllegalArgumentException("external_fixed_ips should not be null");
        } else if (gateway.get("external_fixed_ips").isNull()) {
            throw new IllegalArgumentException("external_fixed_ips should not be empty");
        }
        Iterable<FixedIp> fixedIpList = jsonNodeToFixedIp(gateway
                .get("external_fixed_ips"));
        RouterGateway gatewayObj = RouterGateway
                .routerGateway(networkId, enableSnat, Sets.newHashSet(fixedIpList));
        return gatewayObj;
    }

    /**
     * Changes JsonNode fixedIp to a collection of the fixedIp.
     *
     * @param fixedIp the allocationPools JsonNode
     * @return a collection of fixedIp
     */
    private Iterable<FixedIp> jsonNodeToFixedIp(JsonNode fixedIp) {
        checkNotNull(fixedIp, JSON_NOT_NULL);
        ConcurrentMap<Integer, FixedIp> fixedIpMaps = Maps.newConcurrentMap();
        Integer i = 0;
        for (JsonNode node : fixedIp) {
            if (!node.hasNonNull("subnet_id")) {
                throw new IllegalArgumentException("subnet_id should not be null");
            } else if (node.get("subnet_id").asText().isEmpty()) {
                throw new IllegalArgumentException("subnet_id should not be empty");
            }
            SubnetId subnetId = SubnetId
                    .subnetId(node.get("subnet_id").asText());
            if (!node.hasNonNull("ip_address")) {
                throw new IllegalArgumentException("ip_address should not be null");
            } else if (node.get("ip_address").asText().isEmpty()) {
                throw new IllegalArgumentException("ip_address should not be empty");
            }
            IpAddress ipAddress = IpAddress
                    .valueOf(node.get("ip_address").asText());
            FixedIp fixedIpObj = FixedIp.fixedIp(subnetId, ipAddress);

            fixedIpMaps.putIfAbsent(i, fixedIpObj);
            i++;
        }
        return Collections.unmodifiableCollection(fixedIpMaps.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;
    }
}
