/*
 * Copyright 2015 Open Networking Laboratory
 *
 * 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 static com.google.common.base.Preconditions.checkNotNull;
import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

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 org.onlab.packet.IpAddress;
import org.onlab.packet.IpAddress.Version;
import org.onlab.packet.IpPrefix;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.vtnrsc.AllocationPool;
import org.onosproject.vtnrsc.DefaultAllocationPool;
import org.onosproject.vtnrsc.DefaultHostRoute;
import org.onosproject.vtnrsc.DefaultSubnet;
import org.onosproject.vtnrsc.HostRoute;
import org.onosproject.vtnrsc.Subnet;
import org.onosproject.vtnrsc.SubnetId;
import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.TenantNetworkId;
import org.onosproject.vtnrsc.Subnet.Mode;
import org.onosproject.vtnrsc.subnet.SubnetService;
import org.onosproject.vtnrsc.web.SubnetCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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;

@Path("subnets")
public class SubnetWebResource extends AbstractWebResource {
    private final Logger log = LoggerFactory.getLogger(SubnetWebResource.class);
    public static final String SUBNET_NOT_CREATE = "Subnets is failed to create!";
    public static final String SUBNET_NOT_FOUND = "Subnets is failed to update!";
    public static final String JSON_NOT_NULL = "JsonNode can not be null";

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response listSubnets() {
        Iterable<Subnet> subnets = get(SubnetService.class).getSubnets();
        ObjectNode result = new ObjectMapper().createObjectNode();
        result.set("subnets", new SubnetCodec().encode(subnets, this));
        return ok(result.toString()).build();
    }

    @GET
    @Path("{subnetUUID}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getSubnet(@PathParam("subnetUUID") String id) {

        if (!get(SubnetService.class).exists(SubnetId.subnetId(id))) {
            return ok("The subnet does not exists").build();
        }
        Subnet sub = nullIsNotFound(get(SubnetService.class)
                                            .getSubnet(SubnetId.subnetId(id)),
                                    SUBNET_NOT_FOUND);

        ObjectNode result = new ObjectMapper().createObjectNode();
        result.set("subnet", new SubnetCodec().encode(sub, this));
        return ok(result.toString()).build();
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createSubnet(final InputStream input) {

        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode subnode = mapper.readTree(input);
            Iterable<Subnet> subnets = createOrUpdateByInputStream(subnode);
            Boolean result = nullIsNotFound((get(SubnetService.class)
                                                    .createSubnets(subnets)),
                                            SUBNET_NOT_CREATE);

            if (!result) {
                return Response.status(204).entity(SUBNET_NOT_CREATE).build();
            }
            return Response.status(202).entity(result.toString()).build();
        } catch (Exception e) {
            return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
                    .build();
        }
    }

    @PUT
    @Path("{subnetUUID}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response updateSubnet(@PathParam("id") String id,
                                 final InputStream input) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode subnode = mapper.readTree(input);
            Iterable<Subnet> subnets = createOrUpdateByInputStream(subnode);
            Boolean result = nullIsNotFound(get(SubnetService.class)
                    .updateSubnets(subnets), SUBNET_NOT_FOUND);
            if (!result) {
                return Response.status(204).entity(SUBNET_NOT_FOUND).build();
            }
            return Response.status(203).entity(result.toString()).build();
        } catch (Exception e) {
            return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
                    .build();
        }
    }

    @Path("{subnetUUID}")
    @DELETE
    public Response deleteSingleSubnet(@PathParam("subnetUUID") String id)
            throws IOException {
        try {
            SubnetId subId = SubnetId.subnetId(id);
            Set<SubnetId> subIds = new HashSet<SubnetId>();
            subIds.add(subId);
            get(SubnetService.class).removeSubnets(subIds);
            return Response.status(201).entity("SUCCESS").build();
        } catch (Exception e) {
            return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString())
                    .build();
        }
    }

    private Iterable<Subnet> createOrUpdateByInputStream(JsonNode subnode) {
        checkNotNull(subnode, JSON_NOT_NULL);
        Iterable<Subnet> subnets = null;
        JsonNode subnetNodes = subnode.get("subnets");
        if (subnetNodes == null) {
            subnetNodes = subnode.get("subnet");
        }
        log.debug("subnetNodes is {}", subnetNodes.toString());
        if (subnetNodes.isArray()) {
            subnets = changeJsonToSubs(subnetNodes);
        } else {
            subnets = changeJsonToSub(subnetNodes);
        }
        return subnets;
    }

    /**
     * Returns a collection of subnets from subnetNodes.
     *
     * @param subnetNodes the subnet json node
     * @return subnets a collection of subnets
     */
    public Iterable<Subnet> changeJsonToSubs(JsonNode subnetNodes) {
        checkNotNull(subnetNodes, JSON_NOT_NULL);
        Map<SubnetId, Subnet> subMap = new HashMap<SubnetId, Subnet>();
        for (JsonNode subnetNode : subnetNodes) {
            if (!subnetNode.hasNonNull("id")) {
                return null;
            }
            SubnetId id = SubnetId.subnetId(subnetNode.get("id").asText());
            String subnetName = subnetNode.get("name").asText();
            TenantId tenantId = TenantId
                    .tenantId(subnetNode.get("tenant_id").asText());
            TenantNetworkId networkId = TenantNetworkId
                    .networkId(subnetNode.get("network_id").asText());
            Version ipVersion = Version
                    .valueOf(subnetNode.get("ip_version").asText());
            IpPrefix cidr = IpPrefix.valueOf(subnetNode.get("cidr").asText());
            IpAddress gatewayIp = IpAddress
                    .valueOf(subnetNode.get("gateway_ip").asText());
            Boolean dhcpEnabled = subnetNode.get("enable_dhcp").asBoolean();
            Boolean shared = subnetNode.get("shared").asBoolean();
            JsonNode hostRoutes = subnetNode.get("host_routes");
            Iterable<HostRoute> hostRoutesIt = jsonNodeToHostRoutes(hostRoutes);
            JsonNode allocationPools = subnetNode.get("allocation_pools");
            Iterable<AllocationPool> allocationPoolsIt = jsonNodeToAllocationPools(allocationPools);
            Mode ipV6AddressMode = Mode
                    .valueOf(subnetNode.get("ipv6_address_mode").asText());
            Mode ipV6RaMode = Mode
                    .valueOf(subnetNode.get("ipv6_ra_mode").asText());
            Subnet subnet = new DefaultSubnet(id, subnetName, networkId,
                                              tenantId, ipVersion, cidr,
                                              gatewayIp, dhcpEnabled, shared,
                                              hostRoutesIt, ipV6AddressMode,
                                              ipV6RaMode, allocationPoolsIt);
            subMap.put(id, subnet);
        }
        return Collections.unmodifiableCollection(subMap.values());
    }

    /**
     * Returns a collection of subnets from subnetNodes.
     *
     * @param subnetNodes the subnet json node
     * @return subnets a collection of subnets
     */
    public Iterable<Subnet> changeJsonToSub(JsonNode subnetNodes) {
        checkNotNull(subnetNodes, JSON_NOT_NULL);
        Map<SubnetId, Subnet> subMap = new HashMap<SubnetId, Subnet>();
        if (!subnetNodes.hasNonNull("id")) {
            return null;
        }
        SubnetId id = SubnetId.subnetId(subnetNodes.get("id").asText());
        String subnetName = subnetNodes.get("name").asText();
        TenantId tenantId = TenantId
                .tenantId(subnetNodes.get("tenant_id").asText());
        TenantNetworkId networkId = TenantNetworkId
                .networkId(subnetNodes.get("network_id").asText());
        String version = subnetNodes.get("ip_version").asText();
        Version ipVersion;
        switch (version) {
        case "4":
            ipVersion = Version.INET;
            break;
        case "6":
            ipVersion = Version.INET;
            break;
        default:
            ipVersion = null;
        }

        IpPrefix cidr = IpPrefix.valueOf(subnetNodes.get("cidr").asText());
        IpAddress gatewayIp = IpAddress
                .valueOf(subnetNodes.get("gateway_ip").asText());
        Boolean dhcpEnabled = subnetNodes.get("enable_dhcp").asBoolean();
        Boolean shared = subnetNodes.get("shared").asBoolean();
        JsonNode hostRoutes = subnetNodes.get("host_routes");
        Iterable<HostRoute> hostRoutesIt = jsonNodeToHostRoutes(hostRoutes);
        JsonNode allocationPools = subnetNodes.get("allocation_pools");
        Iterable<AllocationPool> allocationPoolsIt = jsonNodeToAllocationPools(allocationPools);

        Mode ipV6AddressMode = getMode(subnetNodes.get("ipv6_address_mode")
                .asText());
        Mode ipV6RaMode = getMode(subnetNodes.get("ipv6_ra_mode").asText());

        Subnet subnet = new DefaultSubnet(id, subnetName, networkId, tenantId,
                                          ipVersion, cidr, gatewayIp,
                                          dhcpEnabled, shared, hostRoutesIt,
                                          ipV6AddressMode, ipV6RaMode,
                                          allocationPoolsIt);
        subMap.put(id, subnet);
        return Collections.unmodifiableCollection(subMap.values());
    }

    /**
     * Gets ipv6_address_mode or ipv6_ra_mode type.
     *
     * @param mode the String value in JsonNode
     * @return ipV6Mode Mode of the ipV6Mode
     */
    private Mode getMode(String mode) {
        Mode ipV6Mode;
        if (mode == null) {
            return null;
        }
        switch (mode) {
        case "dhcpv6-stateful":
            ipV6Mode = Mode.DHCPV6_STATEFUL;
            break;
        case "dhcpv6-stateless":
            ipV6Mode = Mode.DHCPV6_STATELESS;
            break;
        case "slaac":
            ipV6Mode = Mode.SLAAC;
            break;
        default:
            ipV6Mode = null;
        }
        return ipV6Mode;
    }

    /**
     * Changes JsonNode alocPools to a collection of the alocPools.
     *
     * @param allocationPools the allocationPools JsonNode
     * @return a collection of allocationPools
     */
    public Iterable<AllocationPool> jsonNodeToAllocationPools(JsonNode allocationPools) {
        checkNotNull(allocationPools, JSON_NOT_NULL);
        ConcurrentMap<Integer, AllocationPool> alocplMaps = Maps
                .newConcurrentMap();
        Integer i = 0;
        for (JsonNode node : allocationPools) {
            IpAddress startIp = IpAddress.valueOf(node.get("start").asText());
            IpAddress endIp = IpAddress.valueOf(node.get("end").asText());
            AllocationPool alocPls = new DefaultAllocationPool(startIp, endIp);
            alocplMaps.putIfAbsent(i, alocPls);
            i++;
        }
        return Collections.unmodifiableCollection(alocplMaps.values());
    }

    /**
     * Changes hostRoutes JsonNode to a collection of the hostRoutes.
     *
     * @param hostRoutes the hostRoutes json node
     * @return a collection of hostRoutes
     */
    public Iterable<HostRoute> jsonNodeToHostRoutes(JsonNode hostRoutes) {
        checkNotNull(hostRoutes, JSON_NOT_NULL);
        ConcurrentMap<Integer, HostRoute> hostRouteMaps = Maps
                .newConcurrentMap();
        Integer i = 0;
        for (JsonNode node : hostRoutes) {
            IpAddress nexthop = IpAddress.valueOf(node.get("nexthop").asText());
            IpPrefix destination = IpPrefix.valueOf(node.get("destination")
                    .asText());
            HostRoute hostRoute = new DefaultHostRoute(nexthop, destination);
            hostRouteMaps.putIfAbsent(i, hostRoute);
            i++;
        }
        return Collections.unmodifiableCollection(hostRouteMaps.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;
    }

}
