#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grass/gis.h>
#include <grass/Vect.h>
#include "conv.h"
#include "local_proto.h"
#include <grass/glocale.h>

int 
old2new (char *in, char *out, int endian)
{
    int    i, j, nlines, ncats, sline, att;
    char   *mapset;
    FILE   *Digin, *Attin;
    struct Line *lines;  /* array of points and lines */
    struct Categ *cats;  /* array of categories */
    struct Map_info Mapout;
    double dist, sdist;
    struct line_cats *cat_out;
    struct line_pnts *pnt_out;
   
    cats = NULL;
    
    /* open in map */
    if ( NULL == (mapset = G_find_file ("dig", in, "") )) {
	G_fatal_error( _("Input vector was not found.")) ;
    }

    /* open input dig file */
    if ((Digin  = G_fopen_old ("dig", in, mapset)) == NULL ) {
        G_fatal_error( _("Failed opening input dig file.")) ;
    } 

    /* open new output file */
    Vect_set_fatal_error (GV_FATAL_PRINT);
    if ( Vect_open_new ( &Mapout, out, WITHOUT_Z) < 0) {
	fclose (Digin);
    	exit(-1);
    }  

    Vect_hist_command ( &Mapout );
    
    /* open input dig_att file if exists */
    att = FALSE;
    if (NULL == G_find_file ("dig_att", in, mapset)) {
    	G_warning ( _("dig_att file doesn't exist.")); 
    } else {
        if (NULL == (Attin = G_fopen_old ("dig_att", in, mapset))) {
    	    G_warning ( _("Failed opening input dig_att file.")); 
	} else {
	   att = TRUE;
	}
    }
   
    /* read old dig file */
    nlines = read_dig ( Digin, &Mapout, &lines, endian, att );

    /* read old dig_att file */
    ncats = 0;
    if ( att ) {
            ncats = read_att (Attin, &cats );
            fclose (Attin);
    }
     	
    /* Attach categories to lines and points.
     * Walk through all cats and always find nearest line.
     * If cat is already attached but new one is nearer
     * set cat to new one.  */
     
     G_message ( _("Attaching categories...\n"));
     
     for (i=0; i < ncats; i++){
	 G_percent ( i, ncats - 1, 1 ); 
         if ( cats[i].type & (GV_POINT | GV_LINE) ) {
		sline = -1;
                for (j=0; j < nlines; j++){
                    if (lines[j].type == cats[i].type) {
	                dist = ldist ( cats[i].x, cats[i].y, 
				       &(lines[j]));
			
			if (sline == -1 || dist < sdist){
			    sline = j;
			    sdist = dist;
			}
		    }
	        }
		if ( sline == -1 ) {
                    G_warning ( _("Failed to attach an attribute (category %d) to a line."), cats[i].cat);
		} else {
	            if ( lines[sline].cat > -1 ) {
                        G_warning ( _("WARNING: line %d label: %d matched another label: %d."), sline, lines[sline].cat, cats[i].cat);
		    }
	            lines[sline].cat = cats[i].cat;
		}
	}
    }
     
    /* Write to new file */
    G_message ( _("Writing new file...\n"));
    pnt_out = Vect_new_line_struct ();
    cat_out = Vect_new_cats_struct();
    
    j = 0;
    /* Write all points and lines if dig_att exists */
    if (att) {
        for (i=0; i < nlines; i++) {
            if ( lines[i].cat > 0 ) {
	        Vect_cat_set ( cat_out, 1, lines[i].cat );
	    }
            dig_alloc_points ( pnt_out, lines[i].n_points );
	    memcpy ( (void *) pnt_out->x, (void *) lines[i].x,
		     lines[i].n_points * sizeof(double)); 
	    memcpy ( (void *) pnt_out->y, (void *) lines[i].y,
		     lines[i].n_points * sizeof(double)); 
	    pnt_out->n_points = lines[i].n_points;
            Vect_write_line ( &Mapout, lines[i].type, pnt_out, cat_out );
	    j++;
            Vect_reset_cats (cat_out);
        }
        G_message ( _("%-5d points and lines written to output file.\n"),j);
    }
    /* Write centroids */    
    j = 0;
    for (i=0; i < ncats; i++) {
        if ( cats[i].type == GV_CENTROID ){
            Vect_append_point ( pnt_out, cats[i].x, cats[i].y, 0.0); 
	    Vect_cat_set ( cat_out, 1, cats[i].cat );
            Vect_write_line ( &Mapout, GV_CENTROID, pnt_out, cat_out );
	    j++;
	    Vect_reset_line (pnt_out);
            Vect_reset_cats (cat_out);
	}
    } 
    G_message ( _("%-5d centroids written to output file.\n"),j);

    /* Convert dig_cats to table */
    attributes ( in, &Mapout );
    
    Vect_build ( &Mapout, stdout );  
    Vect_close ( &Mapout );
    
    fclose (Digin);

    /* free memory */
    for (i=0; i < nlines; i++) {
	G_free (lines[i].x);    
	G_free (lines[i].y);    
    }
    G_free (lines);
    if (att)
        G_free (cats);
    
    Vect_destroy_cats_struct (cat_out);
    Vect_destroy_line_struct (pnt_out);
    
    return (1);
}


