/*
 * 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;

@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);
        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, 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;
    }

}
