/**
 * Utility routines that do not depend on
 * IBusChewingEngine
 */

#include "IBusChewingUtil.h"

/*=====================================
 * Tone
 */
const gchar *toneKeys[] = {"6347", // Default
                           "jfds", // hsu
                           "uiop", // ibm
                           "zaq1", // gin-yieh
                           "4321", // eten
                           "kjfd", // eten26
                           "6347", // dvorak
                           "thdn", // dvorak_hsu
                           "yert", // dachen_26
                           "1234", // hanyu
                           NULL};

/*=====================================
 * Key
 */

KSym key_sym_KP_to_normal(KSym k) {
    if (k < IBUS_KP_0 || k > IBUS_KP_9) {
        switch (k) {
        case IBUS_KP_Multiply:
            return IBUS_asterisk;
        case IBUS_KP_Add:
            return IBUS_plus;
        case IBUS_KP_Separator:
            return IBUS_comma;
        case IBUS_KP_Subtract:
            return IBUS_minus;
        case IBUS_KP_Decimal:
            return IBUS_period;
        case IBUS_KP_Divide:
            return IBUS_slash;
        default:
            return 0;
        }
    }
    return k - IBUS_KP_0 + IBUS_0;
}

const char asciiConst[] = " \0"
                          "!\0"
                          "\"\0"
                          "#\0"
                          "$\0"
                          "%\0"
                          "&\0"
                          "'\0"
                          "(\0"
                          ")\0"
                          "*\0"
                          "+\0"
                          ",\0"
                          "-\0"
                          ".\0"
                          "/\0"
                          "0\0"
                          "1\0"
                          "2\0"
                          "3\0"
                          "4\0"
                          "5\0"
                          "6\0"
                          "7\0"
                          "8\0"
                          "9\0"
                          ":\0"
                          ";\0"
                          "<\0"
                          "=\0"
                          ">\0"
                          "?\0"
                          "@\0"
                          "A\0"
                          "B\0"
                          "C\0"
                          "D\0"
                          "E\0"
                          "F\0"
                          "G\0"
                          "H\0"
                          "I\0"
                          "J\0"
                          "K\0"
                          "L\0"
                          "M\0"
                          "N\0"
                          "O\0"
                          "P\0"
                          "Q\0"
                          "R\0"
                          "S\0"
                          "T\0"
                          "U\0"
                          "V\0"
                          "W\0"
                          "X\0"
                          "Y\0"
                          "Z\0"
                          "[\0"
                          "\\\0"
                          "]\0"
                          "^\0"
                          "_\0"
                          "`\0"
                          "a\0"
                          "b\0"
                          "c\0"
                          "d\0"
                          "e\0"
                          "f\0"
                          "g\0"
                          "h\0"
                          "i\0"
                          "j\0"
                          "k\0"
                          "l\0"
                          "m\0"
                          "n\0"
                          "o\0"
                          "p\0"
                          "q\0"
                          "r\0"
                          "s\0"
                          "t\0"
                          "u\0"
                          "v\0"
                          "w\0"
                          "x\0"
                          "y\0"
                          "z\0"
                          "{\0"
                          "|\0"
                          "}\0"
                          "~\0";

