/*
 * GTK VNC Widget
 *
 * Copyright (C) 2006  Anthony Liguori <anthony@codemonkey.ws>
 * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.0 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */

#ifndef VNC_CONNECTION_H
#define VNC_CONNECTION_H

#include <glib.h>
#include <gio/gio.h>

#include <vncframebuffer.h>
#include <vnccursor.h>
#include <vncutil.h>
#include <vncaudio.h>

G_BEGIN_DECLS

#define VNC_TYPE_CONNECTION            (vnc_connection_get_type ())
#define VNC_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), VNC_TYPE_CONNECTION, VncConnection))
#define VNC_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), VNC_TYPE_CONNECTION, VncConnectionClass))
#define VNC_IS_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VNC_TYPE_CONNECTION))
#define VNC_IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VNC_TYPE_CONNECTION))
#define VNC_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), VNC_TYPE_CONNECTION, VncConnectionClass))

/* identical to the ledstate bits */
#define VNC_LEDSTATE_SCROLL_LOCK (1 << 0)
#define VNC_LEDSTATE_NUM_LOCK    (1 << 1)
#define VNC_LEDSTATE_CAPS_LOCK   (1 << 2)


typedef struct _VncConnection VncConnection;
typedef struct _VncConnectionPrivate VncConnectionPrivate;
typedef struct _VncConnectionClass VncConnectionClass;

struct _VncConnection
{
    GObject parent;

    VncConnectionPrivate *priv;

    /* Do not add fields to this struct */
};

struct _VncConnectionClass
{
    GObjectClass parent_class;

    /* Signals */
    void (*vnc_cursor_changed)(VncConnection *conn, VncCursor *cursor);
    void (*vnc_pointer_mode_changed)(VncConnection *conn, gboolean absPointer);
    void (*vnc_bell)(VncConnection *conn);
    void (*vnc_server_cut_text)(VncConnection *conn, const GString *text);
    void (*vnc_framebuffer_update)(VncConnection *conn, guint16 x, guint16 y, guint16 width, guint16 height);
    void (*vnc_desktop_resize)(VncConnection *conn, guint16 width, guint16 height);
    void (*vnc_pixel_format_changed)(VncConnection *conn, VncPixelFormat *format);
    void (*vnc_auth_failure)(VncConnection *conn, const char *reason);
    void (*vnc_auth_unsupported)(VncConnection *conn, unsigned int authType);
    void (*vnc_auth_credential)(VncConnection *conn, GValueArray *creds);
    void (*vnc_auth_choose_type)(VncConnection *conn, GValueArray *types);
    void (*vnc_auth_choose_subtype)(VncConnection *conn, unsigned int type, GValueArray *subtypes);
    void (*vnc_connected)(VncConnection *conn);
    void (*vnc_initialized)(VncConnection *conn);
    void (*vnc_disconnected)(VncConnection *conn);
    void (*vnc_led_state)(VncConnection *conn);
    void (*vnc_error)(VncConnection *conn, const char *message);
    void (*vnc_power_control_initialized)(VncConnection *conn);
    void (*vnc_power_control_failed)(VncConnection *conn);
    void (*vnc_desktop_rename)(VncConnection *conn, const char *name);

    /*
     * If adding fields to this struct, remove corresponding
     * amount of padding to avoid changing overall struct size
     */
    gpointer _vnc_reserved[VNC_PADDING_LARGE - 5];
};


typedef enum {
    VNC_CONNECTION_ENCODING_RAW = 0,
    VNC_CONNECTION_ENCODING_COPY_RECT = 1,
    VNC_CONNECTION_ENCODING_RRE = 2,
    VNC_CONNECTION_ENCODING_CORRE = 4,
    VNC_CONNECTION_ENCODING_HEXTILE = 5,
    VNC_CONNECTION_ENCODING_TIGHT = 7,
    VNC_CONNECTION_ENCODING_ZRLE = 16,

    /* Tight JPEG quality levels */
    VNC_CONNECTION_ENCODING_TIGHT_JPEG0 = -32,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG1 = -31,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG2 = -30,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG3 = -29,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG4 = -28,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG5 = -27,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG6 = -26,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG7 = -25,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG8 = -24,
    VNC_CONNECTION_ENCODING_TIGHT_JPEG9 = -23,

    /* Pseudo encodings */
    VNC_CONNECTION_ENCODING_DESKTOP_RESIZE = -223,
    VNC_CONNECTION_ENCODING_LAST_RECT = -224,
    VNC_CONNECTION_ENCODING_WMVi = 0x574D5669,

    VNC_CONNECTION_ENCODING_CURSOR_POS = -232,
    VNC_CONNECTION_ENCODING_RICH_CURSOR = -239,
    VNC_CONNECTION_ENCODING_XCURSOR = -240,

    VNC_CONNECTION_ENCODING_POINTER_CHANGE = -257,
    VNC_CONNECTION_ENCODING_EXT_KEY_EVENT = -258,
    VNC_CONNECTION_ENCODING_AUDIO = -259,
    VNC_CONNECTION_ENCODING_LED_STATE = -261,

    VNC_CONNECTION_ENCODING_DESKTOP_NAME = -307,
    VNC_CONNECTION_ENCODING_EXTENDED_DESKTOP_RESIZE = -308,
    VNC_CONNECTION_ENCODING_XVP = -309,
    VNC_CONNECTION_ENCODING_ALPHA_CURSOR = -314,
} VncConnectionEncoding;

