/*
  trigger.c
*/

#include "iiimcfint.h"

IIIMF_status
iiimcf_receive_trigger_notify(
    IIIMCF_context_rec *pc,
    int flag
)
{
    IIIMCF_event event;
    IIIMF_status st;

    if (flag && !IIIMCF_IS_ENABLED(pc, IIIMCF_CONTEXT_CONVERSION_MODE)) {
	IIIMCF_SET_STATE(pc, IIIMCF_CONTEXT_CONVERSION_MODE);
	IIIMCF_SET_STATE_CHANGE(pc, IIIMCF_STATE_CONVERSION_MODE_CHANGED);

	st = iiimcf_create_trigger_notify_event(1, &event);
	if (st != IIIMF_STATUS_SUCCESS) return st;
	return iiimcf_store_event(pc, (IIIMCF_event_rec*) event);
    } else if (!flag && IIIMCF_IS_ENABLED(pc, IIIMCF_CONTEXT_CONVERSION_MODE)) {
	IIIMCF_RESET_STATE(pc, IIIMCF_CONTEXT_CONVERSION_MODE);
	IIIMCF_SET_STATE_CHANGE(pc, IIIMCF_STATE_CONVERSION_MODE_CHANGED);

	st = iiimcf_create_trigger_notify_event(0, &event);
	if (st != IIIMF_STATUS_SUCCESS) return st;
	return iiimcf_store_event(pc, (IIIMCF_event_rec*) event);
    }

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_receive_hotkey_notify(
    IIIMCF_context_rec *pc
)
{
    IIIMCF_event event;
    IIIMF_status st;

    st = iiimcf_create_hotkey_notify_event(&event);
    if (st != IIIMF_STATUS_SUCCESS) return st;
    return iiimcf_store_event(pc, (IIIMCF_event_rec*) event);
}

IIIMF_status
iiimcf_forward_trigger_notify(
    IIIMCF_context_rec *pc,
    int flag
)
{
    IIIMF_status st;
    IIIMCF_handle_rec *ph = pc->ph;
    IIIMP_data_s *pds = ph->data_s;
    IIIMP_message *pmes;

    pmes = iiimp_trigger_notify_new(pds, ph->im_id, pc->ic_id, flag ? 0 : 1);
    if (!pmes) {
	return IIIMF_STATUS_MALLOC;
    }

    st = iiimcf_receive_trigger_notify(pc, flag);
    if (st != IIIMF_STATUS_SUCCESS) return st;

    st = iiimcf_request_message(ph, pmes, pc, IM_TRIGGER_NOTIFY_REPLY, NULL);

    return st;
}

IIIMF_status
iiimcf_forward_hotkey_notify(
    IIIMCF_context_rec *pc,
    int hotkey_id,
    int ikev
)
{
    IIIMF_status st;
    IIIMCF_handle_rec *ph = pc->ph;
    IIIMP_data_s *pds = ph->data_s;
    IIIMP_message *pmes;

    pmes = iiimp_hotkey_notify_new(pds, ph->im_id, pc->ic_id, hotkey_id, ikev);
    if (!pmes) {
	return IIIMF_STATUS_MALLOC;
    }

    st = iiimcf_receive_hotkey_notify(pc);
    if (st != IIIMF_STATUS_SUCCESS) return st;

    st = iiimcf_request_message(ph, pmes, pc, IM_HOTKEY_NOTIFY_REPLY, NULL);

    return st;
}

IIIMF_status
iiimcf_process_trigger_keyevent(
    IIIMCF_context_rec *pc,
    IIIMCF_keyevent *pkev
)
{
    int i, n;
    IIIMCF_keyevent *pkevl;
    IIIMF_status st = IIIMF_STATUS_SUCCESS;

    if (IIIMCF_IS_ENABLED(pc, IIIMCF_CONTEXT_CONVERSION_MODE)) {
	n = pc->ph->num_off_keys;
	pkevl = pc->ph->poff_keys;
	for (i = 0; i < n; i++, pkevl++) {
	    if (IIIMCF_IS_KEYEVENT_EQUAL(*pkev, *pkevl)) {
		st = iiimcf_forward_trigger_notify(pc, 0);
		return st;
	    }
	}
    } else {
	n = pc->ph->num_on_keys;
	pkevl = pc->ph->pon_keys;
	for (i = 0; i < n; i++, pkevl++) {
	    if (IIIMCF_IS_KEYEVENT_EQUAL(*pkev, *pkevl)) {
		st = iiimcf_forward_trigger_notify(pc, 1);
		return st;
	    }
	}
    }
    return IIIMF_STATUS_NOT_TRIGGER_KEY;
}

IIIMF_status
iiimcf_process_hotkey_keyevent(
    IIIMCF_context_rec *pc,
    IIIMCF_keyevent *pkev
)
{
    int found, i, j, k, m, n, hotkey_id, sflag, aflag, ikev;
    IIIMCF_keyevent *pkevl;
    IIIMF_status st = IIIMF_STATUS_SUCCESS;

    /* some older version of IIIMSF sends protocol version 3,
     * but not supported hotkey.
     */
    if (!pc->ph->phk_profile || pc->ph->curr_profile_id == -1)
      return iiimcf_process_trigger_keyevent(pc, pkev);

    k = 0;
    found = 0;
    while (k < pc->ph->num_of_hkprofiles) {
      if (pc->ph->phk_profile[k].profile_id == pc->ph->curr_profile_id) {
	found = 1;
	break;
      }
      k++;
    }
    if (found == 0)
      /* no valid hotkey profile is found, so use trigger key event */
      return iiimcf_process_trigger_keyevent(pc, pkev);

    m = pc->ph->phk_profile[k].num_hotkeys;
    for (i = 0; i < m; i++) {
	pkevl = pc->ph->phk_profile[k].phot_keys[i].keys;
	n = pc->ph->phk_profile[k].phot_keys[i].nkeys;
	for (j = 0; j < n; j++, pkevl++) {
	    if (IIIMCF_IS_KEYEVENT_EQUAL(*pkev, *pkevl)) {
		hotkey_id = pc->ph->phk_profile[k].phot_keys[i].hotkey_id;
		sflag = pc->ph->phk_profile[k].phot_keys[i].state_flag;
		aflag = pc->ph->phk_profile[k].phot_keys[i].action_flag;
		ikev = j;
  
		if (IIIMCF_IS_ENABLED(pc, IIIMCF_CONTEXT_CONVERSION_MODE)) { /* Event Forwarding ON */
		    if (!sflag && !aflag) { 
			st = iiimcf_forward_trigger_notify(pc, 0);
			return st;
		    } else if (!sflag && aflag) {
			IIIMCF_SET_STATE(pc, IIIMCF_CONTEXT_CONVERSION_MODE);
			IIIMCF_SET_STATE_CHANGE(pc, IIIMCF_STATE_CONVERSION_MODE_CHANGED);
			st = iiimcf_forward_hotkey_notify(pc, hotkey_id, ikev);
			return st;
		    } else {
			return IIIMF_STATUS_NOT_TRIGGER_KEY;
		    }
		} else { /* Event Forwarding OFF */
		    if (!sflag) { /* if HOTKEY is valid */
			if (aflag) { /* Action flag is Forward ON */
			    IIIMCF_SET_STATE(pc, IIIMCF_CONTEXT_CONVERSION_MODE);
			    IIIMCF_SET_STATE_CHANGE(pc, IIIMCF_STATE_CONVERSION_MODE_CHANGED);
			    st = iiimcf_forward_hotkey_notify(pc, hotkey_id, ikev);
			    return st;
			}
		    }
		} 
	    }
	}
    }
    /* If it is not a HOTKEY */
    st = iiimcf_process_trigger_keyevent(pc, pkev);
    return st;
}

/********************************************************************************
			            APIs
********************************************************************************/

IIIMF_status
iiimcf_create_trigger_notify_event(
    int flag,
    IIIMCF_event *pevent
)
{
    IIIMCF_event_rec *pe;

    pe = iiimcf_make_event(IIIMCF_EVENT_TYPE_TRIGGER_NOTIFY);
    if (!pe) return IIIMF_STATUS_MALLOC;

    if (flag)
	pe->v.number = 1;
    else
	pe->v.number = 0;

    *pevent = pe;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_create_hotkey_notify_event(
    IIIMCF_event *pevent
)
{
    IIIMCF_event_rec *pe;

    pe = iiimcf_make_event(IIIMCF_EVENT_TYPE_HOTKEY_NOTIFY);
    if (!pe) return IIIMF_STATUS_MALLOC;

    *pevent = pe;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_trigger_notify_flag(
    IIIMCF_event event,
    int *pflag
)
{
    IIIMCF_event_rec *pe = (IIIMCF_event_rec*) event;

    if (pe->type != IIIMCF_EVENT_TYPE_TRIGGER_NOTIFY)
	return IIIMF_STATUS_FAIL;

    *pflag = pe->v.number;
    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_current_conversion_mode(
    IIIMCF_context context,
    int *pflag
)
{
    IIIMCF_context_rec *pc = (IIIMCF_context_rec*) context;

    if (IIIMCF_IS_ENABLED(pc, IIIMCF_CONTEXT_CONVERSION_MODE)) {
	*pflag = 1;
    } else {
	*pflag = 0;
    }

    return IIIMF_STATUS_SUCCESS;
}

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