#!/usr/bin/env python

# This script
# (1) loads keysym name and keycode mappings from noVNC/core/input/keysym.js and
# (2) loads keysyn name to atset1 code mappings from keymap files which can be downloadeded from https://github.com/qemu/qemu/blob/master/pc-bios/keymaps
# (3) generates the mappings of keycode and atset1 code
#
# Note: please add language specific mappings if needed.

import os
import sys

keycode_to_x11name = {}
x11name_to_atset1 = {}
layout = ""
result_mappings = {}
js_config = []


def generate_x11name_to_atset1_map(keymap_file):
    # keymap files can be downloadeded from
    # https://github.com/qemu/qemu/blob/master/pc-bios/keymaps
    global layout
    try:
        for c in open(keymap_file):
            if len(c.strip()) == 0:
                continue
            if c.startswith("# quirks section start"):
                # Stop at the quirks section
                break
            if c.startswith("#"):
                if "layout" in c and ":" in c:
                    layout = c.split(":")[1].strip()
                continue
            if "map " in c:
                continue
            values = c.strip().split(" ")
            if len(values) >= 2:
                keyname = 'XK_' + values[0]
                keycode = ' '.join(values[1:]).strip()
                if keyname not in x11name_to_atset1:
                    x11name_to_atset1[keyname] = keycode
                else:
                    print("Duplicated atset1 code for x11name '%s': '%s' and '%s'" % (
                    keyname, x11name_to_atset1[keyname], keycode))

    except IOError:
        print(
            "File '%s' does not exist. \nkeymaps can be downloaded from https://github.com/qemu/qemu/tree/master/pc-bios/keymaps" % keymap_file)
        sys.exit(2)


def generate_keycode_to_x11name():
    for k in open("../core/input/keysym.js"):
        k = k.strip()
        if k.startswith("/") or k.startswith("*"):
            continue
        values = k.split(":")
        if len(values) >= 2:
            keyname = values[0]
            keycode = values[1].strip().split(",")[0].lower()
            keycode_int = int(keycode, 16)
            if str(keycode_int) not in keycode_to_x11name:
                keycode_to_x11name[str(keycode_int)] = keyname


def translate(keysym):
    x11name = keycode_to_x11name[str(keysym)]
    if x11name not in x11name_to_atset1:
        print("Cannot find atset1 code for keysym (%s) / x11name (%s) in keymaps" % (keysym, x11name))
        return "", ""
    atset1 = x11name_to_atset1[x11name]
    values = atset1.split(" ")
    rest = ""
    if len(values) >= 2:
        atset1 = values[0]
        rest = " ".join(values[1:])
    return str(int(atset1, 16)), rest


def add_language_specific_mappings():
    if layout == "jp":
        add_specific_mapping("124", "125", "shift")     # bar


def add_specific_mapping(keycode, atset1, rest):
    result_mappings[keycode] = "%s %s" % (str(atset1).ljust(10), rest)


def generate_js_file(keymap_file):
    generated_filename = keymap_file + "-atset1.js"
    handle = open(generated_filename, "w")
    js_config.append("/* This file is auto-generated by generate-language-keymaps.py\n")
    js_config.append(" * command    : %s\n" % (" ".join(sys.argv)))
    js_config.append(" * layout     : %s\n" % layout)
    js_config.append(" */\n")
    js_config.append("export default {\n")
    for keycode in dict(sorted(list(result_mappings.items()), key=lambda item: int(item[0]))):
        js_config.append("%10s : \"%s\",\n" % ("\"" + str(keycode) + "\"", result_mappings[keycode].strip()))
    js_config.append("}\n")
    for line in js_config:
        handle.write(line)
    handle.close()
    print("Created file %s" % generated_filename)


def main(argv):
    if len(argv) < 1:
        print("Usage:   %s <keymap file>" % (sys.argv[0]))
        sys.exit(1)
    keymap_file = argv[0]
    generate_keycode_to_x11name()
    generate_x11name_to_atset1_map(keymap_file)

    # insert language-specific mappings at beginning
    add_language_specific_mappings()

    for keycode in keycode_to_x11name:
        atset1, rest = translate(keycode)
        if atset1 and keycode not in result_mappings and int(keycode) < 65000:
            result_mappings[keycode] = "%s %s" % (str(atset1).ljust(10), rest)

    generate_js_file(keymap_file)


if __name__ == "__main__":
    main(sys.argv[1:])
