/*
 * Copyright 2017-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.openstacknetworkingui;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.cluster.ClusterService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Element;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Path;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.topology.PathService;
import org.onosproject.ui.JsonUtils;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.apache.commons.io.IOUtils;

import org.onosproject.ui.topo.Highlights;
import org.onosproject.ui.topo.HostHighlight;
import org.onosproject.ui.topo.NodeBadge;
import org.onosproject.ui.topo.NodeBadge.Status;
import org.onosproject.ui.topo.TopoJson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Collection;
import java.util.List;
import java.util.Set;


import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;

/**
 * OpenStack Networking UI message handler.
 */
public class OpenstackNetworkingUiMessageHandler extends UiMessageHandler {

    private static final String OPENSTACK_NETWORKING_UI_START = "openstackNetworkingUiStart";
    private static final String OPENSTACK_NETWORKING_UI_UPDATE = "openstackNetworkingUiUpdate";
    private static final String OPENSTACK_NETWORKING_UI_STOP = "openstackNetworkingUiStop";
    private static final String ANNOTATION_NETWORK_ID = "networkId";
    private static final String FLOW_TRACE_REQUEST = "flowTraceRequest";
    private static final String SRC_IP = "srcIp";
    private static final String DST_IP = "dstIp";
    private static final String ANNOTATION_SEGMENT_ID = "segId";
    private static final String AUTHORIZATION = "Authorization";
    private static final String COMMAND = "command";
    private static final String FLOW_TRACE = "flowtrace";
    private static final String REVERSE = "reverse";
    private static final String TRANSACTION_ID = "transaction_id";
    private static final String TRANSACTION_VALUE = "sona";
    private static final String APP_REST_URL = "app_rest_url";
    private static final String MATCHING_FIELDS = "matchingfields";
    private static final String SOURCE_IP = "source_ip";
    private static final String DESTINATION_IP = "destination_ip";
    private static final String TO_GATEWAY = "to_gateway";
    private static final String IP_PROTOCOL = "ip_protocol";
    private static final String HTTP = "http://";
    private static final String OPENSTACK_NETWORKING_UI_RESULT = ":8181/onos/openstacknetworkingui/result";

    private static final String ID = "id";
    private static final String MODE = "mode";
    private static final String MOUSE = "mouse";

    private enum Mode { IDLE, MOUSE }

    private final Logger log = LoggerFactory.getLogger(getClass());

    private DeviceService deviceService;
    private HostService hostService;
    private PathService pathService;
    private ClusterService clusterService;
    private String restUrl;
    private String restAuthInfo;
    private Mode currentMode = Mode.IDLE;
    private Element elementOfNote;
    private final Client client = ClientBuilder.newClient();


    // ===============-=-=-=-=-=-======================-=-=-=-=-=-=-================================


