#include <qdatetime.h>
#include <qapplication.h>
#include "IIIMQKeyEvent.hh"
#include "IIIMPreedit.hh"
#include "IIIMLineEdit.hh"

IIIMPreeditWidget*
IIIMLineEdit::get_preedit()
{
    if (ppw) return ppw;
    ppw = new IIIMPreeditWidget(get_context(), this);
    return ppw;
}

IIIMStatusWidget*
IIIMLineEdit::get_status()
{
    if (psw) return psw;

    psw = new IIIMStatusWidget(get_context(),
			       NULL, NULL,
			       Qt::WStyle_Customize
			       | Qt::WStyle_NoBorder
			       | Qt::WX11BypassWM
			       | Qt::WStyle_StaysOnTop);
    psw->place(this, IIIMStatusWidget::BOTTOM_RIGHT);
    connect(this, SIGNAL(ref_changed()), psw, SLOT(ref_change()));
    return psw;
}

void
IIIMLineEdit::resizeEvent(
    QResizeEvent *pre
)
{
    emit ref_changed();
    QLineEdit::resizeEvent(pre);
    return;
}

void
IIIMLineEdit::moveEvent(
    QMoveEvent *pme
)
{
    emit ref_changed();
    QLineEdit::moveEvent(pme);
    return;
}

IIIMLookupChoiceWidget*
IIIMLineEdit::get_lookup_choice()
{
    if (plw) return plw;

#if 1
    plw = new IIIMLookupChoiceWidget(get_context(), NULL, NULL,
				     Qt::WStyle_Customize
				     | Qt::WX11BypassWM
    );
#else
    plw = new IIIMLookupChoiceWidget(get_context(), NULL, NULL);
#endif

    return plw;
}

IIIMCF_language
IIIMLineEdit::get_language(
    const char *id
)
{
    IIIMF_status st;
    IIIMCF_language *plangs;
    const char *id2;
    int i, n;
    st = iiimcf_get_supported_languages(handle, &n, &plangs) ;
    if (st != IIIMF_STATUS_SUCCESS) return NULL;
    for (i = 0; i < n; i++) {
	iiimcf_get_language_id(plangs[i], &id2);
	if (strcmp(id2, id) == 0) return plangs[i];
    }
    return NULL;
}

void
IIIMLineEdit::toggle_im(
    IIIMCF_context c,
    bool flag
)
{
    IIIMF_status st;
    IIIMCF_event ev;

    st = iiimcf_create_trigger_notify_event(flag, &ev);
    if (st != IIIMF_STATUS_SUCCESS) return;
    iiimcf_forward_event(c, ev);
    update_UI();
}

IIIMCF_context
IIIMLineEdit::get_context()
{
    if (!iiimcf_flag) {
	IIIMF_status st;
	IIIMCF_language lang;
	IIIMCF_attr attr = IIIMCF_ATTR_NULL;

	ctx = NULL;
	lang = get_language("ja");
	if (lang) {
	    if (iiimcf_create_attr(&attr) != IIIMF_STATUS_SUCCESS) return ctx;
	    if (iiimcf_attr_put_ptr_value(attr, IIIMCF_ATTR_INPUT_LANGUAGE, lang)
		!= IIIMF_STATUS_SUCCESS) return ctx;
	    st = iiimcf_create_context(handle, attr, &ctx);
	    iiimcf_destroy_attr(attr);
	} else {
	    st = iiimcf_create_context(handle, IIIMCF_ATTR_NULL, &ctx);
	}

	if (st == IIIMF_STATUS_SUCCESS) {
	    iiimcf_flag = 1;
	    toggle_im(ctx, true);
	} else {
	    ctx = NULL;
	}
    }
    return ctx;
}

void
IIIMLineEdit::commit_string()
{
    IIIMF_status st;
    const IIIMP_card16 *pu16;
    IIIMCF_text text;
    
    st = iiimcf_get_committed_text(get_context(), &text);
    if (st != IIIMF_STATUS_SUCCESS) return;
    st = iiimcf_get_text_utf16string(text, &pu16);
    if (st != IIIMF_STATUS_SUCCESS) return;
    QString str = QString::fromUcs2(pu16);
    insert(str);
}

