/*
 * Copyright 2015-present 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.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.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.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", "location", "ipAddresses"};

    /**
     * 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;
        try {
            // Parse the input stream
            ObjectNode root = (ObjectNode) mapper().readTree(stream);

            HostProviderRegistry hostProviderRegistry = get(HostProviderRegistry.class);
            InternalHostProvider hostProvider = new InternalHostProvider();
            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();
            hostProviderRegistry.unregister(hostProvider);

        } catch (IOException ex) {
            throw new IllegalArgumentException(ex);
        }
        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", true);
        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));
            JsonNode locationNode = node.get("location");
            String deviceAndPort = locationNode.get("elementId").asText() + "/" +
                    locationNode.get("port").asText();
            HostLocation hostLocation = new HostLocation(ConnectPoint.deviceConnectPoint(deviceAndPort), 0);

            Iterator<JsonNode> ipStrings = node.get("ipAddresses").elements();
            Set<IpAddress> ips = new HashSet<>();
            while (ipStrings.hasNext()) {
                ips.add(IpAddress.valueOf(ipStrings.next().asText()));
            }

            // 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, hostLocation, ips, 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();
        }

    }
}