const char *key_sym_get_name(KSym k) {
    switch (k) {
    case 0:
        return "";
    case IBUS_Return:
        return "Return";
    case IBUS_KP_Enter:
        return "KP_Enter";
    case IBUS_Escape:
        return "Escape";
    case IBUS_BackSpace:
        return "BackSpace";
    case IBUS_Delete:
        return "Delete";
    case IBUS_KP_Delete:
        return "KP_Delete";
    case IBUS_space:
        return "space";
    case IBUS_KP_Space:
        return "KP_space";
    case IBUS_Page_Up:
        return "Page_Up";
    case IBUS_KP_Page_Up:
        return "KP_Page_Up";
    case IBUS_Page_Down:
        return "Page_Down";
    case IBUS_KP_Page_Down:
        return "KP_Page_Down";
    case IBUS_Up:
        return "Up";
    case IBUS_KP_Up:
        return "KP_Up";
    case IBUS_Down:
        return "Down";
    case IBUS_KP_Down:
        return "KP_Down";
    case IBUS_Left:
        return "Left";
    case IBUS_KP_Left:
        return "KP_Left";
    case IBUS_Right:
        return "Right";
    case IBUS_KP_Right:
        return "KP_Right";
    case IBUS_Home:
        return "Home";
    case IBUS_KP_Home:
        return "KP_Home";
    case IBUS_End:
        return "End";
    case IBUS_KP_End:
        return "KP_End";
    case IBUS_Tab:
        return "Tab";
    case IBUS_Caps_Lock:
        return "Caps";
    case IBUS_Shift_L:
        return "Shift_L";
    case IBUS_Shift_R:
        return "Shift_R";
    case IBUS_Alt_L:
        return "Alt_L";
    case IBUS_Alt_R:
        return "Alt_R";
    case IBUS_Control_L:
        return "Control_L";
    case IBUS_Control_R:
        return "Control_R";
    case IBUS_Super_L:
        return "Super_L";
    case IBUS_Super_R:
        return "Super_R";
    case IBUS_ISO_Lock:
        return "ISO_Lock";
    case IBUS_ISO_Level3_Lock:
        return "ISO_Level3_Lock";
    case IBUS_ISO_Level3_Shift:
        return "ISO_Level3_Shift";
    case IBUS_KP_0:
        return "KP_0";
    case IBUS_KP_1:
        return "KP_1";
    case IBUS_KP_2:
        return "KP_2";
    case IBUS_KP_3:
        return "KP_3";
    case IBUS_KP_4:
        return "KP_4";
    case IBUS_KP_5:
        return "KP_5";
    case IBUS_KP_6:
        return "KP_6";
    case IBUS_KP_7:
        return "KP_7";
    case IBUS_KP_8:
        return "KP_8";
    case IBUS_KP_9:
        return "KP_9";
    case IBUS_KP_Multiply:
        return "KP_Multiply";
    case IBUS_KP_Add:
        return "KP_Add";
    case IBUS_KP_Separator:
        return "KP_Separator";
    case IBUS_KP_Subtract:
        return "KP_Subtract";
    case IBUS_KP_Decimal:
        return "KP_Decimal";
    case IBUS_KP_Divide:
        return "KP_Divide";
    case IBUS_KP_Insert:
        return "KP_Insert";
    default:
        /* asciiConst only handle the ASCII */
        if (isascii(k) && isprint(k)) {
            return &asciiConst[(k - ' ') * 2];
        }
        if (k <= 0xffff) {
            return "Others";
        }
        break;
    }
    /* Keycode should NOT greater than 0xffff
     * investigate this if it appear in production
     */
    return "WARN";
}

/*=====================================
 * Modifiers
 */

const gchar *modifier_get_string(guint modifier) {
    switch (modifier) {
    case 0:
        return "";
    case IBUS_SHIFT_MASK:
        return "SHIFT";
    case IBUS_LOCK_MASK:
        return "LOCK";
    case IBUS_CONTROL_MASK:
        return "CONTROL";
    case IBUS_MOD1_MASK:
        return "MOD1";
    case IBUS_MOD2_MASK:
        return "MOD2";
    case IBUS_MOD3_MASK:
        return "MOD3";
    case IBUS_MOD4_MASK:
        return "MOD4";
    case IBUS_MOD5_MASK:
        return "MOD5";
    case IBUS_HANDLED_MASK:
        return "HANDLED";
    case IBUS_FORWARD_MASK:
        return "FORWARD";
    case IBUS_SUPER_MASK:
        return "SUPER";
    case IBUS_HYPER_MASK:
        return "HYPER";
    case IBUS_META_MASK:
        return "META";
    case IBUS_RELEASE_MASK:
        return "RELEASE";
    default:
        break;
    }
    return "UNRECOGNIZED_MASK";
}

#define MODIFIER_BUFFER_SIZE 100
const gchar *modifiers_to_string(guint modifier) {
    static gchar modifierBuf[MODIFIER_BUFFER_SIZE];

    g_strlcpy(modifierBuf, "", MODIFIER_BUFFER_SIZE);
    gboolean first = TRUE;
    gint i, mask;

    for (i = 0; i < 32; i++) {
        mask = 1 << i;
        if (modifier & mask) {
            if (first) {
                g_strlcpy(modifierBuf, modifier_get_string(mask),
                          MODIFIER_BUFFER_SIZE);
                first = FALSE;
            } else {
                g_strlcat(modifierBuf, "| ", MODIFIER_BUFFER_SIZE);
                g_strlcat(modifierBuf, modifier_get_string(mask),
                          MODIFIER_BUFFER_SIZE);
            }
        }
    }
    return modifierBuf;
}
