/*
 * 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.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Charsets;
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.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.util.io.NoCloseInputStream;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.IpAddress;
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.openstacknetworking.api.InstancePort;
import org.onosproject.openstacknetworking.api.InstancePortService;
import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackNodeService;
import org.onosproject.openstacknode.api.OpenstackSshAuth;
import org.onosproject.ui.JsonUtils;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
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 java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;

/**
 * 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 ID = "id";
    private static final String MODE = "mode";
    private static final String MOUSE = "mouse";
    private static final String TRACE_RESULT = "traceResult";
    private static final String IS_SUCCESS = "isSuccess";
    private static final String TRACE_SUCCESS = "traceSuccess";
    private static final String FLOW_TRACE_RESULT = "flowTraceResult";
    private static final String SRC_DEVICE_ID = "srcDeviceId";
    private static final String DST_DEVICE_ID = "dstDeviceId";
    private static final String OVS_VERSION_2_8 = "2.8";
    private static final String OVS_VERSION_2_6 = "2.6";
    private static final String FLAT = "FLAT";
    private static final String VXLAN = "VXLAN";
    private static final String VLAN = "VLAN";
    private static final String DL_DST = "dl_dst=";
    private static final String NW_DST = "nw_dst=";
    private static final String DEFAULT_REQUEST_STRING = "sudo ovs-appctl ofproto/trace br-int ip,in_port=";
    private static final String NW_SRC = "nw_src=";
    private static final String COMMA = ",";


    private static final long TIMEOUT_MS = 5000;
    private static final long WAIT_OUTPUT_STREAM_SECOND = 2;
    private static final int SSH_PORT = 22;

    private enum Mode { IDLE, MOUSE }

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

    private DeviceService deviceService;
    private HostService hostService;
    private PathService pathService;
    private OpenstackNodeService osNodeService;
    private InstancePortService instancePortService;
    private OpenstackNetworkService osNetService;
    private Mode currentMode = Mode.IDLE;
    private Element elementOfNote;

    private final ExecutorService eventExecutor = newSingleThreadExecutor(
            groupedThreads(this.getClass().getSimpleName(), "event-handler", log));

    @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);
        osNodeService = directory.get(OpenstackNodeService.class);
        instancePortService = directory.get(InstancePortService.class);
        osNetService = directory.get(OpenstackNetworkService.class);
    }

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

    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;
                    eventExecutor.execute(() -> 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);
            String srcDeviceId = string(payload, SRC_DEVICE_ID);
            String dstDeviceId = string(payload, DST_DEVICE_ID);
            log.info("Flow trace request called with src IP: {}, dst IP: {}, src device ID: {}, dst device Id: {}",
                    srcIp,
                    dstIp,
                    srcDeviceId,
                    dstDeviceId);
            eventExecutor.execute(() -> processFlowTraceRequest(srcIp, dstIp, srcDeviceId, dstDeviceId));
        }
    }

    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)) {
                eventExecutor.execute(() -> updateForMode(id));
            } else {
                eventExecutor.execute(() -> 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));
    }

    /**
     * Sends JSON-based message to UI.
     * @param type type
     * @param payload payload
     */
    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.parseInt(vni);
    }

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

    private void processFlowTraceRequest(String srcIp, String dstIp, String srcDeviceId, String dstDeviceId) {
        boolean traceSuccess = true;

        ObjectMapper mapper = new ObjectMapper();

        ObjectNode traceResult = mapper.createObjectNode();

        ArrayNode traceResultArray = traceResult.putArray(TRACE_RESULT);

        OpenstackNode srcOpenstackNode = osNodeService.node(DeviceId.deviceId(srcDeviceId));
        if (srcOpenstackNode == null) {
            return;
        }

        if (srcOpenstackNode.sshAuthInfo() == null) {
            log.error("Openstack node {} has no SSH authentication information..",
                    srcOpenstackNode.hostname());
            return;
        }

        String traceResultForward = sendTraceRequestToNode(srcIp, dstIp, srcOpenstackNode);
        if (traceResultForward == null) {
            return;
        }

        log.debug("traceResultForward raw data: {}", traceResultForward);

        ObjectNode traceResultForwardJson = null;

        Device srcDevice = deviceService.getDevice(srcOpenstackNode.intgBridge());
        if (srcDevice.swVersion().startsWith(OVS_VERSION_2_8)) {
            traceResultForwardJson = Ovs28FlowTraceResultParser.flowTraceResultInJson(
                    traceResultForward.trim(), srcOpenstackNode.hostname());
        } else {
            log.error("Currently OVS version {} is not supported",
                    deviceService.getDevice(srcOpenstackNode.intgBridge()));
        }

        if (traceResultForwardJson == null) {
            return;
        }

        traceResultArray.add(traceResultForwardJson);

        log.debug("traceResultForward Json: {}", traceResultForwardJson);

        if (!traceResultForwardJson.get(IS_SUCCESS).asBoolean()) {
            traceSuccess = false;
        }

        //TODO implements trace result in backward

        traceResult.put(TRACE_SUCCESS, traceSuccess);
        log.debug("traceResult Json: {}", traceResult);

        sendMessagetoUi(FLOW_TRACE_RESULT, traceResult);

    }

    private String sendTraceRequestToNode(String srcIp, String dstIp, OpenstackNode openstackNode) {
        String traceResult = null;
        OpenstackSshAuth sshAuth = openstackNode.sshAuthInfo();

        try (SshClient client = SshClient.setUpDefaultClient()) {
            client.start();

            try (ClientSession session = client
                    .connect(sshAuth.id(), openstackNode.managementIp().getIp4Address().toString(), SSH_PORT)
                    .verify(TIMEOUT_MS, TimeUnit.SECONDS).getSession()) {
                session.addPasswordIdentity(sshAuth.password());
                session.auth().verify(TIMEOUT_MS, TimeUnit.SECONDS);


                try (ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL)) {

                    String requestString = traceRequestString(srcIp, dstIp, openstackNode);
                    if (requestString == null) {
                        return null;
                    }

                    log.debug("requestString: {}", requestString);
                    final InputStream inputStream =
                            new ByteArrayInputStream(requestString.getBytes());

                    OutputStream outputStream = new ByteArrayOutputStream();
                    OutputStream errStream = new ByteArrayOutputStream();

                    channel.setIn(new NoCloseInputStream(inputStream));
                    channel.setErr(errStream);
                    channel.setOut(outputStream);

                    Collection<ClientChannelEvent> eventList = Lists.newArrayList();
                    eventList.add(ClientChannelEvent.OPENED);

                    OpenFuture channelFuture = channel.open();

                    if (channelFuture.await(TIMEOUT_MS, TimeUnit.SECONDS)) {

                        long timeoutExpiredMs = System.currentTimeMillis() + TIMEOUT_MS;

                        while (!channelFuture.isOpened()) {
                            if ((timeoutExpiredMs - System.currentTimeMillis()) <= 0) {
                                log.error("Failed to open channel");
                                return null;
                            }
                        }
                        TimeUnit.SECONDS.sleep(WAIT_OUTPUT_STREAM_SECOND);

                        traceResult = ((ByteArrayOutputStream) outputStream).toString(Charsets.UTF_8.name());

                        channel.close();
                    }
                } finally {
                    session.close();
                }
            } finally {
                client.stop();
            }

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

        return traceResult;
    }

    private String traceRequestString(String srcIp, String dstIp, OpenstackNode openstackNode) {

        Optional<InstancePort> instancePort = instancePortService.instancePorts().stream()
                .filter(port -> port.ipAddress().getIp4Address().toString().equals(srcIp)
                        && port.deviceId().equals(openstackNode.intgBridge()))
                .findAny();

        if (!instancePort.isPresent()) {
            return null;
        }

        String requestString = DEFAULT_REQUEST_STRING
                + instancePort.get().portNumber().toString()
                + COMMA
                + NW_SRC
                + srcIp
                + COMMA;

        if (osNetService.networkType(instancePort.get().networkId()).equals(VXLAN)) {
            if (srcIp.equals(dstIp)) {
                dstIp = osNetService.gatewayIp(instancePort.get().portId());
                requestString = requestString + DL_DST + DEFAULT_GATEWAY_MAC_STR + COMMA;
            } else if (!osNetService.ipPrefix(instancePort.get().portId()).contains(IpAddress.valueOf(dstIp))) {
                requestString = requestString + DL_DST + DEFAULT_GATEWAY_MAC_STR + COMMA;
            }
        } else if (osNetService.networkType(instancePort.get().networkId()).equals(FLAT)) {
            if (srcIp.equals(dstIp)) {
                dstIp = osNetService.gatewayIp(instancePort.get().portId());
            }
        }

        requestString = requestString + NW_DST + dstIp + "\n";

        return requestString;
    }
}
