/*
 * 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.checkArgument;
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;
import com.google.common.collect.Sets;

@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,
                                              Sets.newHashSet(hostRoutesIt), ipV6AddressMode,
                                              ipV6RaMode, Sets.newHashSet(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);
        checkArgument(subnetNodes.get("enable_dhcp").isBoolean(), "enable_dhcp should be boolean");
        checkArgument(subnetNodes.get("shared").isBoolean(), "shared should be boolean");
        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:
            throw new IllegalArgumentException("ipVersion should be 4 or 6.");
        }

        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, Sets.newHashSet(hostRoutesIt),
                                          ipV6AddressMode, ipV6RaMode,
                                          Sets.newHashSet(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;
    }

}
