/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

#include "config.h"

#include "argv.h"
#include "client.h"
#include "common/recording.h"
#include "io.h"
#include "kubernetes.h"
#include "ssl.h"
#include "terminal/terminal.h"
#include "url.h"

#include <guacamole/client.h>
#include <guacamole/protocol.h>
#include <libwebsockets.h>

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

/**
 * Callback invoked by libwebsockets for events related to a WebSocket being
 * used for communicating with an attached Kubernetes pod.
 *
 * @param wsi
 *     The libwebsockets handle for the WebSocket connection.
 *
 * @param reason
 *     The reason (event) that this callback was invoked.
 *
 * @param user
 *     Arbitrary data assocated with the WebSocket session. In some cases,
 *     this is actually event-specific data (such as the
 *     LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERT event).
 *
 * @param in
 *     A pointer to arbitrary, reason-specific data.
 *
 * @param length
 *     An arbitrary, reason-specific length value.
 *
 * @return
 *     An undocumented integer value related the success of handling the
 *     event, or -1 if the WebSocket connection should be closed.
 */
static int guac_kubernetes_lws_callback(struct lws* wsi,
        enum lws_callback_reasons reason, void* user,
        void* in, size_t length) {

    guac_client* client = guac_kubernetes_lws_current_client;
    guac_kubernetes_client* kubernetes_client =
        (guac_kubernetes_client*) client->data;

    /* Do not handle any further events if connection is closing */
    if (client->state != GUAC_CLIENT_RUNNING) {
#ifdef HAVE_LWS_CALLBACK_HTTP_DUMMY
        return lws_callback_http_dummy(wsi, reason, user, in, length);
#else
        return 0;
#endif
    }

    switch (reason) {

        /* Complete initialization of SSL */
        case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
            guac_kubernetes_init_ssl(client, (SSL_CTX*) user);
            break;

        /* Failed to connect */
        case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
            guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND,
                    "Error connecting to Kubernetes server: %s",
                    in != NULL ? (char*) in : "(no error description "
                    "available)");
            break;

        /* Connected / logged in */
        case LWS_CALLBACK_CLIENT_ESTABLISHED:
            guac_client_log(client, GUAC_LOG_INFO,
                    "Kubernetes connection successful.");

            /* Allow terminal to render */
            guac_terminal_start(kubernetes_client->term);

            /* Schedule check for pending messages in case messages were added
             * to the outbound message buffer prior to the connection being
             * fully established */
            lws_callback_on_writable(wsi);
            break;

        /* Data received via WebSocket */
        case LWS_CALLBACK_CLIENT_RECEIVE:
            guac_kubernetes_receive_data(client, (const char*) in, length);
            break;

        /* WebSocket is ready for writing */
        case LWS_CALLBACK_CLIENT_WRITEABLE:

            /* Send any pending messages, requesting another callback if
             * yet more messages remain */
            if (guac_kubernetes_write_pending_message(client))
                lws_callback_on_writable(wsi);
            break;

#ifdef HAVE_LWS_CALLBACK_CLIENT_CLOSED
        /* Connection closed (client-specific) */
        case LWS_CALLBACK_CLIENT_CLOSED:
#endif

        /* Connection closed */
        case LWS_CALLBACK_WSI_DESTROY:
        case LWS_CALLBACK_CLOSED:
            guac_client_stop(client);
            guac_client_log(client, GUAC_LOG_DEBUG, "WebSocket connection to "
                    "Kubernetes server closed.");
            break;

        /* No other event types are applicable */
        default:
            break;

    }

#ifdef HAVE_LWS_CALLBACK_HTTP_DUMMY
    return lws_callback_http_dummy(wsi, reason, user, in, length);
#else
    return 0;
#endif

}

/**
 * List of all WebSocket protocols which should be declared as supported by
 * libwebsockets during the initial WebSocket handshake, along with
 * corresponding event-handling callbacks.
 */
