#include "hvisdef_prj.h"
#include "cpgui.h"

static char *_wchar2char(WCHAR *text) {
    char *result = NULL;
    int length = console_w2c(NULL, text, 0);
    if (!length) {
	return NULL;
    }
    result = (char *)malloc(length);
    if (!result) {
	return NULL;
    }
    if (!console_w2c(result, text, length)) {
	free(result);
	return NULL;
    }
    return result;
}

DWORD hvisdef_display_question(THVDefContext * info)
{
    WCHAR *tmp = NULL;
    DWORD err = (DWORD)SCARD_W_CANCELLED_BY_USER;
    DWORD errFn;
    const WCHAR *NEW_LINE = L"\r\n";
    CRYPTOAPI_MESSAGE_WND_CONFIG_EX data = { 0 };
    size_t len = 0;
    // ограничение в 90% (115K) от допустимой длины аргумента (128K)
    enum Consts { HVIS_ARG_MAX_LEN = 117760, UTF8_MULTIBYTE_SIGN = 0xC0, UTF8_ONEBYTE_SIGN = 0x80 };
    const char *ending = "...\r\n< Data is too large >\r\n< for complete visualization >";

    data.parent = info->parent;
    data.language = info->language;
    data.buttons = CRYPTOAPI_MESSAGE_BTN_OK | CRYPTOAPI_MESSAGE_BTN_CANCEL;
    data.header = _wchar2char(info->header);
    if (!data.header && info->header) {
	goto done;
    }
    if (info->frame_header) {
	len = wcslen(info->frame_header);
    }
    len += wcslen(NEW_LINE);
    if (info->window_str) {
	len += wcslen(info->window_str);
    }
    if (len == 0) {
	goto done;
    }
    tmp = (WCHAR *)calloc((len + 1), sizeof(WCHAR));
    if (!tmp) {
	goto done;
    }
    if (info->frame_header) {
	wcscpy(tmp, info->frame_header);
    }
    wcscat(tmp, NEW_LINE);
    if (info->window_str) {
	wcscat(tmp, info->window_str);
    }
    data.text = _wchar2char(tmp);
    if (!data.text && tmp) {
	goto done;
    }
    if (strlen(data.text) > (HVIS_ARG_MAX_LEN + strlen(ending) + 1)) {
	int pos = HVIS_ARG_MAX_LEN;
	// если попали на многобайтовый символ, вернемся к его началу
	while ( ((data.text[pos] & UTF8_MULTIBYTE_SIGN) != UTF8_MULTIBYTE_SIGN) &&
		((data.text[pos] & UTF8_ONEBYTE_SIGN) != 0) )
	{
	    pos--;
	}
	data.text[pos] = '\0';
	strcat(data.text, ending);
    }
    errFn = CPDisplayMessageEx(&data);
    if (errFn) {
	err = errFn;
	goto done;
    }

    err = NO_ERROR;
done:
    free(data.text);
    free(data.header);
    free(tmp);
    return err;
}
