/*
 * QEMU external Spice client display driver
 *
 * Copyright (c) 2018 Marc-André Lureau <marcandre.lureau@redhat.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "qemu/osdep.h"

#include <gio/gio.h>

#include "ui/console.h"
#include "qemu/config-file.h"
#include "qemu/option.h"
#include "qemu/cutils.h"
#include "qemu/module.h"
#include "qapi/error.h"
#include "io/channel-command.h"
#include "chardev/spice.h"
#include "sysemu/sysemu.h"

static const char *tmp_dir;
static char *app_dir;
static char *sock_path;

typedef struct VCChardev {
    SpiceChardev parent;
} VCChardev;

#define TYPE_CHARDEV_VC "chardev-vc"
#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC)

static ChardevBackend *
chr_spice_backend_new(void)
{
    ChardevBackend *be = g_new0(ChardevBackend, 1);

    be->type = CHARDEV_BACKEND_KIND_SPICEPORT;
    be->u.spiceport.data = g_new0(ChardevSpicePort, 1);

    return be;
}

static void vc_chr_open(Chardev *chr,
                        ChardevBackend *backend,
                        bool *be_opened,
                        Error **errp)
{
    ChardevBackend *be;
    const char *fqdn = NULL;

    if (strstart(chr->label, "serial", NULL)) {
        fqdn = "org.qemu.console.serial.0";
    } else if (strstart(chr->label, "parallel", NULL)) {
        fqdn = "org.qemu.console.parallel.0";
    } else if (strstart(chr->label, "compat_monitor", NULL)) {
        fqdn = "org.qemu.monitor.hmp.0";
    }

    be = chr_spice_backend_new();
    be->u.spiceport.data->fqdn = fqdn ?
        g_strdup(fqdn) : g_strdup_printf("org.qemu.console.%s", chr->label);
    qemu_chr_open_spice_port(chr, be, be_opened, errp);
    qapi_free_ChardevBackend(be);
}

static void vc_chr_set_echo(Chardev *chr, bool echo)
{
    /* TODO: set echo for frontends QMP and qtest */
}

static void char_vc_class_init(ObjectClass *oc, void *data)
{
    ChardevClass *cc = CHARDEV_CLASS(oc);

    cc->parse = qemu_chr_parse_vc;
    cc->open = vc_chr_open;
    cc->chr_set_echo = vc_chr_set_echo;
}

static const TypeInfo char_vc_type_info = {
    .name = TYPE_CHARDEV_VC,
    .parent = TYPE_CHARDEV_SPICEPORT,
    .instance_size = sizeof(VCChardev),
    .class_init = char_vc_class_init,
};

static void spice_app_atexit(void)
{
    if (sock_path) {
        unlink(sock_path);
    }
    if (tmp_dir) {
        rmdir(tmp_dir);
    }
    g_free(sock_path);
    g_free(app_dir);
}

static void spice_app_display_early_init(DisplayOptions *opts)
{
    QemuOpts *qopts;
    ChardevBackend *be = chr_spice_backend_new();
    GError *err = NULL;

    if (opts->has_full_screen) {
        error_report("spice-app full-screen isn't supported yet.");
        exit(1);
    }
    if (opts->has_window_close) {
        error_report("spice-app window-close isn't supported yet.");
        exit(1);
    }

    atexit(spice_app_atexit);

    if (qemu_name) {
        app_dir = g_build_filename(g_get_user_runtime_dir(),
                                   "qemu", qemu_name, NULL);
        if (g_mkdir_with_parents(app_dir, S_IRWXU) < -1) {
            error_report("Failed to create directory %s: %s",
                         app_dir, strerror(errno));
            exit(1);
        }
    } else {
        app_dir = g_dir_make_tmp(NULL, &err);
        tmp_dir = app_dir;
        if (err) {
            error_report("Failed to create temporary directory: %s",
                         err->message);
            exit(1);
        }
    }

    type_register(&char_vc_type_info);

    sock_path = g_strjoin("", app_dir, "/", "spice.sock", NULL);
    qopts = qemu_opts_create(qemu_find_opts("spice"), NULL, 0, &error_abort);
    qemu_opt_set(qopts, "disable-ticketing", "on", &error_abort);
    qemu_opt_set(qopts, "unix", "on", &error_abort);
    qemu_opt_set(qopts, "addr", sock_path, &error_abort);
    qemu_opt_set(qopts, "image-compression", "off", &error_abort);
    qemu_opt_set(qopts, "streaming-video", "off", &error_abort);
#ifdef CONFIG_OPENGL
    qemu_opt_set(qopts, "gl", opts->has_gl ? "on" : "off", &error_abort);
    display_opengl = opts->has_gl;
#endif
    be->u.spiceport.data->fqdn = g_strdup("org.qemu.monitor.qmp.0");
    qemu_chardev_new("org.qemu.monitor.qmp", TYPE_CHARDEV_SPICEPORT,
                     be, NULL, &error_abort);
    qopts = qemu_opts_create(qemu_find_opts("mon"),
                             NULL, 0, &error_fatal);
    qemu_opt_set(qopts, "chardev", "org.qemu.monitor.qmp", &error_abort);
    qemu_opt_set(qopts, "mode", "control", &error_abort);

    qapi_free_ChardevBackend(be);
}

static void spice_app_display_init(DisplayState *ds, DisplayOptions *opts)
{
    GError *err = NULL;
    gchar *uri;

    uri = g_strjoin("", "spice+unix://", app_dir, "/", "spice.sock", NULL);
    info_report("Launching display with URI: %s", uri);
    g_app_info_launch_default_for_uri(uri, NULL, &err);
    if (err) {
        error_report("Failed to launch %s URI: %s", uri, err->message);
        error_report("You need a capable Spice client, "
                     "such as virt-viewer 8.0");
        exit(1);
    }
    g_free(uri);
}

static QemuDisplay qemu_display_spice_app = {
    .type       = DISPLAY_TYPE_SPICE_APP,
    .early_init = spice_app_display_early_init,
    .init       = spice_app_display_init,
};

static void register_spice_app(void)
{
    qemu_display_register(&qemu_display_spice_app);
}

type_init(register_spice_app);