    @Override
    public void init(UiConnection connection, ServiceDirectory directory) {
        super.init(connection, directory);
        deviceService = directory.get(DeviceService.class);
        hostService = directory.get(HostService.class);
        pathService = directory.get(PathService.class);
        clusterService = directory.get(ClusterService.class);
    }

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new DisplayStartHandler(),
                new DisplayUpdateHandler(),
                new DisplayStopHandler(),
                new FlowTraceRequestHandler()
        );
    }

    public void setRestUrl(String ipAddress) {
        restUrl = "http://" + ipAddress + ":8000/trace_request";
    }

    public String restUrl() {
        return restUrl;
    }

    public void setRestAuthInfo(String id, String password) {
        restAuthInfo = Base64.getEncoder().encodeToString(id.concat(":").concat(password).getBytes());
    }

    public String restAuthInfo() {
        return restAuthInfo;
    }

    private final class DisplayStartHandler extends RequestHandler {

        public DisplayStartHandler() {
            super(OPENSTACK_NETWORKING_UI_START);
        }

        @Override
        public void process(ObjectNode payload) {
            String mode = string(payload, MODE);

            log.debug("Start Display: mode [{}]", mode);
            clearState();
            clearForMode();

            switch (mode) {
                case MOUSE:
                    currentMode = Mode.MOUSE;
                    sendMouseData();
                    break;

                default:
                    currentMode = Mode.IDLE;
                    break;
            }
        }
    }

    private final class FlowTraceRequestHandler extends RequestHandler {
        public FlowTraceRequestHandler() {
            super(FLOW_TRACE_REQUEST);
        }

        @Override
        public void process(ObjectNode payload) {
            String srcIp = string(payload, SRC_IP);
            String dstIp = string(payload, DST_IP);
            log.debug("SendEvent called with src IP: {}, dst IP: {}", srcIp, dstIp);

            ObjectNode objectNode = getFlowTraceRequestAsJson(srcIp, dstIp);
            InputStream byteArrayInputStream
                    = new ByteArrayInputStream(objectNode.toString().getBytes());

            Invocation.Builder builder = getClientBuilder(restUrl);

            if (builder == null) {
                log.error("Fail to get the client builder for the trace from {} to {}", srcIp, dstIp);
                return;
            }

            try {
                Response response = builder.header(AUTHORIZATION, restAuthInfo.toString())
                        .post(Entity.entity(IOUtils.toString(byteArrayInputStream, StandardCharsets.UTF_8),
                                MediaType.APPLICATION_JSON_TYPE));

                log.debug("Response from server: {}", response);

                if (response.getStatus() != 200) {
                    log.error("FlowTraceRequest failed because of {}", response);
                }

            } catch (IOException e) {
                log.error("Exception occured because of {}", e.toString());
            }

        }
    }

    private ObjectNode getFlowTraceRequestAsJson(String srcIp, String dstIp) {
        ObjectMapper mapper = new ObjectMapper();
        String controllerUrl = HTTP + clusterService.getLocalNode().ip()
                + OPENSTACK_NETWORKING_UI_RESULT;

        ObjectNode objectNode = mapper.createObjectNode();

        objectNode.put(COMMAND, FLOW_TRACE)
                .put(REVERSE, false)
                .put(TRANSACTION_ID, TRANSACTION_VALUE)
                .put(APP_REST_URL, controllerUrl);

        if (srcIp.equals(dstIp)) {
            objectNode.putObject(MATCHING_FIELDS)
                    .put(SOURCE_IP, srcIp)
                    .put(DESTINATION_IP, dstIp)
                    .put(TO_GATEWAY, true)
                    .put(IP_PROTOCOL, 1);

        } else {
            objectNode.putObject(MATCHING_FIELDS)
                    .put(SOURCE_IP, srcIp)
                    .put(DESTINATION_IP, dstIp);
        }
        return  objectNode;
    }

    private Invocation.Builder getClientBuilder(String url) {
        if (Strings.isNullOrEmpty(url)) {
            log.warn("URL in not set");
            return null;
        }

        WebTarget wt = client.target(url);

        return wt.request(MediaType.APPLICATION_JSON_TYPE);
    }

    private final class DisplayUpdateHandler extends RequestHandler {
        public DisplayUpdateHandler() {
            super(OPENSTACK_NETWORKING_UI_UPDATE);
        }

        @Override
        public void process(ObjectNode payload) {
            String id = string(payload, ID);
            log.debug("Update Display: id [{}]", id);
            if (!Strings.isNullOrEmpty(id)) {
                updateForMode(id);
            } else {
                clearForMode();
            }
        }
    }

    private final class DisplayStopHandler extends RequestHandler {
        public DisplayStopHandler() {
            super(OPENSTACK_NETWORKING_UI_STOP);
        }

        @Override
        public void process(ObjectNode payload) {
            log.debug("Stop Display");
            clearState();
            clearForMode();
        }
    }

    // === ------------

    private void clearState() {
        currentMode = Mode.IDLE;
        elementOfNote = null;
    }

    private void updateForMode(String id) {

        try {
            HostId hid = HostId.hostId(id);
            elementOfNote = hostService.getHost(hid);

        } catch (Exception e) {
            try {
                DeviceId did = DeviceId.deviceId(id);
                elementOfNote = deviceService.getDevice(did);

            } catch (Exception e2) {
                log.debug("Unable to process ID [{}]", id);
                elementOfNote = null;
            }
        }

        switch (currentMode) {
            case MOUSE:
                sendMouseData();
                break;

            default:
                break;
        }

    }

    private void clearForMode() {
        sendHighlights(new Highlights());
    }

    private void sendHighlights(Highlights highlights) {
        sendMessage(TopoJson.highlightsMessage(highlights));
    }

    public void sendMessagetoUi(String type, ObjectNode payload) {
        sendMessage(JsonUtils.envelope(type, payload));
    }

    private int getVni(Host host) {
        String vni = host.annotations().value(ANNOTATION_SEGMENT_ID);

        return vni == null ? 0 : Integer.valueOf(vni).intValue();
    }

    private void sendMouseData() {
        Highlights highlights = new Highlights();

        if (elementOfNote != null && elementOfNote instanceof Device) {
            DeviceId deviceId = (DeviceId) elementOfNote.id();

            List<OpenstackLink> edgeLinks = edgeLinks(deviceId);

            edgeLinks.forEach(edgeLink -> {
                highlights.add(edgeLink.highlight(OpenstackLink.RequestType.DEVICE_SELECTED));
            });

            hostService.getConnectedHosts(deviceId).forEach(host -> {
                HostHighlight hostHighlight = new HostHighlight(host.id().toString());
                hostHighlight.setBadge(createBadge(getVni(host)));
                highlights.add(hostHighlight);
            });

            sendHighlights(highlights);

        } else if (elementOfNote != null && elementOfNote instanceof Host) {

            HostId hostId = HostId.hostId(elementOfNote.id().toString());
            if (!hostMadeFromOpenstack(hostId)) {
                return;
            }

            List<OpenstackLink> openstackLinks = linksInSameNetwork(hostId);

            openstackLinks.forEach(openstackLink -> {
                highlights.add(openstackLink.highlight(OpenstackLink.RequestType.HOST_SELECTED));
            });

            hostHighlightsInSameNetwork(hostId).forEach(highlights::add);

            sendHighlights(highlights);

        }
    }

    private boolean hostMadeFromOpenstack(HostId hostId) {
        return hostService.getHost(hostId).annotations()
                .value(ANNOTATION_NETWORK_ID) == null ? false : true;
    }

    private String networkId(HostId hostId) {
        return hostService.getHost(hostId).annotations().value(ANNOTATION_NETWORK_ID);
    }

    private Set<HostHighlight> hostHighlightsInSameNetwork(HostId hostId) {

        Set<HostHighlight> hostHighlights = Sets.newHashSet();
        Streams.stream(hostService.getHosts())
                .filter(host -> isHostInSameNetwork(host, networkId(hostId)))
                .forEach(host -> {
                    HostHighlight hostHighlight = new HostHighlight(host.id().toString());
                    hostHighlight.setBadge(createBadge(getVni(host)));
                    hostHighlights.add(hostHighlight);
                });

        return hostHighlights;
    }

    private List<OpenstackLink> edgeLinks(DeviceId deviceId) {
        OpenstackLinkMap openstackLinkMap = new OpenstackLinkMap();

        hostService.getConnectedHosts(deviceId).forEach(host -> {
            openstackLinkMap.add(createEdgeLink(host, true));
            openstackLinkMap.add(createEdgeLink(host, false));
        });

        List<OpenstackLink> edgeLinks = Lists.newArrayList();

        openstackLinkMap.biLinks().forEach(edgeLinks::add);

        return edgeLinks;
    }

    private List<OpenstackLink> linksInSameNetwork(HostId hostId) {
        OpenstackLinkMap linkMap = new OpenstackLinkMap();

        Streams.stream(hostService.getHosts())
                .filter(host -> isHostInSameNetwork(host, networkId(hostId)))
                .forEach(host -> {
                    linkMap.add(createEdgeLink(host, true));
                    linkMap.add(createEdgeLink(host, false));

                    Set<Path> paths = pathService.getPaths(hostId,
                            host.id());

                    if (!paths.isEmpty()) {
                        paths.forEach(path -> path.links().forEach(linkMap::add));
                    }
                });

        List<OpenstackLink> openstackLinks = Lists.newArrayList();

        linkMap.biLinks().forEach(openstackLinks::add);

        return openstackLinks;
    }

    private boolean isHostInSameNetwork(Host host, String networkId) {
        return hostService.getHost(host.id()).annotations()
                .value(ANNOTATION_NETWORK_ID).equals(networkId);
    }

    private NodeBadge createBadge(int n) {
        return NodeBadge.number(Status.INFO, n, "Openstack Node");
    }
}
