/**********************************************************************
 
	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	"pdb.h"
#include	"xl_zlib.h"
#include	"memory_debug.h"
#include	"xl.h"
#include	"win_flame.h"
#include	"xlerror.h"
#include	"gbs_trailer.h"
#include	"gbgraph.h"


typedef struct color_list {
	struct color_list *	next;
	P2D_COL_TRAILER *	c;
} COLOR_LIST;

void
free_color_list(COLOR_LIST * c)
{
COLOR_LIST * c1;
	for ( ; c ; ) {
		c1 = c->next;
		d_f_ree(c);
		c = c1;
	}
}

GB_COLOR * search_color_id(COLOR_LIST * c,int id)
{
COLOR_LIST * cp;
	for ( ; c ; c = c->next )
		if ( c->c->id == id )
			return &c->c->col;
	return 0;
}

int test_min = 100,test_max = -1;

int test_cnt;


XL_SEXP *
_dgb_p2d_trailer(RESOURCE * r,XL_SEXP * data)
{
XLISP_ENV * ee;
L_CHAR * type;
int depth_int;
OBJ * obj;
XL_SEXP * ret;
int i;
P2D_T_SET set;
int size;
P2D_S_PT_TRAILER * pt_s;
P2D_L_PT_TRAILER * pt_l;

GB_COLOR * cp;
COLOR_LIST * col, * c1;
GB_RECT mr;
void * buffer;

int pt_nos,pl_nos,col_nos;

int ins_ret;
GB_POINT prev,next;
GB_RECT d_rect;


	switch ( get_type(data) ) {
	case XLT_NULL:
		return 0;
	case XLT_RAW:
		break;
	default:
		return 0;
	} 
	buffer = zlib_uncompress(
		&size,
		data->raw.data,
		data->raw.size);
	if ( buffer == 0 )
		return 0;
	col = 0;
	set.trailer = (TRAILER*)buffer;
/*
if ( size > 100000 )
printf("size = %s %i\n",n_string(std_cm,get_url_str2(&r->h.target)),size);
printf("size rate %i/%i %f\n",data->raw.size,size,(float)data->raw.size/size);
*/


	d_rect.tl.x = d_rect.tl.y = 0;
	d_rect.br.x = d_rect.br.y = -1;
	for ( ; size > 0 ; ) {
		change_endian_trailer_to_host(set.trailer);
		get_trailer(&set);
		size -= set.size;
		if ( size < 0 )
			break;
		switch ( set.trailer->t_type ) {
		case TT_COLOR:
			c1 = d_alloc(sizeof(*c1),1);
			c1->c = &set.trailer->c;
			c1->next = col;
			col = c1;
			break;

		case TT_P2D:

			lock_pdb_lock(r,1);
			obj = search_obj(r,set.trailer->d_s.code);
r->draw_gb.pdb_lock_msg = 100;
			if ( obj == 0 ) {
				obj = new_object(r,OT_POLYGON2D,
					set.trailer->d_s.code);
				INIT_RING(&obj->polygon2d.point_list);
			}

r->draw_gb.pdb_lock_msg = 101;

			obj->polygon2d.type = set.trailer->d_s.type;
			mr = obj->h.minrect;

r->draw_gb.pdb_lock_msg = 102;
			cp = search_color_id(col,set.trailer->d_s.padding_id);
			if ( cp )
				get_gb_color(&obj->h.palette.padding_color,cp);
			cp = search_color_id(col,set.trailer->d_s.line_id);
			if ( cp )
				get_gb_color(&obj->h.palette.line_color,cp);
r->draw_gb.pdb_lock_msg = 103;
			for ( i = 0 ; i < set.trailer->d_s.pnos ; i ++ ) {
				pt_s = &set.trailer->d_s.p[i];
				if ( inside_rect(&r->h.minrect,pt_s->p) == 0 )
					continue;

r->draw_gb.pdb_lock_msg = 104;

				ins_ret = insert_point(
					r,
					obj,
					&obj->polygon2d.point_list,
					PP_TO_L(pt_s->no),
					pt_s->p.x,
					pt_s->p.y,
					pt_s->lod_min,
					pt_s->lod_max,
					&prev,
					&next,
					obj->h.code);
r->draw_gb.pdb_lock_msg = 105;
				insert_rect(&mr,pt_s->p);
				insert_rect(&d_rect,&pt_s->p);
				if ( ins_ret & 1 )
					insert_rect(&d_rect,prev);
				if ( ins_ret & 2 )
					insert_rect(&d_rect,next);

				if ( obj->h.lod_min < 0 ) {
					obj->h.lod_min = pt_s->lod_min;
					obj->h.lod_max = pt_s->lod_max;
				}
				else {
					if ( pt_s->lod_min < obj->h.lod_min )
						obj->h.lod_min = pt_s->lod_min;
					if ( pt_s->lod_max > obj->h.lod_max )
						obj->h.lod_max = pt_s->lod_max;
				}
r->draw_gb.pdb_lock_msg = 106;
			}
r->draw_gb.pdb_lock_msg = 107;
			if ( obj->h.minrect.tl.x >
					obj->h.minrect.br.x ) {
				obj->h.minrect = mr;
r->draw_gb.pdb_lock_msg = 108;
				insert_rect_tree(
					&r->draw_gb.obj_rect_tree,
					obj);
			}
			else if ( mr.tl.x != obj->h.minrect.tl.x ||
				mr.tl.y != obj->h.minrect.tl.y ||
				mr.br.x != obj->h.minrect.br.x ||
				mr.br.y != obj->h.minrect.br.y ) {
r->draw_gb.pdb_lock_msg = 109;

				delete_rect_tree(
					&r->draw_gb.obj_rect_tree,
					obj);
				obj->h.minrect = mr;
				insert_rect_tree(
					&r->draw_gb.obj_rect_tree,
					obj);
			}
			r->draw_gb.flags |= DGF_POLY;
r->draw_gb.pdb_lock_msg = 110;
			unlock_pdb_lock(r);
r->draw_gb.pdb_lock_msg = 111;
			break;
		case TT_L_P2D:

			lock_pdb_lock(r,2);
			obj = search_obj(r,set.trailer->d_l.code);
			if ( obj == 0 ) {
				obj = new_object(r,OT_POLYGON2D,
					set.trailer->d_l.code);
				INIT_RING(&obj->polygon2d.point_list);
			}

			obj->polygon2d.type = set.trailer->d_l.type;
			mr = obj->h.minrect;

			cp = search_color_id(col,set.trailer->d_l.padding_id);
			if ( cp )
				get_gb_color(&obj->h.palette.padding_color,cp);
			cp = search_color_id(col,set.trailer->d_l.line_id);
			if ( cp )
				get_gb_color(&obj->h.palette.line_color,cp);
			for ( i = 0 ; i < set.trailer->d_l.pnos ; i ++ ) {
				pt_l = &set.trailer->d_l.p[i];
				if ( inside_rect(&r->h.minrect,pt_l->p) == 0 )
					continue;
				ins_ret = insert_point(
					r,
					obj,
					&obj->polygon2d.point_list,
					pt_l->no,
					pt_l->p.x,
					pt_l->p.y,
					pt_l->lod_min,
					pt_l->lod_max,
					&prev,
					&next,
					obj->h.code);
				insert_rect(&mr,pt_l->p);
				insert_rect(&d_rect,&pt_l->p);
				if ( ins_ret & 1 )
					insert_rect(&d_rect,prev);
				if ( ins_ret & 2 )
					insert_rect(&d_rect,next);

				if ( obj->h.lod_min < 0 ) {
					obj->h.lod_min = pt_l->lod_min;
					obj->h.lod_max = pt_l->lod_max;
				}
				else {
					if ( pt_l->lod_min < obj->h.lod_min )
						obj->h.lod_min = pt_l->lod_min;
					if ( pt_l->lod_max > obj->h.lod_max )
						obj->h.lod_max = pt_l->lod_max;
				}
			}
			if ( obj->h.minrect.tl.x >
					obj->h.minrect.br.x ) {
				obj->h.minrect = mr;
				insert_rect_tree(
					&r->draw_gb.obj_rect_tree,
					obj);
			}
			else if ( mr.tl.x != obj->h.minrect.tl.x ||
				mr.tl.y != obj->h.minrect.tl.y ||
				mr.br.x != obj->h.minrect.br.x ||
				mr.br.y != obj->h.minrect.br.y ) {

				delete_rect_tree(
					&r->draw_gb.obj_rect_tree,
					obj);
				obj->h.minrect = mr;
				insert_rect_tree(
					&r->draw_gb.obj_rect_tree,
					obj);
			}
			r->draw_gb.flags |= DGF_POLY;
			unlock_pdb_lock(r);
			break;
		}
		set.trailer = set.next;
	}
r->draw_gb.pdb_lock_msg = 112;
	free_color_list(col);
r->draw_gb.pdb_lock_msg = 113;
	d_f_ree(buffer);
r->draw_gb.pdb_lock_msg = 114;

	wf_insert_dirty_rect(r,&d_rect,WFF_POLY_DIRTY,10,10);

r->draw_gb.pdb_lock_msg = 115;

	return 0;
}


XL_SEXP *
dgb_p2d_trailer(XLISP_ENV * e,XL_SEXP * s)
{
XL_SEXP * data;
RESOURCE * r;
XL_SEXP * ret;
	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_polygon2d(2)");
	data = get_el(s,1);
	if ( get_type(data) != XLT_RAW )
		goto type_missmatch;

	return _dgb_p2d_trailer(r,data);
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"p2d-trailer"),
		List(n_get_string("type missmatch"),-1));
}
