/*
  object.c
*/

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

/********************************************************************************
			       internal services
********************************************************************************/

static IIIMF_status
get_imvalues(
    IIIMCF_handle_rec *ph,
    int num,
    IIIMP_card16 *pattribids,
    IIIMP_message **ppmes
)
{
    IIIMF_status st;
    IIIMP_card16_list *pc16;
    IIIMP_message *pmes;

    pc16 = iiimp_card16_list_new(ph->data_s, num, pattribids);
    if (!pc16) return IIIMF_STATUS_MALLOC;
    pmes = iiimp_getimvalues_new(ph->data_s, ph->im_id, pc16);
    if (!pmes) {
	iiimp_card16_list_delete(ph->data_s, pc16);
	return IIIMF_STATUS_MALLOC;
    }
    st = iiimcf_request_message(ph, pmes, NULL, IM_GETIMVALUES_REPLY, ppmes);

    return st;
}

static IIIMCF_downloaded_object_rec*
register_downloaded_object(
    IIIMCF_handle_rec *ph,
    const IIIMCF_object_descriptor *pod,
    IIIMP_imattribute *pimattr
)
{
    IIIMP_string *pimstr;
    IIIMCF_downloaded_object_rec *po;

    for (po = ph->pdownloaded_objs; po; po = po->pnext) {
	if (po->pod == pod) return po;
    }

    po = (IIIMCF_downloaded_object_rec*) malloc(sizeof(*po));
    if (!po) return NULL;
    memset(po, 0, sizeof(*po));
    po->pod = pod;

    switch (pod->predefined_id) {
      case IIIMP_IMATTRIBUTE_CHARACTER_CONVERSION_DEFINITION_RULE:
       pimstr = pimattr->value.ccdef->contents;
       po->v.str = iiimcf_make_string(pimstr->ptr, pimstr->len);
       if (!po->v.str) {
	   free(po);
	   return NULL;
       }
       break;

      case IIIMP_IMATTRIBUTE_BINARY_GUI_OBJECT:
      case IIIMP_IMATTRIBUTE_BINARY_LIGHT_WEIGHT_ENGINE_OBJECT:
      case IIIMP_IMATTRIBUTE_SCRIPT_GUI_OBJECT:
      case IIIMP_IMATTRIBUTE_SCRIPT_LIGHT_WEIGHT_ENGINE_OBJECT:
       pimstr = pimattr->value.binaryfile_object->object;
       po->v.str = iiimcf_make_string(pimstr->ptr, pimstr->len);
       if (!po->v.str) {
	   free(po);
	   return NULL;
       }
       break;

      case IIIMP_IMATTRIBUTE_JAR_GUI_OBJECT:
      case IIIMP_IMATTRIBUTE_JAR_LIGHT_WEIGHT_ENGINE_OBJECT:
      default:
       /* Nothing to do with it!
	  Treat it as an invalid object. */
       break;
    }
    po->pnext = ph->pdownloaded_objs;
    ph->pdownloaded_objs = po;

    return po;
}

void
iiimcf_delete_all_downloaded_objects(
    IIIMCF_handle_rec *ph
)
{
    IIIMCF_downloaded_object_rec *po, *po2;

    for (po = ph->pdownloaded_objs; po; po = po2) {
	po2 = po->pnext;
	switch (po->pod->predefined_id) {
	  case IIIMP_IMATTRIBUTE_BINARY_GUI_OBJECT:
	  case IIIMP_IMATTRIBUTE_BINARY_LIGHT_WEIGHT_ENGINE_OBJECT:
	  case IIIMP_IMATTRIBUTE_SCRIPT_GUI_OBJECT:
	  case IIIMP_IMATTRIBUTE_SCRIPT_LIGHT_WEIGHT_ENGINE_OBJECT:
	   if (po->v.str) free(po->v.str);
	   break;
	}
	free(po);
    }
    
    return;
}

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

IIIMF_status
iiimcf_get_downloaded_object_descriptor(
    IIIMCF_downloaded_object object,
    const IIIMCF_object_descriptor **ppdesc
)
{
    IIIMCF_downloaded_object_rec *po = (IIIMCF_downloaded_object_rec*) object;

    *ppdesc = po->pod;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_downloaded_object_filename(
    IIIMCF_downloaded_object object,
    const IIIMP_card16 **pfilename
)
{
    IIIMCF_downloaded_object_rec *po = (IIIMCF_downloaded_object_rec*) object;

    switch (po->pod->predefined_id) {
      case IIIMP_IMATTRIBUTE_BINARY_GUI_OBJECT:
      case IIIMP_IMATTRIBUTE_BINARY_LIGHT_WEIGHT_ENGINE_OBJECT:
      case IIIMP_IMATTRIBUTE_SCRIPT_GUI_OBJECT:
      case IIIMP_IMATTRIBUTE_SCRIPT_LIGHT_WEIGHT_ENGINE_OBJECT:
       *pfilename = po->v.str;
       break;

      default:
       return IIIMF_STATUS_ARGUMENT;
    }

    return IIIMF_STATUS_SUCCESS;
}

#if 0
IIIMF_status
iiimcf_get_object_binary(
    IIIMCF_downloaded_object object,
    const IIIMP_card8 **ppbinary
)
{
    /* Currently, there is no supported
       objects that has binary data. */
    return IIIMF_STATUS_SUCCESS;
}
#endif

IIIMF_status
iiimcf_get_downloaded_objects(
    IIIMCF_handle handle,
    int num_objs,
    const IIIMCF_object_descriptor **ppdesc,
    IIIMCF_downloaded_object *pobjs
)
{
    IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle;
    IIIMF_status st;
    IIIMP_card16 *pattribids;
    IIIMP_imattribute *pimattr;
    IIIMCF_downloaded_object_rec *po;
    IIIMP_message *pmes;
    int i;

    pattribids = (IIIMP_card16*) malloc(sizeof(*pattribids) * num_objs);
    if (!pattribids) return IIIMF_STATUS_MALLOC;

    for (i = 0; i < num_objs; i++) {
	pattribids[i] = ppdesc[i]->dynamic_id;
    }

    st = get_imvalues(ph, num_objs, pattribids, &pmes);
    free(pattribids);
    if (st != IIIMF_STATUS_SUCCESS) return st;

    st = IIIMF_STATUS_SUCCESS;
    pimattr = pmes->v.getimvalues_reply.attr_list;
    for (i = 0; i < num_objs; i++) {
	if (!pimattr) {
	    st = IIIMF_STATUS_FAIL;
	    break;
	}
	if (pimattr->id_dyn !=  ppdesc[i]->dynamic_id) {
	    st = IIIMF_STATUS_FAIL;
	    break;
	}
	ASSERT(pimattr->id_pre == ppdesc[i]->predefined_id);
	po = register_downloaded_object(ph, ppdesc[i], pimattr);
	if (!po) {
	    st = IIIMF_STATUS_MALLOC;
	    break;
	}
	pobjs[i] = (IIIMCF_downloaded_object) po;
	pimattr = pimattr->next;
    }

    iiimp_message_delete(ph->data_s, pmes);
    return st;
}

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