/*
  lookup_choice.c
*/

#include <stdlib.h>
#include <string.h>
#include "iiimcfint.h"

#define IIIMCF_LOOKUP_CHOICE_LABEL_INDEX_SIZE_MAX 32

IIIMF_status
iiimcf_lookup_choice_start(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
)
{
    IIIMCF_lookup_choice_rec *pl = &pc->lookup_choice;
    IIIMP_lookup_choice_start_v *plcs = &pmes->v.lookup_choice_start;

    ASSERT(pmes->opcode == IM_LOOKUP_CHOICE_START);

    pl->masterp = plcs->master;
    pl->choices_per_window = plcs->choice_per_window;
    pl->rows = plcs->rows;
    pl->cols = plcs->columns;
    pl->direction = plcs->direction;
    pl->label_owner = plcs->label_owner;

    pl->enabled_range_start = pl->enabled_range_end = 0;

    IIIMCF_SET_STATE(pc, IIIMCF_CONTEXT_LOOKUP_CHOICE_ENABLED);
    IIIMCF_SET_STATE_CHANGE(pc, IIIMCF_STATE_LOOKUP_CHOICE_CHANGED);
    
    return iiimcf_store_simple_event(pc, IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_START);
}

IIIMF_status
iiimcf_lookup_choice_done(
    IIIMCF_context_rec *pc
)
{
    if (IIIMCF_IS_ENABLED(pc, IIIMCF_CONTEXT_LOOKUP_CHOICE_ENABLED)) {
	IIIMCF_RESET_STATE(pc, IIIMCF_CONTEXT_LOOKUP_CHOICE_ENABLED);
	IIIMCF_SET_STATE_CHANGE(pc, IIIMCF_STATE_LOOKUP_CHOICE_CHANGED);
	return iiimcf_store_simple_event(pc, IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_DONE);
    }

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_update_lookup_choice(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
)
{
    int i, nc, nl;
    int flag, *pflags;
    IIIMF_status st;
    IIIMP_text *pimt;
    IIIMCF_text_rec *ptr;
    IIIMCF_lookup_choice_rec *pl = &pc->lookup_choice;
    IIIMP_lookup_choice_draw_v *plcd = &pmes->v.lookup_choice_draw;
    ASSERT(pmes->opcode == IM_LOOKUP_CHOICE_DRAW);

    st = iiimcf_convert_iiimp_text_to_text(plcd->title, &pl->title);
    if (st != IIIMF_STATUS_SUCCESS) return st;
    for (nc = 0, pimt = plcd->choice; pimt; pimt = pimt->next) nc++;

    if (nc > pl->size) {
	int osize = pl->size;
	int inc = nc - osize;

	ptr = (IIIMCF_text_rec*) realloc(pl->pcandidates, sizeof(*ptr) * nc);
	if (!ptr) return IIIMF_STATUS_MALLOC;
	memset(ptr + osize, 0, sizeof(*ptr) * inc);
	pl->pcandidates = ptr;
	ptr = (IIIMCF_text_rec*) realloc(pl->plabels, sizeof(*ptr) * nc);
	if (!ptr) return IIIMF_STATUS_MALLOC;
	memset(ptr + osize, 0, sizeof(*ptr) * inc);
	pl->plabels = ptr;
	pflags = (int*) realloc(pl->pflags, sizeof(*pflags) * nc);
	if (!pflags) return IIIMF_STATUS_MALLOC;
	memset(pflags + osize, 0, sizeof(*pflags) * inc);
	pl->pflags = pflags;
    }
    for (i = plcd->first, ptr = pl->pcandidates, pflags = pl->pflags, pimt = plcd->choice;
	 pimt; i++, ptr++, pflags++, pimt = pimt->next) {
	st = iiimcf_convert_iiimp_text_to_text(pimt, ptr);
	if (st != IIIMF_STATUS_SUCCESS) return st;
	flag = IIIMCF_LOOKUP_CHOICE_ITEM_ENABLED;
	if (i == plcd->current)
	    flag |= IIIMCF_LOOKUP_CHOICE_SELECTED_ITEM;
	*pflags = flag;
    }
    for (nl = 0, pimt = plcd->index_label; pimt; pimt = pimt->next) nl++;
    if ((pl->masterp != IM_LOOKUP_CHOICE_START_SERVER_IS_MASTER)
	|| (nc != nl)) {
	/* make label */
	int endi = plcd->first + nc;

	for (i = plcd->first, ptr = pl->plabels;
	     i < endi; i++, ptr++) {
	    unsigned char stridx[IIIMCF_LOOKUP_CHOICE_LABEL_INDEX_SIZE_MAX];
	    snprintf(stridx, sizeof(stridx), "%d:", i);
	    st = iiimcf_construct_text_from_UTF8(stridx, ptr);
	}
    } else {
	for (ptr = pl->plabels, pimt = plcd->index_label;
	     pimt; pimt = pimt->next, ptr++) {
	    st = iiimcf_convert_iiimp_text_to_text(pimt, ptr);
	    if (st != IIIMF_STATUS_SUCCESS) return st;
	}
    }
    pl->idx_first = plcd->first;
    pl->idx_last = plcd->last;
    pl->idx_current = plcd->current;
    pl->enabled_range_start = 0;
    if (pl->masterp == IM_LOOKUP_CHOICE_START_CLIENT_IS_MASTER) {
	if (nc > pl->choices_per_window)
	    pl->enabled_range_end = pl->choices_per_window;
	else
	    pl->enabled_range_end = nc;
    } else {
	pl->enabled_range_end = nc;
    }
    pl->size = nc;

    IIIMCF_SET_STATE_CHANGE(pc, IIIMCF_STATE_LOOKUP_CHOICE_CHANGED);

    return iiimcf_store_simple_event(pc, IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_CHANGE);
}

IIIMF_status
iiimcf_process_lookup_choice(
    IIIMCF_context_rec *pc,
    IIIMP_message *pmes
)
{
    IIIMCF_lookup_choice_rec *pl = &pc->lookup_choice;
    IIIMP_lookup_choice_process_v *plcp = &pmes->v.lookup_choice_process;
    ASSERT(pmes->opcode == IM_LOOKUP_CHOICE_PROCESS);

    if (plcp->type == IM_LOOKUP_CHOICE_PROCESS_INDEX) {
	int ridx, ridx_o;

	if (!((plcp->value >= pl->idx_first) || (plcp->value <= pl->idx_last)))
	    return IIIMF_STATUS_SUCCESS;  /* Invalid index.  Simply ignore it. */
	ridx = plcp->value - pl->idx_first;
	if (ridx >= pl->size) 
	    return IIIMF_STATUS_SUCCESS;  /* Invalid index.  Simply ignore it. */
	ridx_o = pl->idx_current - pl->idx_first;
	if ((ridx_o >= 0) && (ridx_o < pl->size)) {
	    pl->pflags[ridx_o] &= ~IIIMCF_LOOKUP_CHOICE_SELECTED_ITEM;
	}
	pl->pflags[ridx] |= IIIMCF_LOOKUP_CHOICE_SELECTED_ITEM;
	pl->idx_current = ridx;
    } else if (plcp->type == IM_LOOKUP_CHOICE_PROCESS_PAGE) {
	int st = pl->enabled_range_start;
	int end = pl->enabled_range_end;
	switch (plcp->value) {
	  case IM_LOOKUP_CHOICE_PROCESS_PAGE_NEXT_PAGE:
	   st += pl->choices_per_window;
	   if (st >= pl->size) return IIIMF_STATUS_SUCCESS; /* ignore */
	   end += pl->choices_per_window;
	   break;
	  case IM_LOOKUP_CHOICE_PROCESS_PAGE_PREV_PAGE:
	   st -= pl->choices_per_window;
	   end -= pl->choices_per_window;
	   if (end <= 0) return IIIMF_STATUS_SUCCESS; /* ignore */
	   break;
	  case IM_LOOKUP_CHOICE_PROCESS_PAGE_FIRST_PAGE:
	   st = 0;
	   end = pl->choices_per_window;
	   break;
	  case IM_LOOKUP_CHOICE_PROCESS_PAGE_LAST_PAGE:
	   st = pl->size - pl->choices_per_window;
	   end = pl->size;
	   break;
	  default:
	   return IIIMF_STATUS_SUCCESS;
	}

	if (st < 0) st = 0;
	else if (st >= pl->size) st = pl->size - 1;

	if (end < 0) end = 0;
	else if (end < st) end = st;
	else if (end > pl->size) end = pl->size;

	pl->enabled_range_start = st;
	pl->enabled_range_end = end;
    } else {
	return IIIMF_STATUS_SUCCESS;
    }
    
    IIIMCF_SET_STATE_CHANGE(pc, IIIMCF_STATE_LOOKUP_CHOICE_CHANGED);

    return iiimcf_store_simple_event(pc, IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_CHANGE);
}

IIIMF_status
iiimcf_get_lookup_choice_size(
    IIIMCF_lookup_choice lookup_choice,
    int *psize,
    int *pindex_of_first_candidate,
    int *pindex_of_last_candidate,
    int *pindex_of_current_candidate
)
{
    IIIMCF_lookup_choice_rec *pl = (IIIMCF_lookup_choice_rec*) lookup_choice;

    *psize = pl->enabled_range_end - pl->enabled_range_start;
    *pindex_of_first_candidate = pl->idx_first;
    *pindex_of_last_candidate = pl->idx_last;
    *pindex_of_current_candidate = pl->idx_current;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_lookup_choice_configuration(
    IIIMCF_lookup_choice lookup_choice,
    int *pchoices_per_window,
    int *pnumber_of_rows,
    int *pnumber_of_columns,
    int *pdirection
)
{
    IIIMCF_lookup_choice_rec *pl = (IIIMCF_lookup_choice_rec*) lookup_choice;

    *pchoices_per_window = pl->choices_per_window;
    *pnumber_of_rows = pl->rows;
    *pnumber_of_columns = pl->cols;
    *pdirection = pl->direction;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_lookup_choice_item(
    IIIMCF_lookup_choice lookup_choice,
    int idx,
    IIIMCF_text *pcandidate,
    IIIMCF_text *plabel,
    int *pflag
)
{
    IIIMCF_lookup_choice_rec *pl = (IIIMCF_lookup_choice_rec*) lookup_choice;

    if (idx < 0) return IIIMF_STATUS_ARGUMENT;
    idx += pl->enabled_range_start;
    if (idx >= pl->enabled_range_end) return IIIMF_STATUS_ARGUMENT;

    *pcandidate = pl->pcandidates + idx;
    *plabel = pl->plabels + idx;
    *pflag = pl->pflags[idx];

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_lookup_choice_title(
    IIIMCF_lookup_choice lookup_choice,
    IIIMCF_text *ptitle
)
{
    IIIMCF_lookup_choice_rec *pl = (IIIMCF_lookup_choice_rec*) lookup_choice;

    *ptitle = &pl->title;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_lookup_choice(
    IIIMCF_context context,
    IIIMCF_lookup_choice *plookup_choice
)
{
    IIIMCF_context_rec *pc = (IIIMCF_context_rec*) context;

    if (IIIMCF_IS_IC_INVALID(pc)) return IIIMF_STATUS_IC_INVALID;
    if ((!IIIMCF_IS_ENABLED(pc, IIIMCF_CONTEXT_LOOKUP_CHOICE_ENABLED))
	|| (!IIIMCF_IS_VALID_LOOKUP_CHOICE(&pc->lookup_choice)))
	return IIIMF_STATUS_NO_LOOKUP_CHOICE;

    *plookup_choice = &pc->lookup_choice;

    return IIIMF_STATUS_SUCCESS;
}

void
iiimcf_destruct_lookup_choice(
    IIIMCF_lookup_choice_rec *pl
)
{
    int i;
    IIIMCF_text_rec *plabels, *pcands;

    iiimcf_destruct_text(&pl->title);
    plabels = pl->plabels;
    pcands = pl->pcandidates;
    for (i = 0; i < pl->size; i++, plabels++, pcands++) {
	iiimcf_destruct_text(plabels);
	iiimcf_destruct_text(pcands);
    }
    free(pl->plabels);
    free(pl->pcandidates);
}

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