struct lws_protocols guac_kubernetes_lws_protocols[] = {
    {
        .name = GUAC_KUBERNETES_LWS_PROTOCOL,
        .callback = guac_kubernetes_lws_callback
    },
    { 0 }
};

/**
 * Input thread, started by the main Kubernetes client thread. This thread
 * continuously reads from the terminal's STDIN and transfers all read
 * data to the Kubernetes connection.
 *
 * @param data
 *     The current guac_client instance.
 *
 * @return
 *     Always NULL.
 */
static void* guac_kubernetes_input_thread(void* data) {

    guac_client* client = (guac_client*) data;
    guac_kubernetes_client* kubernetes_client =
        (guac_kubernetes_client*) client->data;

    char buffer[GUAC_KUBERNETES_MAX_MESSAGE_SIZE];
    int bytes_read;

    /* Write all data read */
    while ((bytes_read = guac_terminal_read_stdin(kubernetes_client->term, buffer, sizeof(buffer))) > 0) {

        /* Send received data to Kubernetes along STDIN channel */
        guac_kubernetes_send_message(client, GUAC_KUBERNETES_CHANNEL_STDIN,
                buffer, bytes_read);

    }

    return NULL;

}

void* guac_kubernetes_client_thread(void* data) {

    guac_client* client = (guac_client*) data;
    guac_kubernetes_client* kubernetes_client =
        (guac_kubernetes_client*) client->data;

    guac_kubernetes_settings* settings = kubernetes_client->settings;

    pthread_t input_thread;
    char endpoint_path[GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH];

    /* Verify that the pod name was specified (it's always required) */
    if (settings->kubernetes_pod == NULL) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
                "The name of the Kubernetes pod is a required parameter.");
        goto fail;
    }

    /* Generate endpoint for attachment URL */
    if (guac_kubernetes_endpoint_attach(endpoint_path, sizeof(endpoint_path),
                settings->kubernetes_namespace,
                settings->kubernetes_pod,
                settings->kubernetes_container)) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
                "Unable to generate path for Kubernetes API endpoint: "
                "Resulting path too long");
        goto fail;
    }

    guac_client_log(client, GUAC_LOG_DEBUG, "The endpoint for attaching to "
            "the requested Kubernetes pod is \"%s\".", endpoint_path);

    /* Set up screen recording, if requested */
    if (settings->recording_path != NULL) {
        kubernetes_client->recording = guac_common_recording_create(client,
                settings->recording_path,
                settings->recording_name,
                settings->create_recording_path,
                !settings->recording_exclude_output,
                !settings->recording_exclude_mouse,
                settings->recording_include_keys);
    }

    /* Create terminal */
    kubernetes_client->term = guac_terminal_create(client,
            kubernetes_client->clipboard,
            settings->max_scrollback, settings->font_name, settings->font_size,
            settings->resolution, settings->width, settings->height,
            settings->color_scheme, settings->backspace);

    /* Fail if terminal init failed */
    if (kubernetes_client->term == NULL) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
                "Terminal initialization failed");
        goto fail;
    }

    /* Send current values of exposed arguments to owner only */
    guac_client_for_owner(client, guac_kubernetes_send_current_argv,
            kubernetes_client);

    /* Set up typescript, if requested */
    if (settings->typescript_path != NULL) {
        guac_terminal_create_typescript(kubernetes_client->term,
                settings->typescript_path,
                settings->typescript_name,
                settings->create_typescript_path);
    }

    /* Init libwebsockets context creation parameters */
    struct lws_context_creation_info context_info = {
        .port = CONTEXT_PORT_NO_LISTEN, /* We are not a WebSocket server */
        .uid = -1,
        .gid = -1,
        .protocols = guac_kubernetes_lws_protocols,
        .user = client
    };

    /* Init WebSocket connection parameters which do not vary by Guacmaole
     * connection parameters or creation of future libwebsockets objects */
    struct lws_client_connect_info connection_info = {
        .host = settings->hostname,
        .address = settings->hostname,
        .origin = settings->hostname,
        .port = settings->port,
        .protocol = GUAC_KUBERNETES_LWS_PROTOCOL,
        .userdata = client
    };

    /* If requested, use an SSL/TLS connection for communication with
     * Kubernetes. Note that we disable hostname checks here because we
     * do our own validation - libwebsockets does not validate properly if
     * IP addresses are used. */
    if (settings->use_ssl) {
#ifdef HAVE_LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT
        context_info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
#endif
#ifdef HAVE_LCCSCF_USE_SSL
        connection_info.ssl_connection = LCCSCF_USE_SSL
            | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
#else
        connection_info.ssl_connection = 2; /* SSL + no hostname check */
#endif
    }

    /* Create libwebsockets context */
    kubernetes_client->context = lws_create_context(&context_info);
    if (!kubernetes_client->context) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
                "Initialization of libwebsockets failed");
        goto fail;
    }

    /* Generate path dynamically */
    connection_info.context = kubernetes_client->context;
    connection_info.path = endpoint_path;

    /* Open WebSocket connection to Kubernetes */
    kubernetes_client->wsi = lws_client_connect_via_info(&connection_info);
    if (kubernetes_client->wsi == NULL) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
                "Connection via libwebsockets failed");
        goto fail;
    }

    /* Init outbound message buffer */
    pthread_mutex_init(&(kubernetes_client->outbound_message_lock), NULL);

    /* Start input thread */
    if (pthread_create(&(input_thread), NULL, guac_kubernetes_input_thread, (void*) client)) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread");
        goto fail;
    }

    /* Force a redraw of the attached display (there will be no content
     * otherwise, given the stream nature of attaching to a running
     * container) */
    guac_kubernetes_force_redraw(client);

    /* As long as client is connected, continue polling libwebsockets */
    while (client->state == GUAC_CLIENT_RUNNING) {

        /* Cease polling libwebsockets if an error condition is signalled */
        if (lws_service(kubernetes_client->context,
                    GUAC_KUBERNETES_SERVICE_INTERVAL) < 0)
            break;

    }

    /* Kill client and Wait for input thread to die */
    guac_terminal_stop(kubernetes_client->term);
    guac_client_stop(client);
    pthread_join(input_thread, NULL);

