/**********************************************************************
 
	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	<fcntl.h>
#include	<math.h>
#include	"memory_debug.h"
#include	"xl.h"
#include	"gbparam.h"
#include	"utils.h"
#include	"gbview.h"
#include	"memory_routine.h"
#include	"xlerror.h"
#include	"tree_cache.h"
#include	"lock_level.h"
#include	"pri_level.h"

SEM luster_lock;
XL_SEXP * gv_luster_r64_status();


void
init_luster()
{
XLISP_ENV * l_top,* l_cmd;

	luster_lock = new_lock(LL_LUSTER);

	l_cmd = new_env(0);
	l_top = new_env(gblisp_top_env0);

	set_env(l_top,l_string(std_cm,"gv-status"),
			get_func_prim(gv_luster_r64_status,
			FO_APPLICATIVE,0,1,1));

	root_tag(l_top,l_string(std_cm,"luster"),l_cmd);
	set_env(gblisp_top_env0,l_string(std_cm,"luster"),
		get_env(l_top));
	set_gv_resource(RT_PIXEL_MAP_R64,l_top);
}

XL_SEXP * 
gv_luster_r64_status(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
XL_SEXP * ret;
RESOURCE * r;
	return cons(
		get_symbol(l_string(std_cm,"luster")),
		get_resource_status_header(&r,env,s,a,0));
}



XL_SEXP *
get_r64_meta(XL_SEXP * s)
{
XL_SEXP * rec, * tag;
	for ( ; get_type(s) ; s = cdr(s) ) {
		if ( get_type(s) != XLT_PAIR )
			return 0;
		rec = car(s);
		if ( get_type(rec) != XLT_PAIR )
			continue;
		tag = car(rec);
		if ( get_type(tag) != XLT_SYMBOL )
			continue;
		if ( l_strcmp(tag->symbol.data,l_string(std_cm,"r64"))
				== 0 )
			return rec;
	}
	return 0;
}

XL_SEXP *
get_cr_meta(XL_SEXP * s)
{
XL_SEXP * rec, * tag;
	for ( ; get_type(s) ; s = cdr(s) ) {
		if ( get_type(s) != XLT_PAIR )
			return 0;
		rec = car(s);
		if ( get_type(rec) != XLT_PAIR )
			continue;
		tag = car(rec);
		if ( get_type(tag) != XLT_SYMBOL )
			continue;
		if ( l_strcmp(tag->symbol.data,l_string(std_cm,"cr"))
				== 0 )
			return rec;
	}
	return 0;
}

/*
void
luster_check_loop(RESOURCE * r)
{
int i;
	if ( r->h.type != RT_LUSTER )
		return;
	for ( i = 0 ; i < r->pr64.max_level ; i ++ ) {
		if ( r->pr64.width[i] == 0 )
			er_panic("A");
		if ( r->pr64.height[i] == 0 )
			er_panic("B");
	}
}

void
_luster_check()
{
int i;
RESOURCE * r;
extern RESOURCE ** res_no_hash_table;
	for ( i = 0 ; i < RES_HASH_SIZE ; i ++ ) {
		r = res_no_hash_table[i];
		for( ; r ; r = r->h.no_next )
			luster_check_loop(r);
	}
}

void
luster_check()
{
extern SEM res_lock;
	lock_task(res_lock);
	_luster_check();
	unlock_task(res_lock,"luster_check");
}

*/

