# This file is part of Xpra.
# Copyright (C) 2017-2021 Antoine Martin <antoine@xpra.org>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

import struct
from enum import IntEnum

#merge header and packet if packet is smaller than:
PIXEL_FORMAT = b"BBBBHHHBBBBBB"
CLIENT_INIT = b"!HH"+PIXEL_FORMAT+b"I"


class RFBClientMessage(IntEnum):
    """ client to server messages """
    SetPixelFormat = 0
    SetEncodings = 2
    FramebufferUpdateRequest = 3
    KeyEvent = 4
    PointerEvent = 5
    ClientCutText = 6
    #optional:
    FileTransfer = 7
    SetScale = 8
    SetServerInput = 9
    SetSW = 10
    TextChat = 11
    KeyFrameRequest = 12
    KeepAlive = 13
    SetScaleFactor = 15
    RequestSession = 20
    SetSession = 21
    NotifyPluginStreaming = 80
    VMWare = 127
    CarConnectivity = 128
    EnableContinuousUpdates = 150
    ClientFence = 248
    OliveCallControl = 249
    XVPClientMessage = 250
    SetDesktopSize = 251
    Tight = 252
    GIIClientMessage = 253
    #VMWARE = 254
    QEMUClientMessage = 255

CLIENT_PACKET_TYPE_STR = {}
for e in RFBClientMessage:
    CLIENT_PACKET_TYPE_STR[e.value] = e.name


PACKET_STRUCT = {}
for msg, fmt in {
    RFBClientMessage.SetPixelFormat             : b"!BBBB"+PIXEL_FORMAT,
    RFBClientMessage.SetEncodings               : b"!BBH",
    RFBClientMessage.FramebufferUpdateRequest   : b"!BBHHHH",
    RFBClientMessage.KeyEvent                   : b"!BBBBi",
    RFBClientMessage.PointerEvent               : b"!BBHH",
    RFBClientMessage.ClientCutText              : b"!BBBBi",
    }.items():
    PACKET_STRUCT[msg] = struct.Struct(fmt)


class RFBServerMessage(IntEnum):
    #server to client messages:
    FRAMEBUFFERUPDATE = 0
    SETCOLORMAPENTRIES = 1
    BELL = 2
    SERVERCUTTEXT = 3
    #optional:
    RESIZEFRAMEBUFFER1 = 4
    KEYFRAMEUPDATE = 4
    FILETRANSFER = 7
    TEXTCHAT = 11
    KEEPALIVE = 13
    RESIZEFRAMEBUFFER2 = 15
    VMWARE1 = 127
    CARCONNECTIVITY = 128
    ENDOFCONTINOUSUPDATES = 150
    SERVERSTATE = 173
    SERVERFENCE = 248
    OLIVECALLCONTROL = 249
    XVPSERVERMESSAGE = 250
    TIGHT = 252
    GIISERVERMESSAGE = 253
    VMWARE2 = 254
    QEMUSERVERMESSAGE = 255

SERVER_PACKET_TYPE_STR = {}
for e in RFBServerMessage:
    SERVER_PACKET_TYPE_STR[e.value] = e.name

class RFBEncoding(IntEnum):
    RAW = 0
    COPYRECT = 1
    RRE = 2
    CORRE = 4
    HEXTILE = 5
    ZLIB = 6
    TIGHT = 7
    ZLIBHEX = 8
    TRLE = 15
    ZRLE = 16
    H264 = 20
    JPEG = 21
    JRLE = 22
    VAH264 = 23
    ZRLE2 = 24
    HITACHI_ZYWRLE = 17
    DESKTOPSIZE = -223
    LASTRECT = -224
    CURSOR = -239
    XCURSOR = -240
    QEMU_POINTER = -257
    QEMU_KEY = -258
    QEMU_AUDIO = -259
    TIGHT_PNG = -260
    GII = -305
    DESKTOPNAME = -307
    EXTENDEDDESKTOPSIZE = -308
    XVP = -309
    FENCE = -312
    CONTINUOUSUPDATES = -313
    CURSORWITHALPHA = -314
    VA_H264 = 0x48323634

    #-23 to -32    JPEG Quality Level Pseudo-encoding
    #-247 to -256    Compression Level Pseudo-encoding
    #-412 to -512    JPEG Fine-Grained Quality Level Pseudo-encoding
    #-763 to -768    JPEG Subsampling Level Pseudo-encoding

ENCODING_STR = {}
for e in RFBEncoding:
    ENCODING_STR[e.value] = e.name