void
IIIMLineEdit::deal_with_iiimcf_event()
{
    IIIMF_status st;
    IIIMCF_event ev;
    IIIMCF_event_type et;

    while ((st = iiimcf_get_next_event(get_context(), &ev))
	   == IIIMF_STATUS_SUCCESS) {
	if (iiimcf_get_event_type(ev, &et) == IIIMF_STATUS_SUCCESS) {
	    if (et == IIIMCF_EVENT_TYPE_KEYEVENT) {
		IIIMCF_keyevent kev;
		QKeyEvent *pqe;

		if (iiimcf_get_keyevent_value(ev, &kev)
		    != IIIMF_STATUS_SUCCESS)
		    continue;
		if (convert_IIIMCF_keyevent_to_QKeyEvent(&kev, 1, &pqe)
		    != IIIMF_STATUS_SUCCESS)
		    continue;
		QLineEdit::keyPressEvent(pqe);
		delete pqe;
		if (convert_IIIMCF_keyevent_to_QKeyEvent(&kev, 0, &pqe)
		    != IIIMF_STATUS_SUCCESS)
		    continue;
		QLineEdit::keyReleaseEvent(pqe);
		delete pqe;
	    }
	}
	iiimcf_ignore_event(ev);
    }
}

void
IIIMLineEdit::update_UI()
{
    int flag;
    if (iiimcf_is_UIstate_changed(get_context(), &flag)
	!= IIIMF_STATUS_SUCCESS)
	return;

    if (flag & IIIMCF_STATE_PREEDIT_CHANGED) {
	int w;
	QRect cr = contentsRect();
	QFontMetrics fm = fontMetrics();

	w = fm.width(displayText().left(cursorPosition()));
	cr.setWidth(w);
	get_preedit()->move(cr.topRight());
	get_preedit()->update_im();
    }
    if (flag & IIIMCF_STATE_STATUS_CHANGED) {
	get_status()->update_im();
    }
    if (flag & IIIMCF_STATE_LOOKUP_CHOICE_CHANGED) {
	get_lookup_choice()->update_im();
    }
    if (flag & IIIMCF_STATE_COMMIT_REQUIRED) {
	commit_string();
    }
    deal_with_iiimcf_event();
}

void
IIIMLineEdit::keyPressEvent(
    QKeyEvent *e
)
{
    IIIMCF_event ev;
    IIIMCF_keyevent kev;

    if (convert_QKeyEvent_to_IIIMCF_keyevent(e, &kev)
	!= IIIMF_STATUS_SUCCESS)
	return QLineEdit::keyPressEvent(e);

    if (iiimcf_create_keyevent(&kev, &ev) != IIIMF_STATUS_SUCCESS)
	return;

    if (iiimcf_forward_event(get_context(), ev) != IIIMF_STATUS_SUCCESS)
	return QLineEdit::keyPressEvent(e);

    update_UI();

    return;
}

IIIMLineEdit::IIIMLineEdit(
    IIIMCF_handle h,
    QWidget *parent,
    const char *name
)
    : QLineEdit(parent, name)
{
    handle = h;
    QString text = QString::fromUtf8("漢字");
    setText(text);
    ppw = NULL;
    psw = NULL;
    plw = NULL;
    iiimcf_flag = 0;
}

IIIMLineEdit::~IIIMLineEdit()
{
    if (ppw) delete ppw;
    if (psw) delete psw;
    if (plw) delete plw;
    if (iiimcf_flag) iiimcf_destroy_context(ctx);
}

int
main(
    int argc,
    char **argv
)
{
    IIIMCF_attr attr;
    IIIMCF_handle h;
    int r;
    QApplication app(argc, argv);
    iiimcf_initialize(IIIMCF_ATTR_NULL);
    iiimcf_create_attr(&attr);
    iiimcf_attr_put_string_value(attr, IIIMCF_ATTR_CLIENT_TYPE,
				 "Qt based sample IIIM client");
    if (iiimcf_create_handle(attr, &h) != IIIMF_STATUS_SUCCESS) {
	return 255;
    }
    iiimcf_destroy_attr(attr);

    IIIMLineEdit *lineedit = new IIIMLineEdit(h);
    app.setMainWidget(lineedit);
    lineedit->show();
    r = app.exec();
    delete lineedit;
    iiimcf_destroy_handle(h);
    iiimcf_finalize();
    return r;
}

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
