/**********************************************************************
 
	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	<fcntl.h>
#include	"xl.h"
#include	"memory_debug.h"
#include	"lump.h"
#include	"acrp.h"

void
init_lump_opt(LUMP_OPT * opt)
{
	opt->destroy = 0;
	opt->launch = 0;
	opt->flag = 0;
	opt->lump = 0;
	opt->fade_time = 0;
	opt->fade_interval = 0;
}

void
free_lump_opt(LUMP_OPT * opt)
{
	if ( opt->lump )
		d_f_ree(opt->lump);
}


void
free_lr(LUMP_ROUTE * lr)
{
LUMP_ROUTE * lr1;
	for ( ; lr ; ) {
		lr1 = lr->next;
		d_f_ree(lr->lump_crd);
		if ( lr->dir )
			d_f_ree(lr->dir);
		d_f_ree(lr);
		lr = lr1;
	}
}


LUMP_ROUTE *
search_lr(LUMP_ROUTE * lr,L_CHAR * crd)
{
	for ( ; lr ; lr = lr->next )
		if ( l_strcmp(lr->lump_crd,crd) == 0 )
			return lr;
	return 0;
}


XL_SEXP *
image_of_lump_info(LUMP_INFO * info)
{
XL_SEXP * ret;
	ret = 0;
	if ( info->crd )
		ret = cons(
			List(n_get_symbol("crd"),
				get_string(info->crd),
				-1),
			ret);
	return cons(n_get_symbol("lump"),ret);
}

char *
get_lump_info_path(L_CHAR * path)
{
int len,slen;
char * filename;
extern L_CHAR * sys_path;
	len = l_strlen(path);
	slen = l_strlen(sys_path);
	filename = d_alloc((len+slen+100)*sizeof(L_CHAR));
	sprintf(filename,"%s%sinfo.xl",
		n_string(std_cm,sys_path),
		n_string(std_cm,path));
	return filename;
}

char *
get_fullpath(L_CHAR * path)
{
int len,slen;
char * filename;
extern L_CHAR * sys_path;
	for ( ; sys_path == 0 ; ) {
		fprintf(stderr,"undefined sys_path");
		sleep_sec(1);
	}

	len = l_strlen(path);
	slen = l_strlen(sys_path);
	filename = d_alloc((len+slen+100)*sizeof(L_CHAR));
	sprintf(filename,"%s%s",
		n_string(std_cm,sys_path),
		n_string(std_cm,path));
	return filename;
}

void
save_lump_info(L_CHAR * path,LUMP_INFO * info)
{
XL_SEXP * gt;
char * filename;
STREAM * st;

	filename = get_lump_info_path(path);
	gt = n_get_symbol("?xl");
	set_attribute(gt,
		l_string(std_cm,"version"),
		l_string(std_cm,"0.1"));
	set_attribute(gt,
		l_string(std_cm,"encoding"),
		l_string(std_cm,"EUC-JP"));
	st = s_open_file(
		filename,
		O_CREAT|O_TRUNC|O_RDWR,
		0644);
	if ( st == 0 ) {
		d_f_ree(filename);
		return;
	}
	print_sexp(
		st,
		List(	List(gt,-1),
			image_of_lump_info(info),
			-1),
		PF_MULTI_ROOT|PF_INDENT);
	s_printf(st,"\n");
	s_close(st);
	d_f_ree(filename);
}

int
load_lump_info(LUMP_INFO * info,L_CHAR * db)
{
char * path;
STREAM * st;
XL_SEXP * d;
L_CHAR * crd;
int crd_ret;
L_CHAR * _db;
int i;
	info->crd = 0;
	_db = ll_copy_str(db);
	i = l_strlen(_db)-1;
	if ( _db[i] != '/' ) {
		for ( ; i >= 0 ; i -- )
			if ( _db[i] == '/' )
				break;
		i ++;
		_db[i] = 0;
	}
	path = get_lump_info_path(_db);
	d_f_ree(_db);
	st = s_open_file(path,O_RDONLY);
	d = init_parse(st,l_string(std_cm,path),
			l_string(std_cm,path));
	d_f_ree(path);
	if ( get_type(d) == XLT_ERROR )
		return -1;
	d = get_el(d,1);
	if ( get_type(d) != XLT_PAIR )
		return -1;
	get_field(d,
		l_string(std_cm,"crd"),"s",&crd,&crd_ret,
		0);
	if ( crd_ret )
		return -1;
	info->crd = ll_copy_str(crd);
	return 0;
}

void
free_lump_info(LUMP_INFO * info)
{
	if ( info->crd )
		d_f_ree(info->crd);
	info->crd = 0;
}


LUMP_ROUTE *
xx_insert_lr(LUMP_ROUTE * lr,LUMP_ROUTE * ref,int ofs,L_CHAR * comein,
char * __file,int __line)
{
int dist;
LUMP_ROUTE ** lrp;
LUMP_ROUTE * lr1;
	dist = ref->distance + ofs;
	for ( lrp = &lr ; *lrp ; lrp = &(*lrp)->next ) {
		if ( (*lrp)->distance > dist )
			break;
		if ( (*lrp)->distance < dist )
			continue;
		if ( l_strcmp((*lrp)->lump_crd,ref->lump_crd) > 0 )
			break;
	}
	lr1 = xx_d_alloc(sizeof(*lr1),__file,__line);
	lr1->lump_crd = xx_ll_copy_str(ref->lump_crd,__file,__line);
	if ( comein == 0 )
		lr1->dir = xx_ll_copy_str(ref->dir,__file,__line);
	else	lr1->dir = xx_ll_copy_str(comein,__file,__line);
	lr1->pri = ref->pri;
	lr1->distance = dist;
	lr1->radius = ref->radius;

	lr1->next = *lrp;
	*lrp = lr1;
	return lr;
}


void
lr_option(LUMP_OPT * opt,XL_SEXP * op)
{
XL_SEXP * ent, * sym;
XL_SEXP * es;
	if ( opt == 0 )
		return;
	op = cdr(op);
	for ( ; get_type(op) == XLT_PAIR ; op = cdr(op) ) {
		ent = car(op);
		if ( get_type(ent) != XLT_PAIR )
			continue;
		sym = car(ent);
		if ( get_type(sym) != XLT_SYMBOL )
			continue;
		if ( l_strcmp(sym->symbol.data,l_string(std_cm,"destroy"))
				== 0 ) {
			es = get_el(ent,1);
			if ( get_type(es) != XLT_INTEGER )
				continue;
			opt->destroy = es->integer.data;
		}
		else if ( l_strcmp(sym->symbol.data,l_string(std_cm,"launch"))
				== 0 ) {
			es = get_el(ent,1);
			if ( get_type(es) != XLT_INTEGER )
				continue;
			opt->launch = es->integer.data;
		}
		else if ( l_strcmp(sym->symbol.data,
				l_string(std_cm,"lump"))
				== 0 ) {
			es = get_el(ent,1);
			if ( get_type(es) != XLT_STRING )
				continue;
			if ( opt->lump )
				d_f_ree(opt->lump);
			opt->lump = ll_copy_str(es->string.data);
		}
		else if ( l_strcmp(sym->symbol.data,
				l_string(std_cm,"fade"))
				== 0 ) {
			es = get_el(ent,1);
			if ( get_type(es) != XLT_INTEGER )
				continue;
			opt->fade_time = es->integer.data;
			es = get_el(ent,2);
			if ( get_type(es) != XLT_INTEGER )
				continue;
			opt->fade_interval = es->integer.data;
		}
	}
}

void
check_lr_opt(LUMP_OPT * opt,LUMP_ROUTE * r,L_CHAR *crd)
{
LUMP_ROUTE * r1;
LUMP_ROUTE * lr;
	if ( opt == 0 )
		return;
	if ( opt->lump && crd ) {
		r1 = search_lr(r,crd);
		if ( r1 == 0 ) {
			d_f_ree(opt->lump);
			opt->lump = 0;
			opt->flag = 1;
		}
	}
}

LUMP_ROUTE *
xx_get_lr(LUMP_OPT * opt,XL_SEXP * data,L_CHAR * cc,char * __file,int __line)
{
LUMP_ROUTE * ret, lr;
XL_SEXP * li, * sym, * ent;
XL_SEXP * crd, * pri, * dist,* dir, * radius;
	ret = 0;
	if ( get_type(data) == 0 )
		return 0;
	li = cdr(data);
	for ( ; get_type(li) == XLT_PAIR ; li = cdr(li) ) {
		ent = car(li);
		if ( get_type(ent) != XLT_PAIR )
			continue;
		sym = car(ent);
		if ( get_type(sym) != XLT_SYMBOL )
			continue;
		if ( l_strcmp(sym->symbol.data,l_string(std_cm,"entry")) 
				== 0 ) {
			crd = get_el(ent,1);
			dir = get_el(ent,2);
			pri = get_el(ent,3);
			dist = get_el(ent,4);
			if ( list_length(ent) < 6 )
				radius = 0;
			else	radius = get_el(ent,5);
			if ( get_type(crd) != XLT_STRING )
				continue;
			if ( get_type(dir) != XLT_STRING )
				continue;
			if ( get_type(pri) != XLT_INTEGER )
				continue;
			if ( get_type(dist) != XLT_INTEGER )
				continue;
			if ( radius != 0 &&
				get_type(radius) != XLT_INTEGER )
				continue;
			lr.lump_crd = crd->string.data;
			lr.dir = dir->string.data;
			lr.pri = pri->integer.data;
			lr.distance = dist->integer.data;
			if ( radius )
				lr.radius = radius->integer.data;
			else	lr.radius = DEFAULT_TTL-1;
			if ( cc && dist->integer.data == 0 &&
					l_strcmp(lr.lump_crd,cc) ) {
				if ( opt )
					opt->flag = 1;
			}
			else 	ret = xx_insert_lr(ret,&lr,0,0,__file,__line);
		}
		else if ( l_strcmp(sym->symbol.data,l_string(std_cm,"option"))
				== 0 )
			lr_option(opt,ent);
	}
	check_lr_opt(opt,ret,cc);
	return ret;
}

