/*
 * 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.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", "locations", "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));

            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);
            }

            Iterator<JsonNode> ipNodes = node.get("ipAddresses").elements();
            Set<IpAddress> ips = new HashSet<>();
            while (ipNodes.hasNext()) {
                ips.add(IpAddress.valueOf(ipNodes.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, locations, 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();
        }

    }
}