/**
 * VncConnectionAuth:
 * @VNC_CONNECTION_AUTH_INVALID:
 * @VNC_CONNECTION_AUTH_NONE: No authentication is needed and protocol data is to be sent unencrypted.
 * @VNC_CONNECTION_AUTH_VNC: VNC authentication is to be used and protocol data is to be sent unencrypted.
 * @VNC_CONNECTION_AUTH_RA2: RealVNC authentication.
 * @VNC_CONNECTION_AUTH_RA2NE: RealVNC authentication.
 * @VNC_CONNECTION_AUTH_TIGHT: The Tight security type is a generic protocol extension.
 * @VNC_CONNECTION_AUTH_ULTRA: Ultra authentication.
 * @VNC_CONNECTION_AUTH_TLS: TLS authentication.
 * @VNC_CONNECTION_AUTH_VENCRYPT: The VeNCrypt security type is a generic authentication method which encapsulates multiple authentication subtypes.
 * @VNC_CONNECTION_AUTH_SASL: SASL authentication.
 * @VNC_CONNECTION_AUTH_ARD: Apple remote desktop (screen sharing) authentication.
 * @VNC_CONNECTION_AUTH_MSLOGONII: Authentication used by UltraVNC.
 * @VNC_CONNECTION_AUTH_MSLOGON: Authentication used by UltraVNC.
 */
typedef enum {
    VNC_CONNECTION_AUTH_INVALID = 0,
    VNC_CONNECTION_AUTH_NONE = 1,
    VNC_CONNECTION_AUTH_VNC = 2,
    VNC_CONNECTION_AUTH_RA2 = 5,
    VNC_CONNECTION_AUTH_RA2NE = 6,
    VNC_CONNECTION_AUTH_TIGHT = 16,
    VNC_CONNECTION_AUTH_ULTRA = 17,
    VNC_CONNECTION_AUTH_TLS = 18,  /* Used by VINO */
    VNC_CONNECTION_AUTH_VENCRYPT = 19, /* Used by VeNCrypt and QEMU */
    VNC_CONNECTION_AUTH_SASL = 20, /* SASL type used by VINO and QEMU */
    VNC_CONNECTION_AUTH_ARD = 30, /* Apple remote desktop (screen sharing) */
    VNC_CONNECTION_AUTH_MSLOGONII = 0x71, /* Used by UltraVNC */
    VNC_CONNECTION_AUTH_MSLOGON = 0xfffffffa, /* (aka 250 when converted to U8), Used by UltraVNC */
} VncConnectionAuth;

typedef enum {
    VNC_CONNECTION_AUTH_VENCRYPT_PLAIN = 256,
    VNC_CONNECTION_AUTH_VENCRYPT_TLSNONE = 257,
    VNC_CONNECTION_AUTH_VENCRYPT_TLSVNC = 258,
    VNC_CONNECTION_AUTH_VENCRYPT_TLSPLAIN = 259,
    VNC_CONNECTION_AUTH_VENCRYPT_X509NONE = 260,
    VNC_CONNECTION_AUTH_VENCRYPT_X509VNC = 261,
    VNC_CONNECTION_AUTH_VENCRYPT_X509PLAIN = 262,
    VNC_CONNECTION_AUTH_VENCRYPT_X509SASL = 263,
    VNC_CONNECTION_AUTH_VENCRYPT_TLSSASL = 264,
} VncConnectionAuthVencrypt;

typedef enum {
    VNC_CONNECTION_CREDENTIAL_PASSWORD,
    VNC_CONNECTION_CREDENTIAL_USERNAME,
    VNC_CONNECTION_CREDENTIAL_CLIENTNAME,
    VNC_CONNECTION_CREDENTIAL_CA_CERT_DATA,
} VncConnectionCredential;

