/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/

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

#include "v/VObject.h"
#include "v/VgbQueryIndicate.h"
#include "v/vobj_utils.h"

extern "C" {
#include 	"xl.h"
#include	"xlerror.h"

XL_SEXP *
vobj_VgbQueryIndicate(XLISP_ENV *env, XL_SEXP *arg, XLISP_ENV *a, XL_SYM_FIELD *sf);
char * VgbQueryIndicate_get_from_sf(VgbQueryIndicateStatus *,int*,XLISP_ENV*,L_CHAR *,XL_SYM_FIELD *,XL_SEXP*);
VImage *
get_image_from_lchar(XL_SEXP ** retp,XLISP_ENV * env,L_CHAR *,L_CHAR * _img_field);
XL_SEXP *
vobj_get_VgbQueryIndicate(XLISP_ENV * env,XL_SEXP * arg,XLISP_ENV * a,XL_SYM_FIELD * sf);
int
get_flag_VgbQueryIndicate(L_CHAR * fname);

char * VgbQueryIndicate_get_from_sf(
	VgbQueryIndicateStatus * q_sts,
	int* q_flags,
	XLISP_ENV* env,
	L_CHAR * filepath,
	XL_SYM_FIELD * sf,
	XL_SEXP * arg)
{
L_CHAR * d;
XL_SEXP * dd;
XL_SEXP * _ret;
char * ret;
	*q_flags = 0;
	d = get_sf_attribute(sf,l_string(std_cm,"qind.qthFocused"));
	if ( d ) {
		q_sts->qth_focused = atoi(n_string(std_cm,d));
	}
	else {
		q_sts->qth_focused = 0;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.qthSet"));
	if ( d ) {
		dd = eval(env,get_symbol(d));
		if ( get_type(dd) != XLT_PAIR ) {
			ret = "qind.qth.set(1)";
			goto err;
		}
		q_sts->qth_set = sexp_to_q_thread(dd);
		if ( q_sts->qth_set == 0 ) {
			ret = "qind.qth.set(2)";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_QTH_SET;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.qthDelete"));
	if ( d ) {
		dd = eval(env,get_symbol(d));
		if ( get_type(dd) != XLT_PAIR ) {
			ret = "qind.qth.delete(1)";
			goto err;
		}
		q_sts->qth_delete = sexp_to_q_thread(dd);
		if ( q_sts->qth_delete == 0 ) {
			ret = "qind.qth.delete(2)";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_QTH_DELETE;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.qthReplace"));
	if ( d ) {
		dd = eval(env,get_symbol(d));
		if ( get_type(dd) != XLT_PAIR ) {
			ret = "qind.qth.replace(1)";
			goto err;
		}
		q_sts->qth_replace = sexp_to_q_thread(dd);
		if ( q_sts->qth_replace == 0 ) {
			ret = "qind.qth.replace(2)";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_QTH_REPLACE;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.qthResetFocus"));
	if ( d ) {
		dd = eval(env,get_symbol(d));
		if ( get_type(dd) != XLT_PAIR ) {
			ret = "qind.qthResetFocus(1)";
			goto err;
		}
		q_sts->qth_reset_focus = sexp_to_q_thread(dd);
		if ( q_sts->qth_reset_focus == 0 ) {
			ret = "qind.qthResetFocus(2)";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_QTH_RESET_FOCUS;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.NewButton"));
	if ( d ) {
		q_sts->new_button = (VButton*)get_object_from_name(env,d);
		if ( q_sts->new_button == 0 ) {
			ret = "NewButton";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_NEW_BUTTON;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.DelButton"));
	if ( d ) {
		q_sts->del_button = (VButton*)get_object_from_name(env,d);
		if ( q_sts->del_button == 0 ) {
			ret = "DelButton";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_DEL_BUTTON;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.EditButton"));
	if ( d ) {
		q_sts->edit_button = (VButton*)get_object_from_name(env,d);
		if ( q_sts->edit_button == 0 ) {
			ret = "EditButton";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_EDIT_BUTTON;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.EditEvent"));
	if ( d ) {
		q_sts->edit_event = get_vsat(env,d);
		if ( q_sts->edit_event == 0 ) {
			ret = "qind.EditEvent";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_EDIT_EVENT;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.Flame"));
	if ( d ) {
		q_sts->flame = (VgbFlameStandard*)get_object_from_name(env,d);
		if ( q_sts->flame == 0 ) {
			ret = "Flame";
			goto err;
		}
		*q_flags |= VSF_QINDICATE_FLAME;
	}

	d = get_sf_attribute(sf,l_string(std_cm,"qind.Eye.raw"));
	if ( d )  {
		q_sts->eye = 
			get_image_from_lchar(&_ret,env,arg->h.file->name,d);
		if ( get_type(_ret) == XLT_ERROR ) {
			ret = "qind.Eye.raw";
			goto err;
		}
		(*q_flags) |= VSF_QINDICATE_EYE;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.Eye.elr0"));
	if ( d ) {
		q_sts->eye_elr[0]
			= get_elr(n_string(std_cm,d),q_sts->eye);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.Eye.elr1"));
	if ( d ) {
		q_sts->eye_elr[1]
			= get_elr(n_string(std_cm,d),q_sts->eye);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"qind.Eye.elr"));
	if ( d ) {
		get_elr_ary(
			&q_sts->eye_elr[0],
			n_string(std_cm,d),q_sts->eye);
	}

	d = get_sf_attribute(sf,l_string(std_cm,"qind.Scroll"));
	if ( d ) {
		if ( l_strcmp(d,l_string(std_cm,"on")) == 0 )
			*q_flags |= VSF_QINDICATE_SCROLL;
	}
	return 0;
err:
	return ret;
}

int
get_flag_VgbQueryIndicate(L_CHAR * fname)
{
#define RET_FLAG(value, ff)  if ( l_strcmp(fname, l_string(std_cm, #value)) == 0 ) return ff
	RET_FLAG(qind.qthGet,VSF_QINDICATE_QTH_GET);
	RET_FLAG(qind.NewButton,VSF_QINDICATE_NEW_BUTTON);
	RET_FLAG(qind.DelButton,VSF_QINDICATE_DEL_BUTTON);
	RET_FLAG(qind.EditButton,VSF_QINDICATE_EDIT_BUTTON);
	RET_FLAG(qind.Flame,VSF_QINDICATE_FLAME);
	return 0;
}


XL_SEXP *
vobj_get_VgbQueryIndicate(XLISP_ENV * env,XL_SEXP * arg,XLISP_ENV * a,XL_SYM_FIELD * sf)
{
VStatusFlagsFromFS vsffs[2];
VObject * obj;
VgbQueryIndicateStatus q_sts;
VgbQueryIndicate * q_obj;
XL_SEXP * ret,* ret2;
VObjectStatus _sts;
	vsffs[0].get_flag = get_flag_VgbQueryIndicate;
	vsffs[1].get_flag = 0;
	ret = _vobj_GetStatus(&obj,env,arg,a,sf,vsffs);
	if ( ret == 0 && obj == 0 )
		return ret;
	if ( get_type(ret) == XLT_ERROR || vsffs[0].flags == 0 )
		return ret;
	memset(&q_sts,0,sizeof(q_sts));
	q_obj = dynamic_cast<VgbQueryIndicate*>(obj);
	q_obj->get_queryindicate_status(&q_sts,vsffs[0].flags);
	ret2 = 0;
	if ( vsffs[0].flags & VSF_QINDICATE_QTH_GET ) {
		ret2 = cons(
			List(n_get_symbol("qind.qthGet"),
				q_thread_to_sexp(q_sts.qth_get,QTH_NOID_INFO),
				-1),
			ret2);
	}
	if ( vsffs[0].flags & VSF_QINDICATE_NEW_BUTTON ) {
		q_sts.new_button->get_status(&_sts,VSF_ID);
		ret2 = cons(
			List(n_get_symbol("qind.NewButton"),
				get_integer(_sts.id,0),
				-1),
			ret2);
	}
	if ( vsffs[0].flags & VSF_QINDICATE_DEL_BUTTON ) {
		q_sts.del_button->get_status(&_sts,VSF_ID);
		ret2 = cons(
			List(n_get_symbol("qind.DelButton"),
				get_integer(_sts.id,0),
				-1),
			ret2);
	}

	if ( vsffs[0].flags & VSF_QINDICATE_EDIT_BUTTON ) {
		q_sts.edit_button->get_status(&_sts,VSF_ID);
		ret2 = cons(
			List(n_get_symbol("qind.EditButton"),
				get_integer(_sts.id,0),
				-1),
			ret2);
	}
	if ( vsffs[0].flags & VSF_QINDICATE_FLAME ) {
		q_sts.flame->get_status(&_sts,VSF_ID);
		ret2 = cons(
			List(n_get_symbol("qind.Flame"),
				get_integer(_sts.id,0),
				-1),
			ret2);
	}
	free_VgbQueryIndicateStatus(&q_sts);
	return append(ret,ret2);
}


XL_SEXP *
vobj_VgbQueryIndicate(XLISP_ENV *env, XL_SEXP *arg, XLISP_ENV *a, XL_SYM_FIELD *sf)
{
VExError ex_er;
VObjectStatus _sts;
VgbQueryIndicateStatus q_sts;
int q_flags;
char * param_ret;
XL_SEXP * p;
VObjectAppStatusAry app[2];
VgbQueryIndicate * obj;

	p = vobj_get_VgbQueryIndicate(env,arg,a,sf);
	if ( get_type(p) != XLT_NULL )
		return p;

	memset(&q_sts,0,sizeof(q_sts));
	param_ret = VgbQueryIndicate_get_from_sf(&q_sts,&q_flags,env,
				arg->h.file->name,sf,arg);
	if ( param_ret )
		goto param_err;
	app[0].sts = (void*)&q_sts;
	app[0].flags = q_flags;
	app[1].sts = 0;
	app[1].flags = 0;
	p = get_refered_object<VgbQueryIndicate>(&obj,env,arg,sf,
			VO_GQIN,"VgbQueryIndicate",
			&_sts,0,app);
	if ( get_type(p) == XLT_ERROR ) {
		free_VgbQueryIndicateStatus(&q_sts);
		return p;
	}
	if ( get_type(p) == XLT_INTEGER ) {
		free_VgbQueryIndicateStatus(&q_sts);
		return vobj_get_id_list(p->integer.data, 0, sf,0);
	}
	
	ex_er = obj->set_queryindicate_status(&q_sts,q_flags);
	if ( ex_er.code != V_ER_NO_ERR )
		goto err2;
	free_VgbQueryIndicateStatus(&q_sts);
	return 0;
err2:
	obj->destroy();
	free_VgbQueryIndicateStatus(&q_sts);
	return vobj_get_error(ex_er, arg);
param_err:
	free_VgbQueryIndicateStatus(&q_sts);
	return get_error(
		arg->h.file,
		arg->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"VgbQueryIndicate"),
		List(n_get_string("invalid param of attribute ::"),
			n_get_string(param_ret),
			-1));
}

void
init_vobj_VgbQueryIndicate(XLISP_ENV *env)
{
	set_env(env,l_string(std_cm,"VgbQueryIndicate"),
		get_func_prim((XL_SEXP*(*)())vobj_VgbQueryIndicate,FO_NORMAL,0,1,1));
}


} // extern "C"
