/*
 * 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.rest.resources;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostAdminService;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.rest.AbstractWebResource;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import static org.onlab.util.Tools.nullIsNotFound;
import static org.onlab.util.Tools.readTreeFromStream;
import static org.onosproject.net.HostId.hostId;

/**
 * Manage inventory of end-station hosts.
 */
@Path("hosts")
public class HostsWebResource extends AbstractWebResource {

    @Context
    private UriInfo uriInfo;
    private static final String HOST_NOT_FOUND = "Host is not found";
    private static final String[] REMOVAL_KEYS = {"mac", "vlan", "locations", "ipAddresses",
            "auxLocations", "innerVlan", "outerTpid"};

    /**
     * Get all end-station hosts.
     * Returns array of all known end-station hosts.
     *
     * @return 200 OK with array of all known end-station hosts.
     * @onos.rsModel Hosts
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getHosts() {
        final Iterable<Host> hosts = get(HostService.class).getHosts();
        final ObjectNode root = encodeArray(Host.class, "hosts", hosts);
        return ok(root).build();
    }

    /**
     * Get details of end-station host.
     * Returns detailed properties of the specified end-station host.
     *
     * @param id host identifier
     * @return 200 OK with detailed properties of the specified end-station host
     * @onos.rsModel Host
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{id}")
    public Response getHostById(@PathParam("id") String id) {
        final Host host = nullIsNotFound(get(HostService.class).getHost(hostId(id)),
                                         HOST_NOT_FOUND);
        final ObjectNode root = codec(Host.class).encode(host, this);
        return ok(root).build();
    }

    /**
     * Get details of end-station host with MAC/VLAN.
     * Returns detailed properties of the specified end-station host.
     *
     * @param mac  host MAC address
     * @param vlan host VLAN identifier
     * @return 200 OK with detailed properties of the specified end-station host
     * @onos.rsModel Host
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{mac}/{vlan}")
    public Response getHostByMacAndVlan(@PathParam("mac") String mac,
                                        @PathParam("vlan") String vlan) {
        final Host host = nullIsNotFound(get(HostService.class).getHost(hostId(mac + "/" + vlan)),
                                         HOST_NOT_FOUND);
        final ObjectNode root = codec(Host.class).encode(host, this);
        return ok(root).build();
    }

    /**
     * Creates a new host based on JSON input and adds it to the current
     * host inventory.
     *
     * @param stream input JSON
     * @return status of the request - CREATED if the JSON is correct,
     * BAD_REQUEST if the JSON is invalid
     * @onos.rsModel HostPut
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createAndAddHost(InputStream stream) {
        URI location;
        HostProviderRegistry hostProviderRegistry = get(HostProviderRegistry.class);
        InternalHostProvider hostProvider = new InternalHostProvider();
        try {
            // Parse the input stream
            ObjectNode root = readTreeFromStream(mapper(), stream);

            HostProviderService hostProviderService = hostProviderRegistry.register(hostProvider);
            hostProvider.setHostProviderService(hostProviderService);
            HostId hostId = hostProvider.parseHost(root);

            UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
                    .path("hosts")
                    .path(hostId.mac().toString())
                    .path(hostId.vlanId().toString());
            location = locationBuilder.build();
        } catch (IOException ex) {
            throw new IllegalArgumentException(ex);
        } finally {
            hostProviderRegistry.unregister(hostProvider);
        }

        return Response
                .created(location)
                .build();
    }

    /**
     * Removes infrastructure device.
     * Administratively deletes the specified device from the inventory of
     * known devices.
     *
     * @param mac  host MAC address
     * @param vlan host VLAN identifier
     * @return 204 OK
     * @onos.rsModel Host
     */
    @DELETE
    @Path("{mac}/{vlan}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response removeHost(@PathParam("mac") String mac,
                               @PathParam("vlan") String vlan) {
        get(HostAdminService.class).removeHost(hostId(mac + "/" + vlan));
        return Response.noContent().build();
    }

    /**
     * Internal host provider that provides host events.
     */
    private final class InternalHostProvider implements HostProvider {
        private final ProviderId providerId =
                new ProviderId("host", "org.onosproject.rest");
        private HostProviderService hostProviderService;

        /**
         * Prevents from instantiation.
         */
        private InternalHostProvider() {
        }

        public void triggerProbe(Host host) {
            // Not implemented since there is no need to check for hosts on network
        }

