/**********************************************************************
 
	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	"memory_debug.h"
#include	"xl.h"
#include	"gbpmd.h"
#include	"resource.h"
#include	"lump.h"
#include	"utils.h"
#include	"routing.h"

void
convert_rect(
	GB_RECT * ret_rect,
	REAL1 * ret_reso,

	MAP_HISTORY * mh,
	GB_RECT rect,
	REAL1 reso)
{
GB_POINT p[8];
REAL1	r[8];
int i;
GB_RECT ret;
	p[0] = rect.tl;
	p[2].x = rect.tl.x;
	p[2].y = rect.br.y;
	p[4] = rect.br;
	p[6].x = rect.br.x;
	p[6].y = rect.tl.y;
	p[1] = p_avg(p[0],p[2]);
	p[3] = p_avg(p[2],p[4]);
	p[5] = p_avg(p[4],p[6]);
	p[7] = p_avg(p[6],p[0]);
	for ( i = 0 ; i < 8 ; i ++ )
		r[i] = reso;
	map_from_flame(mh,p,r,8);
	ret.tl.x = ret.tl.y = 0;
	ret.br.x = ret.br.y = -1;
	reso = 0;
	for ( i = 0 ; i < 8 ; i ++ ) {
		if ( r[i] < 0 )
			continue;
		insert_rect(&ret,p[i]);
		reso += r[i];
	}
	*ret_reso = reso/8;
	*ret_rect = ret;
}

void
set_target_crd(int ses,L_CHAR * db,L_CHAR * crd,L_CHAR * map,L_CHAR * obj,
	       int interval)
{
LUMP_ROUTE * lr;
MAP_HISTORY * mh1, * mh2, * mh3;
RESOURCE * crd_r, * obj_r, * db_r;
URL u;
GB_RECT minrect;
REAL1 reso,obj_reso;
LUMP_INFO info;
XL_SEXP * lmp;
RESOURCE * map_r;

	lmp = load_meta(ses,"lump",crd);
	if ( get_type(lmp) == XLT_ERROR )
		return;
	lr = get_lr(0,lmp,0);
	if ( load_lump_info(&info,db) < 0 )
		goto end0;
	if ( search_lr(lr,info.crd) == 0 )
		goto end0;
	if ( l_strcmp(crd,info.crd) ) {
		mh1 = resolve_mappath(ses,crd,info.crd,RR_WM_DIRECT);
		if ( mh1 == MP_MH_NO_ROUTE )
			goto end0;
		get_url2(&u,crd);
		crd_r = load_resource(ses,&u,Q_PRI_OBJ);
		free_url(&u);
		if ( crd_r == 0 )
			goto end1;
		convert_rect(&minrect,&reso,
			mh1,
			crd_r->h.minrect,
			crd_r->h.visible_resolution);
	}
	else {
		mh1 = 0;
		get_url2(&u,crd);
		crd_r = load_resource(ses,&u,Q_PRI_OBJ);
		free_url(&u);
		if ( crd_r == 0 )
			goto end1;
		minrect = crd_r->h.minrect;
		reso = crd_r->h.visible_resolution;
	}

	get_url2(&u,info.crd);
	db_r = load_resource(ses,&u,Q_PRI_OBJ);
	free_url(&u);
	if ( db_r == 0 )
		goto end1;
	

	set_metadata(db,&minrect,reso,crd,crd_r,db_r,4*interval);
	if ( obj == 0 )
		goto end1;
	get_url2(&u,obj);
	obj_r = load_resource(ses,&u,Q_PRI_OBJ);
	free_url(&u);
	if ( obj_r == 0 )
		goto end1;
	get_url2(&u,map);
	map_r = load_resource(ses,&u,Q_PRI_OBJ);
	free_url(&u);
	if ( map_r == 0 ) {
log_printf(LOG_DEBUG,"cannot load %s\n",n_string(std_cm,map));
		goto end1;
	}
	mh2 = new_mh(map_r,MHD_FORWARD);
	mh3 = add_mh(mh2,mh1);
	obj_reso = rect_resolution(&obj_r->h.minrect,0,1);
	convert_rect(
		&minrect,&obj_reso,
		mh3,obj_r->h.minrect,
		obj_reso);

	if ( reso > obj_reso )
		obj_reso = reso;

	set_metadata(db,&minrect,obj_reso,crd,obj_r,db_r,4*interval);
end2:
	free_mh(mh2);
	free_mh(mh3);
end1:
	free_mh(mh1);
end0:
	free_lr(lr);
	free_lump_info(&info);
}

void
set_target_map(int ses,L_CHAR * db,L_CHAR * target,int interval)
{
XL_SEXP * raw, * meta, * lrs;
int src_ret,dest_ret;
L_CHAR * src,* dest;
int len;

	raw = meta = load_meta(ses,"meta",target);
	if ( get_type(meta) == XLT_ERROR ) {
		print_sexp(s_stdout,meta,0);
		printf("\n");
		return;
	}
	meta = get_el(meta,1);
	get_field(meta,
		l_string(std_cm,"src"),"s",&src,&src_ret,
		l_string(std_cm,"dest"),"s",&dest,&dest_ret,
		0);
	if ( src_ret || dest_ret ) {
printf("src_ret dest_rect = %i %i\n",src_ret,dest_ret);
print_sexp(s_stdout,raw,0);
printf("\n");
log_printf(LOG_DEBUG,"cannot access meta %s %i %i",
n_string(std_cm,target),src_ret,dest_ret);
		return;
	}
	src = compose_url(target,src);
	dest = compose_url(target,dest);
	len = l_strlen(dest);
	if ( l_strcmp(&dest[len-4],l_string(std_cm,".crd")) )
		return;
	len = l_strlen(src);
	if ( l_strcmp(&src[len-4],l_string(std_cm,".crd")) ) {
		set_target_crd(ses,db,dest,target,src,interval);
	}
	else {
		set_target_crd(ses,db,dest,0,0,interval);
		set_target_crd(ses,db,src,0,0,interval);
	}
}

void
set_target(int ses,L_CHAR * db,L_CHAR* target,int interval)
{
int len;
	len = l_strlen(target);

	if ( l_strcmp(&target[len-4],l_string(std_cm,".map")) == 0 )
		set_target_map(ses,db,target,interval);
	else if ( l_strcmp(&target[len-4],l_string(std_cm,".crd")) == 0 )
		set_target_crd(ses,db,target,0,0,interval);
}
