/**********************************************************************
 
	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 "vpf_std.h"
#include "gm_svg_util.h"
#include "vpf_util.h"
#include "coordinate_conv.h"
#include "gm_convert_env.h"

GM_SVG_FILE *gm_svg_write_begin(const char *filename, VPF_TABLE_TYPE type, const GM_SVG_COLOR_TABLE *color_table)
{
	int i;
	GM_SVG_FILE *ret;
	ret = (GM_SVG_FILE *)calloc(sizeof(GM_SVG_FILE),1);
	ret->type = type;
	ret->fp = fopen(filename, "w");
	if(ret->fp == NULL){
		printf("error: open file %s for write\n", filename);
		free(ret);
		return NULL;
	}
	// svg header place holder
	for(i=0; i<256; ++i){
		fwrite(" ", 1, 1, ret->fp );
	}
	ret->max_rect.is_null = TRUE;
	ret->color_table = color_table;
	return ret;
}

void gm_svg_write_end(GM_SVG_FILE *fp){
	const char *line_color;
	const char *fill_color;
	int end_pos;
	if(!fp){
		return;
	}
	if(fp->fp){
		end_pos = ftell(fp->fp);
		fseek(fp->fp, 0, SEEK_SET);
		fprintf(fp->fp, "<?xml version=\"1.0\"?>\n");
		fprintf(fp->fp, "<svg viewBox=\"%f %f %f %f\">\n", 
			fp->max_rect.left, 
			fp->max_rect.top, 
			fp->max_rect.right-fp->max_rect.left, 
			fp->max_rect.bottom-fp->max_rect.top);
		line_color = fp->color_table->line_colors[fp->type];
		fill_color = fp->color_table->fill_colors[fp->type];
		if(line_color==NULL){
			line_color = "none";
		}
		if(fill_color==NULL){
			fill_color = "none";
		}
		fprintf(fp->fp, "<g style=\"stroke:%s;stroke-width:0.001;fill:%s\">", line_color, fill_color);
		
		fseek(fp->fp, end_pos, SEEK_SET);
		fprintf(fp->fp, "</g>\n");
		fprintf(fp->fp, "</svg>\n");
		
		fclose(fp->fp);
	}
	free(fp);
}

void gm_write_coordinates_svg(GM_SVG_FILE *fp, VPF_LIST* coordinates, BOOL is_first_coordinates){
VPF_LIST_ITEM *i;
VPF_COORDINATE* coordinate;

	for(i = coordinates->head; i; i=i->next){
		coordinate = (VPF_COORDINATE*)(i->data);
		if(is_first_coordinates && i==coordinates->head)
		{
			fprintf(fp->fp, "M %f %f", coordinate->x, coordinate->y);
		}
		else
		{
			fprintf(fp->fp, " L %f %f", coordinate->x, coordinate->y);
		}
		vpf_max_rect_xy(&fp->max_rect, coordinate->x, coordinate->y);
	}
	
}

void gm_write_node_svg(
		GM_SVG_FILE *fp, 
		VPF_NODE_RECORD *node, 
		const char *edge_code_name){
LONG_FLOAT r=0.005;
VPF_COORDINATE *c;
	c = &node->coordinate;
	fprintf(fp->fp, "<path id=\"%s\" d=\"", edge_code_name);
	fprintf(fp->fp, "M%f,%f", c->x-r, c->y-r);
	fprintf(fp->fp, " L%f,%f", c->x+r, c->y-r);
	fprintf(fp->fp, " L%f,%f", c->x+r, c->y+r);
	fprintf(fp->fp, " L%f,%fz", c->x-r, c->y+r);
	fprintf(fp->fp, "\" />\n");
	
	vpf_max_rect_xy(&fp->max_rect, c->x-r, c->y-r);
	vpf_max_rect_xy(&fp->max_rect, c->x+r, c->y+r);

}
void gm_write_edge_svg(
		GM_SVG_FILE *fp, 
		VPF_EDGE_RECORD *edge, 
		const char *edge_code_name){

	fprintf(fp->fp, "<path id=\"%s\" d=\"", edge_code_name);
	gm_write_coordinates_svg(fp, edge->coordinates, TRUE);
	fprintf(fp->fp, "\" />\n");
}


void gm_write_face_edges_svg(
	GM_SVG_FILE *fp, VPF_LIST *edges, const char *face_code_name){
VPF_LIST_ITEM *i;
VPF_EDGE_RECORD *edge;
VPF_EDGE_RECORD *next_edge;
VPF_LIST* coordinates;
VPF_LIST* inverted_coordinates;
BOOL invert_flag;

	fprintf(fp->fp, "<path id=\"%s\" d=\"", face_code_name);
	invert_flag=FALSE;

	for(i = edges->head; i; i=i->next){
		edge = (VPF_EDGE_RECORD*)(i->data);
		if(edge->coordinates->head==NULL)
			continue;
		
		inverted_coordinates = NULL;

		if(i==edges->head && i->next){
			next_edge = (VPF_EDGE_RECORD*)(i->next->data);
			if(vpf_coordinate_equals(edge->coordinates->head->data, next_edge->coordinates->head->data) ||
				vpf_coordinate_equals(edge->coordinates->head->data, next_edge->coordinates->tail->data)
				){
				invert_flag=TRUE;
			}
		}
		
		if(invert_flag){
			inverted_coordinates = vpf_list_new(NULL);
			vpf_list_invert(inverted_coordinates, edge->coordinates);
			coordinates = inverted_coordinates;
		}
		else{
			coordinates = edge->coordinates;
		}
		
		gm_write_coordinates_svg(fp, coordinates, i == edges->head);
		
		if(i->next){
			next_edge = (VPF_EDGE_RECORD*)(i->next->data);
			if(vpf_coordinate_equals(coordinates->tail->data, next_edge->coordinates->tail->data)){
				invert_flag=TRUE;
			}
			else{
				invert_flag=FALSE;
			}
		}
		
		vpf_list_delete(inverted_coordinates);
	}
	fprintf(fp->fp, "z\" />\n");
}
			
void gm_svg_make_code_name(char *code_name, const GM_TILEREF_AFT_RECORD *tile, LONG primitive_id)
{
	sprintf(code_name, "%s_%d", tile->tile_name, (int)primitive_id);
}
