/**********************************************************************
 
	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/VgbFlame.h"
#include "v/vobj_utils.h"

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

char *
VgbFlame_get_sw_from_sf(VgbFlameSwitchStatus * sts,int *flags,XL_SYM_FIELD * sf);
VObject * get_object_from_name(XLISP_ENV * env,L_CHAR * name);
char * VgbFlame_get_flame_from_sf(
	VgbFlameStatus * sts,
	int * flags,
	XLISP_ENV * env,
	XL_SYM_FIELD * sf,
	XL_SEXP * arg,
	VObject::FreeList **);
char * VgbFlame_get_flame_radar_from_sf(
	VgbFlameRadarStatus * sts,
	int * flags,
	XLISP_ENV * env,
	XL_SYM_FIELD * sf);
char * VgbFlame_get_flame_coordinate_from_sf(
	VgbFlameCoordinateStatus * sts,
	int * flags,
	XLISP_ENV * env,
	XL_SYM_FIELD * sf);
XL_SEXP * vobj_VgbFlameStandard(XLISP_ENV *env, XL_SEXP *arg, XLISP_ENV *a, XL_SYM_FIELD *sf);
void init_vobj_VgbFlameStandard(XLISP_ENV *env);
void free_VgbFlameRadarStatus(VgbFlameRadarStatus * sts,int flags);
VImage *
get_image_from_lchar(XL_SEXP ** retp,XLISP_ENV * env,L_CHAR *,L_CHAR * _img_field);
char * _get_point_from_char(REAL1*,char*);
GB_POINT get_point_from_char(L_CHAR*);
GB_RECT get_rect_from_char(L_CHAR*);
XL_SEXP *
vsat_VgbFlameStandard_translator(VObject* obj, void* arg);


char * _get_point_from_char(REAL1 * ret,char * str)
{
char * p;
char * d;
int len;
	for ( p = str ; *p && *p != ',' ; p ++ );
	d = (char*)d_alloc(len = p - str + 1);
	memcpy(d,str,len);
	d[p-str] = 0;
	sscanf(str,"%f",ret);
	d_f_ree(d);
	if ( *p == 0 )
		return 0;
	return p+1;
}

GB_POINT get_point_from_char(L_CHAR * str)
{
GB_POINT ret;
char * d;
	d = n_string(std_cm,str);
	d = _get_point_from_char(&ret.x,d);
	if ( d )
		_get_point_from_char(&ret.y,d);
	return ret;
}

GB_RECT get_rect_from_char(L_CHAR * str)
{
GB_RECT ret;
char * d;
	d = n_string(std_cm,str);
	d = _get_point_from_char(&ret.tl.x,d);
	if ( d )
		d = _get_point_from_char(&ret.tl.y,d);
	if ( d )
		d = _get_point_from_char(&ret.br.x,d);
	if ( d )
		_get_point_from_char(&ret.br.y,d);
	return ret;
}



char * VgbFlame_get_flame_coordinate_from_sf(
	VgbFlameCoordinateStatus * sts,
	int * flags,
	XLISP_ENV * env,
	XL_SYM_FIELD * sf)
{
char * ret;
L_CHAR * d;
	*flags = 0;
	ret = 0;
	d = get_sf_attribute(sf,l_string(std_cm,"flame.crd.FlameBaseRect"));
	if ( d ) {
		sts->flame_base_rect = get_rect_from_char(d);
		(*flags) |= VSF_FLAME_C_FLAME_BASE_RECT;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.crd.FlameBaseCenter"));
	if ( d ) {
		sts->flame_base_center = get_point_from_char(d);
		(*flags) |= VSF_FLAME_C_FLAME_BASE_CENTER;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.crd.FlameBaseRotate"));
	if ( d ) {
		sscanf(n_string(std_cm,d),"%f",&sts->flame_base_rotate);
		(*flags) |= VSF_FLAME_C_FLAME_BASE_ROTATE;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.crd.FlameBaseResolution"));
	if ( d ) {
		sscanf(n_string(std_cm,d),"%f",&sts->flame_base_resolution);
		(*flags) |= VSF_FLAME_C_FLAME_BASE_RESOLUTION;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.crd.Target"));
	if ( d ) {
		sts->target = ll_copy_str(d);
		(*flags) |= VSF_FLAME_C_TARGET;
	}
	return 0;
}

char *
VgbFlame_get_sw_from_sf(VgbFlameSwitchStatus * sts,int *flags,XL_SYM_FIELD * sf)
{
char * ret;
L_CHAR * d;
	*flags = 0;
	ret = 0;
	d = get_sf_attribute(sf,l_string(std_cm,"flame.switch.Format"));
	if ( d ) {
		sts->format = ll_copy_str(d);
		(*flags) |= VSF_FLAME_S_FORMAT;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.switch.Quality"));
	if ( d ) {
		sts->quality = ll_copy_str(d);
		(*flags) |= VSF_FLAME_S_QUALITY;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.switch.Peripheral"));
	if ( d ) {
		sts->peripheral = ll_copy_str(d);
		(*flags) |= VSF_FLAME_S_PERIPHERAL;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.switch.Parameter"));
	if ( d ) {
		sts->parameter = ll_copy_str(d);
		(*flags) |= VSF_FLAME_S_PARAMETER;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.switch.AgentURL"));
	if ( d ) {
		sts->agent_url = ll_copy_str(d);
		(*flags) |= VSF_FLAME_S_AGENT_URL;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.switch.Mode"));
	if ( d ) {
		if ( l_strcmp(d,l_string(std_cm,"Idle")) == 0 )
			sts->mode = SW_MODE_IDLE;
		else if ( l_strcmp(d,l_string(std_cm,"Local")) == 0 )
			sts->mode = SW_MODE_LOCAL;
		else if ( l_strcmp(d,l_string(std_cm,"Remote")) == 0 )
			sts->mode = SW_MODE_REMOTE;
		else {
			ret = "flame.switch.Mode";
			goto err;
		}
		(*flags) |= VSF_FLAME_S_MODE;
	}
	return 0;
err:
	return ret;
}

XL_SEXP *
vsat_VgbFlameStandard_translator(VObject* obj, void* arg)
{
	return List(n_get_symbol("quote"),(XL_SEXP*)arg,-1);
}


char *
VgbFlame_get_flame_from_sf(
	VgbFlameStatus * sts,
	int * flags,
	XLISP_ENV * env,
	XL_SYM_FIELD * sf,
	XL_SEXP * arg,
	VObject::FreeList **free_list)
{
char * ret;
XL_SEXP * _ret;
L_CHAR * d;
	*flags = 0;
	ret = 0;
	d = get_sf_attribute(sf,l_string(std_cm,"flame.Style"));
	if ( d ) {
		if ( l_strcmp(d,l_string(std_cm,"onFlameButton")) == 0 )
			sts->style = VGB_STYLE_ON_FLAME_BTN;
		else if ( l_strcmp(d,l_string(std_cm,"exFlameButton")) == 0 )
			sts->style = VGB_STYLE_EX_FLAME_BTN;
		else {
			ret = "flame.Style";
			goto err;
		}
		(*flags) |= VSF_FLAME_STYLE;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.DefaultWS"));
	if ( d ) {
		sts->default_ws = get_ws(d);
		if ( sts->default_ws == 0 ) {
			ret = "flame.DefaultWS";
			goto err;
		}
		(*flags) |= VSF_FLAME_DEFAULT_WS;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.ZoomIn"));
	if ( d )  {
		sts->zoom_in = (VButton*)get_object_from_name(env,d);
		if ( sts->zoom_in == 0 ) {
			ret = "flame.ZoomIn";
			goto err;
		}
		(*flags) |= VSF_FLAME_ZOOM_IN;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.ZoomOut"));
	if ( d )  {
		sts->zoom_out = (VButton*)get_object_from_name(env,d);
		if ( sts->zoom_out == 0 ) {
			ret = "flame.ZoomOut";
			goto err;
		}
		(*flags) |= VSF_FLAME_ZOOM_OUT;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.GrabModeButton"));
	if ( d )  {
		sts->grab_mode_button = (VRadioButton*)get_object_from_name(env,d);
		if ( sts->grab_mode_button == 0 ) {
			ret = "flame.GrabModeButton";
			goto err;
		}
		(*flags) |= VSF_FLAME_GRAB_MODE_BUTTON;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.RotateModeButton"));
	if ( d )  {
		sts->rotate_mode_button = (VRadioButton*)get_object_from_name(env,d);
		if ( sts->rotate_mode_button == 0 ) {
			ret = "flame.RotateModeButton";
			goto err;
		}
		(*flags) |= VSF_FLAME_ROTATE_MODE_BUTTON;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.ClickModeButton"));
	if ( d )  {
		sts->click_mode_button = (VRadioButton*)get_object_from_name(env,d);
		if ( sts->click_mode_button == 0 ) {
			ret = "flame.ClickModeButton";
			goto err;
		}
		(*flags) |= VSF_FLAME_CLICK_MODE_BUTTON;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.ButtonsControl"));
	if ( d )  {
	int id;
		id = atoi(n_string(std_cm,d));
		sts->buttons_control = id2marshaler(id);
		if ( sts->buttons_control == 0 ) {
			ret = "flame.ButtonsControl";
			goto err;
		}
		(*flags) |= VSF_FLAME_BUTTONS_CONTROL;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateObj"));
	if ( d )  {
		sts->indicate_obj = (VgbIndicate*)get_object_from_name(env,d);
		if ( sts->indicate_obj == 0 ) {
			ret = "flame.IndicateObj";
			goto err;
		}
		(*flags) |= VSF_FLAME_INDICATE_OBJ;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeObj"));
	if ( d )  {
		sts->indicate_tree_obj = (VxlTreeView*)get_object_from_name(env,d);
		if ( sts->indicate_obj == 0 ) {
			ret = "flame.IndicateTreeObj";
			goto err;
		}
		(*flags) |= VSF_FLAME_INDICATE_TREE_OBJ;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeEye.raw"));
	if ( d )  {
		sts->indicate_tree_eye = 
			get_image_from_lchar(&_ret,env,arg->h.file->name,d);
		if ( get_type(_ret) == XLT_ERROR ) {
			ret = "flame.IndicateTreeEye.raw";
			goto err;
		}
		(*flags) |= VSF_FLAME_INDICATE_TREE_EYE;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeEye.elr0"));
	if ( d ) {
		sts->indicate_tree_eye_elr[0]
			= get_elr(n_string(std_cm,d),sts->indicate_tree_eye);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeEye.elr1"));
	if ( d ) {
		sts->indicate_tree_eye_elr[1]
			= get_elr(n_string(std_cm,d),sts->indicate_tree_eye);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeEye.elr"));
	if ( d ) {
		get_elr_ary(
			&sts->indicate_tree_eye_elr[0],
			n_string(std_cm,d),sts->indicate_tree_eye);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeInfo.raw"));
	if ( d )  {
		sts->indicate_tree_info = 
			get_image_from_lchar(&_ret,env,arg->h.file->name,d);
		if ( get_type(_ret) == XLT_ERROR ) {
			ret = "flame.IndicateTreeInfo.raw";
			goto err;
		}
		(*flags) |= VSF_FLAME_INDICATE_TREE_INFO;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeInfo.elr0"));
	if ( d ) {
		sts->indicate_tree_info_elr[0]
			= get_elr(n_string(std_cm,d),sts->indicate_tree_info);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeInfo.elr1"));
	if ( d ) {
		sts->indicate_tree_info_elr[1]
			= get_elr(n_string(std_cm,d),sts->indicate_tree_info);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeInfo.elr"));
	if ( d ) {
		get_elr_ary(
			&sts->indicate_tree_info_elr[0],
			n_string(std_cm,d),sts->indicate_tree_info);
	}

	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeBase.raw"));
	if ( d )  {
		sts->indicate_tree_base = 
			get_image_from_lchar(&_ret,env,arg->h.file->name,d);
		if ( get_type(_ret) == XLT_ERROR ) {
			ret = "flame.IndicateTreeBase.raw";
			goto err;
		}
		(*flags) |= VSF_FLAME_INDICATE_TREE_BASE;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeBase.elr0"));
	if ( d ) {
		sts->indicate_tree_base_elr[0]
			= get_elr(n_string(std_cm,d),sts->indicate_tree_base);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeBase.elr1"));
	if ( d ) {
		sts->indicate_tree_base_elr[1]
			= get_elr(n_string(std_cm,d),sts->indicate_tree_base);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeBase.elr2"));
	if ( d ) {
		sts->indicate_tree_base_elr[2]
			= get_elr(n_string(std_cm,d),sts->indicate_tree_base);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeBase.elr3"));
	if ( d ) {
		sts->indicate_tree_base_elr[3]
			= get_elr(n_string(std_cm,d),sts->indicate_tree_base);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.IndicateTreeBase.elr"));
	if ( d ) {
		get_elr_ary(
			&sts->indicate_tree_base_elr[0],
			n_string(std_cm,d),sts->indicate_tree_base);
	}

	d = get_sf_attribute(sf,l_string(std_cm,"flame.OAttributeHandler"));
	if ( d ) {
	VSysArgTranslator * vsat;
	VObject::FreeList * list;
		vsat = get_vsat(env,d);
		if ( vsat == 0 ) {
			ret = "OAttributeHandler";
			goto err;
		}
		vsat->translator = vsat_VgbFlameStandard_translator;
		sts->oattribute_handler = vobj_callback_glue;
		sts->oattribute_handler_arg = vsat;

		list = new VObject::FreeList;
		list->target = vsat;
		list->next = *free_list;
		list->free_func = free_VSysArgTranslator;
		insert_vsat_list(vsat);
		*free_list = list;
		(*flags) |= VSF_FLAME_OATTRIBUTE_HANDLER;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.SelectMode"));
	if ( d )  {
		if ( l_strcmp(d,l_string(std_cm,"GrabMode")) == 0 )
			sts->select_mode = VGB_MODE_GRAB;
		else if ( l_strcmp(d,l_string(std_cm,"RotateMode")) == 0 )
			sts->select_mode = VGB_MODE_ROTATE;
		else if ( l_strcmp(d,l_string(std_cm,"ClickMode")) == 0 )
			sts->select_mode = VGB_MODE_CLICK;
		else {
			ret = "flame.SelectMode";
			goto err;
		}
		(*flags) |= VSF_FLAME_SELECT_MODE;
	}

	d = get_sf_attribute(sf,l_string(std_cm,"flame.Focus"));
	if ( d ) {
		if ( l_strcmp(d,l_string(std_cm,"on")) == 0 )
			(*flags) |= VSF_FLAME_FOCUS;
	}

	return 0;
err:
	return ret;
}

char *
VgbFlame_get_flame_radar_from_sf(
	VgbFlameRadarStatus * sts,
	int * flags,
	XLISP_ENV * env,
	XL_SYM_FIELD * sf)
{
L_CHAR * d;
char * ret;
XL_SEXP * _q;
	*flags = 0;
	ret = 0;
	memset(sts,0,sizeof(*sts));
	d = get_sf_attribute(sf,l_string(std_cm,"flame.RadarGetQuery"));
	if ( d ) {
		*flags |= VSF_FLAME_R_QUERY_GET;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.RadarInsertQuery"));
	if ( d ) {
		*flags |= VSF_FLAME_R_QUERY_INSERT;
		_q = eval(env,get_symbol(d));
		if ( get_type(_q) == XLT_ERROR ) {
			ret = "invalid query";
			goto err;
		}
		sts->query_insert = sexp_to_q_thread(_q);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.RadarSetQuery"));
	if ( d ) {
		*flags |= VSF_FLAME_R_QUERY_SET;
		_q = eval(env,get_symbol(d));
		if ( get_type(_q) == XLT_ERROR ) {
			ret = "invalid query";
			goto err;
		}
		sts->query_set = sexp_to_q_thread(_q);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.RadarReplaceQuery"));
	if ( d ) {
		*flags |= VSF_FLAME_R_QUERY_REPLACE;
		_q = eval(env,get_symbol(d));
		if ( get_type(_q) == XLT_ERROR ) {
			ret = "invalid query";
			goto err;
		}
		sts->query_replace = sexp_to_q_thread(_q);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"flame.RadarDeleteQueryByNo"));
	if ( d ) {
		*flags |= VSF_FLAME_R_QUERY_DELETE_BYNO;
		if ( l_strcmp(d,l_string(std_cm,"all")) == 0 )
			sts->delete_byno = -1;
		else	sts->delete_byno = atoi(n_string(std_cm,d));
	}
	return 0;
err:
	return ret;
}

void
free_VgbFlameRadarStatus(VgbFlameRadarStatus * sts,int flags)
{
	if ( flags & VSF_FLAME_R_QUERY_GET )
		free_query_thread(sts->result_query);
	if ( flags & VSF_FLAME_R_QUERY_INSERT )
		free_query_thread(sts->query_insert);
}

XL_SEXP *
vobj_VgbFlameStandard(XLISP_ENV *env, XL_SEXP *arg, XLISP_ENV *a, XL_SYM_FIELD *sf)
{
VExError ex_er;
VObjectStatus _sts;
VgbFlameSwitchStatus sw_sts;
VgbFlameStatus f_sts;
VgbFlameRadarStatus r_sts;
VgbFlameCoordinateStatus c_sts;
int f_flags,sw_flags,r_flags,c_flags;
char * param_ret;
/*
int flags = get_sts_from_sf(&sts,0, sf, &free_list);
*/
XL_SEXP * p;
/*
L_CHAR * refer;
*/
VgbFlameStandard * obj;
VObject::FreeList * free_list = 0;
VObjectAppStatusAry app[2];