class RFBAuth(IntEnum):
    INVALID = 0
    NONE = 1
    VNC = 2
    TIGHT = 16
    VeNCrypt = 19

AUTH_STR = {
    RFBAuth.INVALID     : "Invalid",
    RFBAuth.NONE        : "None",
    RFBAuth.VNC         : "VNC",
    RFBAuth.TIGHT       : "Tight",
    5                   : "RA2",
    6                   : "RA2ne",
    17                  : "Ultra",
    18                  : "TLS",
    RFBAuth.VeNCrypt    : "VeNCrypt",
    20                  : "SASL",
    21                  : "MD5",
    22                  : "xvp",
    }
for i in (3, 4):
    AUTH_STR[i] = "RealVNC"
for i in range(7, 16):
    AUTH_STR[i] = "RealVNC"
for i in range(128, 255):
    AUTH_STR[i] = "RealVNC"
for i in range(30, 35):
    AUTH_STR[i] = "Apple"


RFB_KEYNAMES = {
    0xff08      : "BackSpace",
    0xff09      : "Tab",
    0xff0d      : "Return",
    0xff1b      : "Escape",
    0xff63      : "Insert",
    0xffff      : "Delete",
    0xff50      : "Home",
    0xff57      : "End",
    0xff55      : "PageUp",
    0xff56      : "PageDown",
    0xff51      : "Left",
    0xff52      : "Up",
    0xff53      : "Right",
    0xff54      : "Down",
    0xffe1      : "Shift_L",
    0xffe2      : "Shift_R",
    0xffe3      : "Control_L",
    0xffe4      : "Control_R",
    0xffe7      : "Meta_L",
    0xffe8      : "Meta_R",
    0xffe9      : "Alt_L",
    0xffea      : "Alt_R",
    0x20        : "space",
    0x60        : "grave",
    0x2d        : "minus",
    0x3d        : "equal",
    0x2b        : "plus",
    0x5f        : "underscore",
    0xac        : "notsign",
    0x21        : "exclam",
    0x22        : "quotedbl",
    0x24        : "dollar",
    0x5e        : "asciicircum",
    0x26        : "ampersand",
    0x2a        : "asterisk",
    0x28        : "parenleft",
    0x29        : "parenright",
    0x5c        : "backslash",
    0x7c        : "bar",
    0x5b        : "bracketleft",
    0x5d        : "bracketright",
    0x7b        : "braceleft",
    0x7d        : "braceright",
    0x3b        : "semicolon",
    0x27        : "apostrophe",
    0x23        : "numbersign",
    0x3a        : "colon",
    0x40        : "at",
    0x7e        : "asciitilde",
    0x2c        : "comma",
    0x2e        : "period",
    0x2f        : "slash",
    0x3c        : "less",
    0x3e        : "greater",
    0x3f        : "question",
    0xffb0      : "KP_0",
    0xffb1      : "KP_1",
    0xffb2      : "KP_2",
    0xffb3      : "KP_3",
    0xffb4      : "KP_4",
    0xffb5      : "KP_5",
    0xffb6      : "KP_6",
    0xffb7      : "KP_7",
    0xffb8      : "KP_8",
    0xffb9      : "KP_9",
    0xffae      : "KP_Decimal",
    0xffaf      : "KP_Divide",
    0xffaa      : "KP_Multiply",
    0xffad      : "KP_Subtract",
    0xffab      : "KP_Add",
    0xff8d      : "KP_Enter",
    0xff7f      : "Num_Lock",
    0xff9f      : "KP_Delete",
    0xff9e      : "KP_Insert",
    0xff9c      : "KP_End",
    0xff9b      : "KP_Down",
    #0xffb3      : "KP_Next",
    0xff96      : "KP_Left",
    0xff9d      : "KP_Begin",
    0xff98      : "KP_Right",
    0xff95      : "KP_Home",
    0xff97      : "KP_Up",
    0xff9a      : "KP_Prior",
    0xff14      : "Scroll_Lock",
    0xff13      : "Pause",
    0x1008ff26  : "XF86Back",
    0x1008ff27  : "XF86Forward",
    0x1008ff18  : "XF86HomePage",
    }

for i in range(1, 13):
    RFB_KEYNAMES[0xffbe+(i-1)] = "F%i" % i

RFB_KEYS = {}
for keysym, name in RFB_KEYNAMES.items():
    RFB_KEYS[name.lower()] = keysym