fail:

    /* Kill and free terminal, if allocated */
    if (kubernetes_client->term != NULL)
        guac_terminal_free(kubernetes_client->term);

    /* Clean up recording, if in progress */
    if (kubernetes_client->recording != NULL)
        guac_common_recording_free(kubernetes_client->recording);

    /* Free WebSocket context if successfully allocated */
    if (kubernetes_client->context != NULL)
        lws_context_destroy(kubernetes_client->context);

    guac_client_log(client, GUAC_LOG_INFO, "Kubernetes connection ended.");
    return NULL;

}

void guac_kubernetes_resize(guac_client* client, int rows, int columns) {

    char buffer[64];

    guac_kubernetes_client* kubernetes_client =
        (guac_kubernetes_client*) client->data;

    /* Send request only if different from last request */
    if (kubernetes_client->rows != rows ||
            kubernetes_client->columns != columns) {

        kubernetes_client->rows = rows;
        kubernetes_client->columns = columns;

        /* Construct terminal resize message for Kubernetes */
        int length = snprintf(buffer, sizeof(buffer),
                "{\"Width\":%i,\"Height\":%i}", columns, rows);

        /* Schedule message for sending */
        guac_kubernetes_send_message(client, GUAC_KUBERNETES_CHANNEL_RESIZE,
                buffer, length);

    }

}

void guac_kubernetes_force_redraw(guac_client* client) {

    guac_kubernetes_client* kubernetes_client =
        (guac_kubernetes_client*) client->data;

    /* Get current terminal dimensions */
    guac_terminal* term = kubernetes_client->term;
    int rows = term->term_height;
    int columns = term->term_width;

    /* Force a redraw by increasing the terminal size by one character in
     * each dimension and then resizing it back to normal (the same technique
     * used by kubectl */
    guac_kubernetes_resize(client, rows + 1, columns + 1);
    guac_kubernetes_resize(client, rows, columns);

}