XL_SEXP *
gv_new_luster(RESOURCE * r,XL_SEXP * s,int ds)
{
XL_SEXP * ss,* r64, * cr;
REAL1 rate;
double dpm;
L_CHAR * unit;
int er;
L_CHAR * t2_buf,* nm_buf;
int ret_t2,ret_nm,ret_scale,ret_dpm,ret_mr;
XL_SEXP * scale_buf,* minrect;
L_CHAR * r64_type;
XL_SEXP * r64_rect;
int r64_level,cr_type;
int ret_r64_type,ret_r64_rect,ret_r64_level;
int width,height;
int i;
L_CHAR * dummy;
char * e_param;
XL_SEXP * e_data;

	if ( ds == NR_KEEP )
		return 0; 


	get_field(s,
		l_string(std_cm,"scale"),"sexp",&scale_buf,&ret_scale,
		l_string(std_cm,"scan-resolution"),"lf",&dpm,&ret_dpm,&unit,
		0);
	if ( ret_dpm || ret_scale ) {
		e_param = "resource subtype error (resolution or scale)";
		e_data = s;
		goto subtype_error;
	}
	if ( l_strcmp(&r->h.target.resource
			[l_strlen(r->h.target.resource)-4],
			l_string(std_cm,".r64")) == 0 ) {
		r64 = get_r64_meta(s);
		get_field(r64,
		l_string(std_cm,"type"),"s",&r64_type,&ret_r64_type,
		l_string(std_cm,"rect"),"sexp",&r64_rect,&ret_r64_rect,
		l_string(std_cm,"level"),"i",&r64_level,&ret_r64_level,
				&dummy,
			0);
		if ( ret_r64_type || ret_r64_rect || ret_r64_level ) {
			e_param = "resource r64 subtype error";
			e_data = r64;
			goto subtype_error;
		}
		cr_type = 0;
	}
	else {
		r64_type = 0;
		cr = get_cr_meta(s);
		get_field(cr,
		l_string(std_cm,"type"),"i",&cr_type,&ret_r64_type,
				&dummy,
		l_string(std_cm,"rect"),"sexp",&r64_rect,&ret_r64_rect,
		l_string(std_cm,"level"),"i",&r64_level,&ret_r64_level,
				&dummy,
			0);
		if ( ret_r64_type || ret_r64_rect || ret_r64_level ) {
			e_param = "resource CR subtype error";
			e_data = cr;
			goto subtype_error;
		}
	}
	if ( get_type(scale_buf) != XLT_PAIR ) {
		e_param = "resource shukushaku error\n";
		goto invalid_param;
	}
	ss = eval(gblisp_top_env0,scale_buf);
	switch  ( get_type(ss) ) {
	case XLT_INTEGER:
		rate = ss->integer.data;
		break;
	case XLT_FLOAT:
		rate = ss->floating.data;
		break;
	default:
		e_param = "shukushaku eval error\n";
		e_data = scale_buf;
		goto invalid_param;
	}
	dpm = conv_unit(&er,r->h.cu.uenv,
			dpm,unit,reso_c_unit(&r->h.cu));
	ss = get_el(r64_rect,0);
	if ( get_type(ss) != XLT_INTEGER ) {
		e_param = "r64 rect : integer is required";
		e_data = r64_rect;
		goto invalid_param;
	}
	width = ss->integer.data;
	ss = get_el(r64_rect,1);
	if ( get_type(ss) != XLT_INTEGER ) {
		e_param = "r64 rect : integer is required";
		e_data = r64_rect;
		goto invalid_param;
	}
	height = ss->integer.data;

	r->pr64.dpm = rate*dpm;

	if ( r64_type )
		r->pr64.type = r64_type[0];
	else switch ( cr_type ) {
	case 64:
		r->pr64.type = '0';
		break;
	case 128:
		r->pr64.type = '1';
		break;
	case 256:
	default:
		r->pr64.type = '2';
		break;
	}

	for ( i = 0 ; i < r64_level ; i ++ ) {
		r->pr64.width[i] = width;
		r->pr64.height[i] = height;
		if ( width & 1 )
			width = (width>>1) + 1;
		else	width = (width>>1);
		if ( height & 1 )
			height = (height>>1) + 1;
		else	height = (height>>1);
	}
	r->pr64.max_level = r64_level;
	r->pr64.loop_no = 0;
	if ( ds == NR_NEW ) {
		gv_new_luster_option(r,r64_level);
	}
	return 0;
invalid_param:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"gv-new-resource(r64)"),
		List(n_get_string("invalid parameter in the meta info"),
			get_string(l_string(std_cm,e_param)),
			n_get_string("argument"),
			e_data,
			-1));
subtype_error:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"gv-new-resource(r64)"),
		List(n_get_string("invalid subtype in the meta info"),
			get_string(l_string(std_cm,e_param)),
			n_get_string("argument"),
			e_data,
			-1));
}
