#include <stdio.h>

#include "ime.h"
#include "chewing_im.h"

#if 0
#define KB_DEFAULT_STR       "¼Ð·ÇÁä½L"
#define KB_HSU_STR           "³\¤óÁä½L"
#define KB_IBM_STR           "IBM Áä½L"
#define KB_GIN_YIEH_STR      "ºë·~Áä½L"
#define KB_ET_STR            "­Ê¤ÑÁä½L"
#define KB_ET26_STR          "­Ê¤Ñ26Áä½L"
#define KB_DVORAK_STR        "Dvorak Áä½L"
#define KB_DVORAK_HSU_STR    "Dvorak + ³\¤óÁä½L"

#define CHEWING_KEYMAP_MODE_STR     "Áä½L±Æ¦C¤è¦¡¡G"
#endif

#define CHEWING_KEYMAP_MODE_ID      0

char kb_default_str[] = { 0xbc,0xd0,0xb7,0xc7,0xc1,0xe4,0xbd,0x4c,0 };
char kb_hsu_str[] = { 0xb3,0x5c,0xa4,0xf3,0xc1,0xe4,0xbd,0x4c,0 };
char kb_ibm_str[] = { 0x49,0x42,0x4d,0x20,0xc1,0xe4,0xbd,0x4c,0 };
char kb_gin_yieh_str[] = { 0xba,0xeb,0xb7,0x7e,0xc1,0xe4,0xbd,0x4c,0 };
char kb_et_str[] = { 0xad,0xca,0xa4,0xd1,0xc1,0xe4,0xbd,0x4c,0 };
char kb_et26_str[] = { 0xad,0xca,0xa4,0xd1,0x32,0x36,0xc1,0xe4,0xbd,0x4c,0 };
char kb_dvorak_str[] = { 0x44,0x76,0x6f,0x72,0x61,0x6b,0x20,0xc1,0xe4,0xbd,0x4c,0 };
char kb_dvorak_hsu_str[] = { 0x44,0x76,0x6f,0x72,0x61,0x6b,0x20,0x2b,0x20,0xb3,0x5c,0xa4,0xf3,0xc1,0xe4,0xbd,0x4c,0 };
char chewing_keymap_mode_str[] = { 0xc1,0xe4,0xbd,0x4c,0xb1,0xc6,0xa6,0x43,0xa4,0xe8,0xa6,0xa1,0xa1,0x47,0 };

char **KeymappingOptions = NULL;

ImePropertyRec chewing_options[] = {
    {CHEWING_KEYMAP_MODE_ID, ENCODE_BIG5, "/keymapping",
     chewing_keymap_mode_str, NULL, ImeProperty_Selection, {0, 0}, 0},
};

ImePropertyListRec chewing_optionlist = {
    sizeof(chewing_options) / sizeof(ImePropertyRec),
    chewing_options
};

extern ImmServices imm_services;

char *chewing_get_keymapping_str(int kb_type)
{
    int i, buf_len;
    char pho[16]; 
    char key[2];
    int  ret;
    int  searchTimes = 0;
    char *keymapping_str = NULL;

    char *valid_keys = "abcdefghijklmnopqrstuvwxyz0123456789-=[]\\;',./";

    char *kb_strs[KB_TYPE_NUM + 1] = {
        kb_default_str,
        kb_hsu_str,
        kb_ibm_str,
        kb_gin_yieh_str,
        kb_et_str,
        kb_et26_str,
        kb_dvorak_str,
        kb_dvorak_hsu_str,
        NULL,
    };

    if (kb_type < 0 || kb_type >= KB_TYPE_NUM - 1)
        return (NULL);

    buf_len = strlen(kb_strs[kb_type]);
    for (i = 0; i < strlen(valid_keys); i++) {
        memset (pho, 0, 6);
        key[0] = *(valid_keys + i);
        key[1] = 0;
        searchTimes = 1;
        ret = Key2Pho(pho, key, kb_type, searchTimes);
        if (ret == 0)
            continue;

        buf_len += strlen(pho) + 2;
    }

    keymapping_str = (char *)calloc (buf_len + 3, sizeof (char));
    if (keymapping_str == NULL)
        return (NULL);

    snprintf(keymapping_str, buf_len, "%s", kb_strs[kb_type]);

    for (i = 0; i < strlen(valid_keys); i++) {
        char ch = *(valid_keys + i);
        char *format_str = "|%c%s";
        char key_str[256];

        memset (pho, 0, 16);
        key[0] = ch;
        key[1] = 0;

        searchTimes = 1;
        ret = Key2Pho(pho, key, kb_type, searchTimes);
        if (ret == 0 || pho[0] == 0)
            continue;

        if (ch == '/' || ch == '|')
            format_str = "|\\%c%s";

        snprintf(key_str, 256, format_str, ch, pho);
        strncat(keymapping_str, key_str, buf_len);
    }

    DEBUG_printf("keymapping_str: %s\n", keymapping_str);
    return (keymapping_str);
}

ImeResult chewing_Init_Ime_Properties(ImeInfoRec * chewing_info)
{
    int i, num_keymap;

    if (chewing_info == NULL)
	return (IME_FAIL);

    DEBUG_printf("chewing_Init_Ime_Properties\n");

    if (KeymappingOptions == NULL) {
        KeymappingOptions = (char **) calloc (KB_TYPE_NUM + 1, sizeof (char *));
        if (KeymappingOptions == NULL)
            return (IME_FAIL);

        /* "KB_TYPE_NUM - 1" means we disable KB_HANYU_PINYING for libchewing 0.2.5 */
        num_keymap = 0;
        for (i = 0; i < KB_TYPE_NUM - 1; i++) {
            char *keymapping_str;
            keymapping_str = (char *)chewing_get_keymapping_str(i);
            if (keymapping_str) {
                KeymappingOptions[num_keymap++] = keymapping_str;
            }
        }

        if (num_keymap == 0)
            return (IME_FAIL);
    }

    chewing_options[CHEWING_KEYMAP_MODE_ID].range.multiString_range = KeymappingOptions;
    chewing_options[CHEWING_KEYMAP_MODE_ID].value.int_value = 0;

    chewing_info->pl = (ImePropertyListRec *) (&chewing_optionlist);

    return (IME_OK);
}

ImeResult chewing_Destroy_Ime_Properties(ImeInfoRec * chewing_info)
{
    int i;

    if (KeymappingOptions != NULL) {
        for (i = 0; i < KB_TYPE_NUM; i++) {
            if (KeymappingOptions[i])
                free ((char *) KeymappingOptions[i]);
        }
        free ((char *)KeymappingOptions);
    }

    return (IME_OK);
}

ImeResult chewing_Set_Ime_Properties(ImeInputContext ic,
				     chewing_session_t * chewing_session)
{
    int i;
    ImePropertyListRec *pl;
    ImePropertyRec *pi;

    DEBUG_printf("chewing_Set_Ime_Properties\n");

    if (chewing_session == NULL)
	return (IME_FAIL);

    chewing_session->keyboard_type = KB_DEFAULT;

    pl = imm_services->ImmGetPropertyList(ic);
    if (pl != NULL && pl->count > 0 && pl->properties != NULL) {
	for (i = 0; i < pl->count; i++) {
	    pi = &(pl->properties[i]);
	    switch (pi->id) {
	    case CHEWING_KEYMAP_MODE_ID:
		chewing_session->keyboard_type = pi->value.int_value;
		break;
	    }
	}
    }

    return (IME_OK);
}