        public void setHostProviderService(HostProviderService service) {
            this.hostProviderService = service;
        }

        /*
         * Return the ProviderId of "this"
         */
        public ProviderId id() {
            return providerId;
        }

        /**
         * Creates and adds new host based on given data and returns its host ID.
         *
         * @param node JsonNode containing host information
         * @return host ID of new host created
         */
        private HostId parseHost(JsonNode node) {
            MacAddress mac = MacAddress.valueOf(node.get("mac").asText());
            VlanId vlanId = VlanId.vlanId((short) node.get("vlan").asInt(VlanId.UNTAGGED));

            // Parse locations
            if (null == node.get("locations")) {
                throw new IllegalArgumentException("location isn't specified");
            }
            Iterator<JsonNode> locationNodes = node.get("locations").elements();
            Set<HostLocation> locations = new HashSet<>();
            while (locationNodes.hasNext()) {
                JsonNode locationNode = locationNodes.next();
                String deviceAndPort = locationNode.get("elementId").asText() + "/" +
                        locationNode.get("port").asText();
                HostLocation hostLocation = new HostLocation(ConnectPoint.deviceConnectPoint(deviceAndPort), 0);
                locations.add(hostLocation);
            }

            // Parse ipAddresses
            if (null == node.get("ipAddresses")) {
                throw new IllegalArgumentException("ipAddress isn't specified");
            }
            Iterator<JsonNode> ipNodes = node.get("ipAddresses").elements();
            Set<IpAddress> ips = new HashSet<>();
            while (ipNodes.hasNext()) {
                ips.add(IpAddress.valueOf(ipNodes.next().asText()));
            }

            // Parse auxLocations
            Set<HostLocation> auxLocations;
            JsonNode auxLocationsNode = node.get("auxLocations");
            if (null == auxLocationsNode) {
                auxLocations = null;
            } else {
                Iterator<JsonNode> auxLocationNodes = auxLocationsNode.elements();
                auxLocations = new HashSet<>();
                while (auxLocationNodes.hasNext()) {
                    JsonNode auxLocationNode = auxLocationNodes.next();
                    String deviceAndPort = auxLocationNode.get("elementId").asText() + "/" +
                            auxLocationNode.get("port").asText();
                    HostLocation auxLocation = new HostLocation(ConnectPoint.deviceConnectPoint(deviceAndPort), 0);
                    auxLocations.add(auxLocation);
                }
            }

            // Parse innerVlan
            JsonNode innerVlanNode = node.get("innerVlan");
            VlanId innerVlan = (null == innerVlanNode) ? VlanId.NONE : VlanId.vlanId(innerVlanNode.asText());

            // Parse outerTpid
            JsonNode outerTpidNode = node.get("outerTpid");
            EthType outerTpid = (null == outerTpidNode) ? EthType.EtherType.UNKNOWN.ethType() :
                    EthType.EtherType.lookup((short) (Integer.decode(outerTpidNode.asText()) & 0xFFFF)).ethType();

            // try to remove elements from json node after reading them
            SparseAnnotations annotations = annotations(removeElements(node, REMOVAL_KEYS));
            // Update host inventory

            HostId hostId = HostId.hostId(mac, vlanId);
            DefaultHostDescription desc = new DefaultHostDescription(mac, vlanId, locations, auxLocations,
                    ips, innerVlan, outerTpid, true, annotations);
            hostProviderService.hostDetected(hostId, desc, false);
            return hostId;
        }

        /**
         * Remove a set of elements from JsonNode by specifying keys.
         *
         * @param node JsonNode containing host information
         * @param removalKeys key of elements that need to be removed
         * @return removal keys
         */
        private JsonNode removeElements(JsonNode node, String[] removalKeys) {
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> map = mapper.convertValue(node, Map.class);
            for (String key : removalKeys) {
                map.remove(key);
            }
            return mapper.convertValue(map, JsonNode.class);
        }

        /**
         * Produces annotations from specified JsonNode. Copied from the ConfigProvider
         * class for use in the POST method.
         *
         * @param node node to be annotated
         * @return SparseAnnotations object with information about node
         */
        private SparseAnnotations annotations(JsonNode node) {
            if (node == null) {
                return DefaultAnnotations.EMPTY;
            }

            DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
            Iterator<String> it = node.fieldNames();
            while (it.hasNext()) {
                String k = it.next();
                builder.set(k, node.get(k).asText());
            }
            return builder.build();
        }

    }
}