void mem_test(char*);

	memset(&f_sts,0,sizeof(f_sts));
	param_ret = VgbFlame_get_sw_from_sf(&sw_sts,&sw_flags,sf);
	if ( param_ret )
		goto param_err;
	param_ret = VgbFlame_get_flame_from_sf(&f_sts,&f_flags,env,sf,arg,&free_list);
	if ( param_ret )
		goto param_err;
	param_ret = VgbFlame_get_flame_radar_from_sf(&r_sts,&r_flags,env,sf);
	if ( param_ret ) {
		goto param_err;
	}
	param_ret = VgbFlame_get_flame_coordinate_from_sf(&c_sts,&c_flags,env,sf);
	if ( param_ret ) {
		goto param_err;
	}
	app[0].sts = (void*)&f_sts;
	app[0].flags = f_flags;
	app[1].sts = 0;
	app[1].flags = 0;
	p = get_refered_object<VgbFlameStandard>(&obj,env,arg,sf,
			VO_GFLM,"VgbFlameStandard",
			&_sts,0,app);
	if ( get_type(p) == XLT_ERROR )
		return p;

	obj->free_on_release_list(free_list);
	ex_er = obj->set_switch_status(&sw_sts,sw_flags);
	if ( ex_er.code != V_ER_NO_ERR )
		goto err2;
	if ( get_type(p) != XLT_INTEGER ) {
		ex_er = obj->set_flame_status(&f_sts,f_flags);
		if ( ex_er.code != V_ER_NO_ERR )
			goto err2;
	}
	ex_er = obj->set_radar_status(&r_sts,r_flags);
	free_VgbFlameRadarStatus(&r_sts,r_flags);
	if ( ex_er.code != V_ER_NO_ERR )
		goto err2;
	ex_er = obj->set_coordinate_status(&c_sts,c_flags);
	free_VgbFlameCoordinateStatus(&c_sts,c_flags);
	if ( ex_er.code != V_ER_NO_ERR )
		goto err2;
	if ( get_type(p) == XLT_INTEGER )
		return vobj_get_id_list(p->integer.data, 0, sf,0);
	else	return 0;
err2:
	obj->destroy();
	if ( f_sts.indicate_tree_eye )
		v_image_unref(f_sts.indicate_tree_eye);
	if ( f_sts.indicate_tree_info )
		v_image_unref(f_sts.indicate_tree_info);

	return vobj_get_error(ex_er, arg);
param_err:
	if ( f_sts.indicate_tree_eye )
		v_image_unref(f_sts.indicate_tree_eye);
	if ( f_sts.indicate_tree_info )
		v_image_unref(f_sts.indicate_tree_info);

	return get_error(
		arg->h.file,
		arg->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"VgbFlameStandard"),
		List(n_get_string("invalid param of attribute ::"),
			n_get_string(param_ret),
			-1));
}

void
init_vobj_VgbFlameStandard(XLISP_ENV *env)
{
	set_env(env,l_string(std_cm,"VgbFlameStandard"),
		get_func_prim((XL_SEXP*(*)())vobj_VgbFlameStandard,FO_NORMAL,0,1,1));
}


} // extern "C"
