/**********************************************************************
 
	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	<math.h>
#include	<stdlib.h>
#include	"memory_debug.h"
#include	"xl.h"
#include	"gbview.h"
#include	"xlerror.h"
#include	"gbs_trailer.h"

#define SELECT_OFS	5

XL_SEXP *
dgb_mark(XLISP_ENV * e,XL_SEXP * s,
	XLISP_ENV * a,
	XL_SYM_FIELD * sf)
{
RESOURCE * r;
L_CHAR * url;
L_CHAR * id;
int _id;
int align;
int t_color,er;
int depth_int;
char * e_param;
XL_SEXP * ret;
OBJ * obj;
GB_POINT ptr;
XL_SEXP * p;
XL_SEXP * x, * y;

	align = AG_TB_CENTER|AG_LR_CENTER;
	t_color = C_TRANSPARENT;
	id = 0;
	for ( ; sf ; sf = sf->next ) {
		if ( l_strcmp(sf->name,l_string(std_cm,"img")) == 0 ) {
			url = sf->data;
		}
		else if ( l_strcmp(sf->name,l_string(std_cm,"name")) == 0 ) {
			id = sf->data;
		}
		else if ( l_strcmp(sf->name,l_string(std_cm,"code")) == 0 ) {
			id = sf->data;
		}
		else if ( l_strcmp(sf->name,
				l_string(std_cm,"halign")) == 0 ) {
			if ( l_strcmp(sf->data,
				l_string(std_cm,"left")) == 0 ) {

				align &= ~AG_LR_MASK;
				align |= AG_LR_LEFT;
			}
			else if ( l_strcmp(sf->data,
				l_string(std_cm,"right")) == 0 ) {

				align &= ~AG_LR_MASK;
				align |= AG_LR_RIGHT;
			}
			else if ( l_strcmp(sf->data,
				l_string(std_cm,"center")) == 0 ) {

				align &= ~AG_LR_MASK;
				align |= AG_LR_CENTER;
			}
			else {
				e_param = "halign";
				goto param_error;
			}
		}
		else if ( l_strcmp(sf->name,
				l_string(std_cm,"valign")) == 0 ) {
			if ( l_strcmp(sf->data,
				l_string(std_cm,"top")) == 0 ) {

				align &= ~AG_TB_MASK;
				align |= AG_TB_TOP;
			}
			else if ( l_strcmp(sf->data,
				l_string(std_cm,"bottom")) == 0 ) {

				align &= ~AG_TB_MASK;
				align |= AG_TB_BOTTOM;
			}
			else if ( l_strcmp(sf->data,
				l_string(std_cm,"center")) == 0 ) {

				align &= ~AG_TB_MASK;
				align |= AG_TB_CENTER;
			}
			else {
				e_param = "valign";
				goto param_error;
			}
		}
		else if ( l_strcmp(sf->name,
				l_string(std_cm,"transparent")) == 0 ) {
		char * dt;
			dt = n_string(std_cm,sf->data);
			sscanf(&dt[1],"%x",&t_color);
			t_color = 
				((t_color&0xff)<<(COL_BIT-8))|
				((t_color&0xff00)<<((COL_BIT-8)*2))|
				((t_color&0xff0000)<<((COL_BIT-8)*3));
		}
	}
	if ( id == 0 ) {
		goto required_name;
	}
	if ( list_length(s) == 2 ) {
		p = get_el(s,1);
		if ( get_type(p) != XLT_PAIR )
			goto type_missmatch;
	}
	else {
		p = cdr(s);
	}
	if ( list_length(p) != 2 )
		goto type_missmatch;
	x = get_el(p,0);
	switch ( get_type(x) ) {
	case XLT_ERROR:
		return x;
	case XLT_INTEGER:
		er = 0;
		ptr.x = conv_unit(&er,
				get_uenv(gblisp_top_env0),
				x->integer.data,
				x->integer.unit,
				l_string(std_cm,"m"));
		break;
	case XLT_FLOAT:
		er = 0;
		ptr.x = conv_unit(&er,
				get_uenv(gblisp_top_env0),
				x->floating.data,
				x->floating.unit,
				l_string(std_cm,"m"));
		break;
	default:
		goto type_missmatch;
	}
	y = get_el(p,1);
	switch ( get_type(y) ) {
	case XLT_ERROR:
		return y;
	case XLT_INTEGER:
		er = 0;
		ptr.y = conv_unit(&er,
				get_uenv(gblisp_top_env0),
				y->integer.data,
				y->integer.unit,
				l_string(std_cm,"m"));
		break;
	case XLT_FLOAT:
		er = 0;
		ptr.y = conv_unit(&er,
				get_uenv(gblisp_top_env0),
				y->floating.data,
				y->floating.unit,
				l_string(std_cm,"m"));
		break;
	default:
		goto type_missmatch;
	}
	r = get_resource_ptr(&ret,e,s->h.file,s->h.line);
	if ( r == 0 )
		return ret;
	if ( r->h.type != RT_DRAW_GB )
		er_panic("dgb_mark(2)");
	lock_pdb_lock(r,0);
	sscanf(n_string(std_cm,id),"%i",&_id);
	obj = search_obj(r,_id);
	if ( obj == 0 ) {
		obj = new_object(r,OT_MARK,_id);
		obj->mark.path = 0;
	}
	if ( obj->mark.path )
		d_f_ree(obj->mark.path);
	obj->mark.path = compose_url(get_url_str2(&r->h.target),url);
	obj->mark.t_color = t_color;
	obj->mark.align = align;
	obj->mark.pt = ptr;
	obj->h.minrect.tl = obj->h.minrect.br = ptr;

	insert_rect_tree(
		&r->draw_gb.obj_rect_tree,
		obj);

	r->draw_gb.flags |= DGF_MARK;
	unlock_pdb_lock(r);

	return 0;

required_name:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_UNDEF_NAME,
		l_string(std_cm,"mark"),
		List(n_get_string("id is required"),-1));
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"mark"),
		List(n_get_string("type missmatch"),-1));
param_error:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"mark"),
		List(n_get_string("invalid parameter of the attribute"),
			n_get_string(e_param),-1));
}

int
draw_mark(
	GBVIEW_FLAME * gf,
	OBJ * o,
	DRAW_WORK * dw)
{
GB_POINT p1,p2,last;
POINT_LIST * p,* pp;
REAL1 er;
int x,y,w,h;
int xx,yy,x_cnt,y_cnt;
int * data;
unsigned int * dt;
XL_SEXP * ret;
int pic_w,pic_h;
int dx,dy;
int dd;
GB_RECT rect;
int i;


	if ( dw->method == 0 )
		return 0; 
	p1 = o->mark.pt;
	er = 1;
	map_conv_forward(dw->map->map_file,&p1,&er,1);
	map_from_resource(dw->mh,&p1,&er,1);
	if ( er < 0 )
		return -1;
	data = get_ri(&w,&h,gf,dw->wfid,o->mark.path);
	if ( data == 0 ) {
		return -1;
	}
	switch ( o->mark.align & AG_LR_MASK ) {
	case AG_LR_LEFT:
		x = p1.x;
		break;
	case AG_LR_CENTER:
		x = p1.x - w/2;
		break;
	case AG_LR_RIGHT:
		x = p1.x - w;
		break;
	}
	switch ( o->mark.align & AG_TB_MASK ) {
	case AG_TB_TOP:
		y = p1.y;
		break;
	case AG_TB_CENTER:
		y = p1.y - h/2;
		break;
	case AG_TB_BOTTOM:
		y = p1.y - h;
		break;
	}

	dt = d_alloc(w*h*sizeof(int));
	memcpy(dt,data,w*h*sizeof(int));
	for ( i = 0 ; i < w*h ; i ++ )
		if ( dt[i] == o->mark.t_color )
			dt[i] = C_TRANSPARENT;

	rect.tl.x = x;
	rect.tl.y = y;
	rect.br.x = x + w;
	rect.br.y = y + h;

	wf_insert_si(
		gf,
		ISI_INSERT,
		dw->wfid,
		dw->resource->h.no,
		o->h.code,
		0,
		&rect,
		dt,
		0,
		SIF_ANCOR,
		0);

	if ( (o->h.flags & OF_INFO_STS) != OF_INFO_FETCH )
		o->h.flags |= OF_ONMAP_REQ;

	p1.x = rect.br.x + 3;
	p1.y = rect.br.y;
	indicate_onmap(gf,1,dw->wfid,dw->resource,o,p1);

	return 0;
}

int
get_point_mark(
	GBVIEW_FLAME * gf,
	RESOURCE * r,
	OBJ * o,
	GET_POINT_WORK * w)
{
	return 0;
}


void
free_mark(
	OBJ * o)
{
	d_f_ree(o->mark.path);
	d_f_ree(o);
}


int
select_mark(
	OBJ * o,
	SELECT_WORK * sw)
{
GB_POINT p1,p2,last;
POINT_LIST * p,* pp;
REAL1 er;
GB_RECT minrect;
int w,h,i;
int ww,hh;

	if ( sw->select_obj != o )
		return 0;
	if ( get_ri(&w,&h,0,0,o->mark.path) == 0 )
		return 0;
	p1 = o->mark.pt;
	er = 1;
	map_conv_forward(sw->map->map_file,&p1,&er,1);
	map_from_resource(sw->mh,&p1,&er,1);
	switch ( o->mark.align & AG_LR_MASK ) {
	case AG_LR_LEFT:
		minrect.tl.x = p1.x - SELECT_OFS;
		break;
	case AG_LR_CENTER:
		minrect.tl.x = p1.x - w/2 - SELECT_OFS;
		break;
	case AG_LR_RIGHT:
		minrect.tl.x = p1.x - w - SELECT_OFS;
		break;
	}
	switch ( o->mark.align & AG_TB_MASK ) {
	case AG_TB_TOP:
		minrect.tl.y = p1.y - SELECT_OFS;
		break;
	case AG_TB_CENTER:
		minrect.tl.y = p1.y - h/2 - SELECT_OFS;
		break;
	case AG_TB_BOTTOM:
		minrect.tl.y = p1.y - h - SELECT_OFS;
		break;
	}
	minrect.br.x = minrect.tl.x + w + SELECT_OFS*2+1;
	minrect.br.y = minrect.tl.y + h + SELECT_OFS*2+1;
	ww = minrect.br.x - minrect.tl.x;
	hh = minrect.br.y - minrect.tl.y;
	sw->si->pixels = d_alloc(sizeof(long)*ww*hh);
	for ( i = 0 ; i < ww*hh ; i ++ )
		sw->si->pixels[i] = C_TRANSPARENT;
	sw->si->x = minrect.tl.x;
	sw->si->y = minrect.tl.y;
	sw->si->w = ww;
	sw->si->h = hh;

	for ( i = 0 ; i < ww ; i ++ ) {
		sw->si->pixels[i] = put_color(
			sw->si->pixels[i],
			&sw->color);
		sw->si->pixels[i+ww*(hh-1)] = put_color(
			sw->si->pixels[i+ww*(hh-1)],
			&sw->color);
	}
	for ( i = 0 ; i < hh ; i ++ ) {
		sw->si->pixels[i*ww] = put_color(
			sw->si->pixels[i],
			&sw->color);
		sw->si->pixels[ww-1+ww*i] = put_color(
			sw->si->pixels[ww-1+ww*i],
			&sw->color);
	}
	return 1;
}


int
olist_mark(OBJ * o,XL_SEXP ** ret)
{
XL_SEXP * header;
	header = get_object_header(o);
	*ret = cons(get_symbol(l_string(std_cm,"mark")),
		append(header,
		List(
			List(get_symbol(l_string(std_cm,"uri")),
				get_string(o->mark.path),
				-1),
			List(get_symbol(l_string(std_cm,"align")),
				get_integer(o->mark.align,0),
				-1),
			List(get_symbol(l_string(std_cm,"transparent")),
				get_integer(o->mark.t_color,0),
				-1),
			List(get_symbol(l_string(std_cm,"point")),
				get_floating(o->mark.pt.x,
					l_string(std_cm,"m")),
				get_floating(o->mark.pt.y,
					l_string(std_cm,"m")),
				-1),
			-1)));
	return 0;
}