typedef enum {
    VNC_CONNECTION_POWER_ACTION_SHUTDOWN = 2,
    VNC_CONNECTION_POWER_ACTION_REBOOT = 3,
    VNC_CONNECTION_POWER_ACTION_RESET = 4,
} VncConnectionPowerAction;

typedef enum {
    VNC_CONNECTION_RESIZE_STATUS_UNSUPPORTED = -1,
    VNC_CONNECTION_RESIZE_STATUS_OK = 0,
    VNC_CONNECTION_RESIZE_STATUS_ADMIN_PROHIBITED = 1,
    VNC_CONNECTION_RESIZE_STATUS_OUT_OF_RESOURCES = 2,
    VNC_CONNECTION_RESIZE_STATUS_INVALID_LAOUT = 3,
    VNC_CONNECTION_RESIZE_STATUS_FORWARDED = 4,
}  VncConnectionResizeStatus;

GType vnc_connection_get_type(void) G_GNUC_CONST;

VncConnection *vnc_connection_new(void);

gboolean vnc_connection_open_fd(VncConnection *conn, int fd);
gboolean vnc_connection_open_fd_with_hostname(VncConnection *conn, int fd, const char *hostname);
gboolean vnc_connection_open_host(VncConnection *conn, const char *host, const char *port);
gboolean vnc_connection_open_addr(VncConnection *conn, GSocketAddress *addr, const char *hostname);
gboolean vnc_connection_is_open(VncConnection *conn);
void vnc_connection_shutdown(VncConnection *conn);

gboolean vnc_connection_set_auth_type(VncConnection *conn, unsigned int type);
gboolean vnc_connection_set_auth_subtype(VncConnection *conn, unsigned int type);
gboolean vnc_connection_set_credential(VncConnection *conn, int type, const gchar *data);

gboolean vnc_connection_is_initialized(VncConnection *conn);

gboolean vnc_connection_client_cut_text(VncConnection *conn,
                                        const void *data, size_t length);

gboolean vnc_connection_pointer_event(VncConnection *conn, guint8 button_mask,
                                      guint16 x, guint16 y);

gboolean vnc_connection_key_event(VncConnection *conn, gboolean down_flag,
                                  guint32 key, guint16 scancode);

gboolean vnc_connection_framebuffer_update_request(VncConnection *conn,
                                                   gboolean incremental,
                                                   guint16 x, guint16 y,
                                                   guint16 width, guint16 height);

gboolean vnc_connection_set_encodings(VncConnection *conn, int n_encoding, gint32 *encoding);

gboolean vnc_connection_set_pixel_format(VncConnection *conn,
                                         const VncPixelFormat *fmt);

const VncPixelFormat *vnc_connection_get_pixel_format(VncConnection *conn);

gboolean vnc_connection_set_shared(VncConnection *conn, gboolean shared);
gboolean vnc_connection_get_shared(VncConnection *conn);

gboolean vnc_connection_has_error(VncConnection *conn);

gboolean vnc_connection_set_framebuffer(VncConnection *conn,
                                        VncFramebuffer *fb);

const char *vnc_connection_get_name(VncConnection *conn);
int vnc_connection_get_width(VncConnection *conn);
int vnc_connection_get_height(VncConnection *conn);

VncCursor *vnc_connection_get_cursor(VncConnection *conn);

gboolean vnc_connection_get_abs_pointer(VncConnection *conn);
gboolean vnc_connection_get_ext_key_event(VncConnection *conn);
gboolean vnc_connection_get_power_control(VncConnection *conn);
int vnc_connection_get_ledstate(VncConnection *conn);

gboolean vnc_connection_set_audio(VncConnection *conn,
                                  VncAudio *audio);

gboolean vnc_connection_set_audio_format(VncConnection *conn,
                                         const VncAudioFormat *fmt);
const VncAudioFormat *vnc_connection_get_audio_format(VncConnection *conn);

gboolean vnc_connection_audio_enable(VncConnection *conn);
gboolean vnc_connection_audio_disable(VncConnection *conn);

gboolean vnc_connection_power_control(VncConnection *conn,
                                      VncConnectionPowerAction action);

VncConnectionResizeStatus vnc_connection_set_size(VncConnection *conn,
                                                  guint width, guint height);

G_DEFINE_AUTOPTR_CLEANUP_FUNC(VncConnection, g_object_unref)

G_END_DECLS

#endif /* VNC_CONNECTION_H */
