/* Function: vect_legend
**
** Author: Paul W. Carlson	April 1992
** Modified by: Radim Blazek Jan 2000 area, label added 
** Modified by: Morten Hulden Mar 2004, support for legend in columns added 
*/

#include "vector.h"
#include "ps_info.h"
#include "local_proto.h"

int PS_vlegend (void)
{
    int h, i, j, k, l, lc, st, lcount, nopos;
    double x, y, fontsize, dx, dy, xo, yo, xs, ys, margin, width;
    double llx, lly, urx, ury, sc;
    char pat[50];
    int **vec, *nvec;

    G_debug (2, "vect_legend(): count = %d", vector.count );

    vec = (int **) G_malloc ( vector.count * sizeof(int *) );
    for ( i = 0; i < vector.count; i++ ) 
        vec[i] = (int *) G_malloc ( vector.count * sizeof(int) );
    nvec = (int *) G_malloc ( vector.count * sizeof(int) );
    
    /* vec[][] is array of vectors on each row of legend, first to be drawn is first in array,
     *         label is stored in last in row (last plotted, first in the script)
     * nvec[] is number of vector on each row 
     *        index for both start at 0, lpos in script starts from 1
     * If position is not used by any vector it is used for next not used vector without
     * lpos or lpos > vector.count */

    nopos = -1; /* last used without position in script or position > count */

    for ( l = 0; l < vector.count; l++ ) {
	nvec[l] = 0;
	for ( i = vector.count-1; i >= 0; i-- ) { /* last in script plot first */
	    if ( vector.layer[i].lpos == l+1 ) {
		vec[l][nvec[l]] = i;
		nvec[l]++;
	    }
	}
	if ( nvec[l] == 0 ) { /* no vector with this lpos */
	    for ( i = nopos + 1; i < vector.count; i++ ) { 
		/* first in script (most important) in script plot first */
		if ( vector.layer[i].lpos == -1 || vector.layer[i].lpos > vector.count ) {
		    vec[l][0] = i;
		    nvec[l]++;
		    nopos = i;
		    break;
		}
	    }
	}
    }

    /* find last used row */
    lcount = 0; /* number of used rows in legend */
    for ( i = vector.count-1; i >=0; i-- ) {
	if ( nvec[i] > 0 ) {
	    lcount = i + 1;
	    break;
	}
    }

    /* set font */
    fontsize = (double)vector.fontsize;
    fprintf(PS.fp, "(%s) FN %.1f SF\n", vector.font, fontsize);

    /* get text location */
    dy = 1.5 * fontsize;
    if (vector.x > 0.0) x = 72.0 * vector.x;
    else x = PS.map_left;
    if (vector.y > 0.0) y = 72.0 * (PS.page_height - vector.y);
    else if (vector.x <= 0.0) y = PS.min_y;
    else y = PS.map_bot;
    margin = 0.4 * fontsize;
    if (x < PS.map_left + margin) x = PS.map_left + margin;

    if (lcount < vector.cols) vector.cols = lcount;
    dx = (PS.map_right - x) / vector.cols;
    xs = x; /*save x and y*/
    ys = y;
    lc = (int) lcount/vector.cols; /* lines per column */
    if (lcount%vector.cols) lc++;
    
    for ( h = 0; h < vector.cols; h++) { 

	y = ys;
	if (h) x+=dx;
	st = ((h+1)*lc < lcount) ? ((h+1)*lc) : lcount;

	/* make PostScript array "a" of name-mapset strings */
	fprintf(PS.fp, "/a [\n");

	for ( i = h*lc; i < st; i++ ) {
    	    G_debug (4, "  row = %d", i );
	    if ( nvec[i] > 0 ) { /* used position */
		j = vec[i][nvec[i]-1]; /* vector with label */
		if ( vector.layer[j].label == NULL )
		    fprintf(PS.fp, "( %s (%s))\n", vector.layer[j].name, vector.layer[j].mapset);
		else		
		    fprintf(PS.fp, "( %s)\n", vector.layer[j].label);
	    } else { /* not used -> empty string */
		fprintf(PS.fp, "( )\n" );
	    }
	}
	fprintf(PS.fp, "] def\n");

	width = 72.0 * vector.width;
	if(width <= 0.0)
	    width = 2.4 * fontsize;

/* HB 2006: always figure width & draw so the border will always work. */
	/* if vector legend is on map... */
/* 	if (y > PS.map_bot && y <= PS.map_top && x < PS.map_right) {   */
	    fprintf(PS.fp, "/mg %.1f def\n", margin);

    	    /* get width of widest string in PostScript variable "w" */
    	    fprintf(PS.fp, "/w 0 def 0 1 a length 1 sub { /i XD\n");
    	    fprintf(PS.fp, "a i get SW pop /t XD t w gt {/w t def} if } for\n");
    	    fprintf(PS.fp, "/w w %.1f add mg add %.1f add def\n", x, width);

    	    /* make white background for text */
    	    fprintf(PS.fp, "1 1 1 C ");
    	    fprintf(PS.fp, "%.1f %.1f w %.1f B fill \n", 
		x - margin,  y - lc * dy - margin, y);
/*	} */

	/* draw the border, if set */
	if(vector.border != -1) {
	    set_rgb_color(vector.border);

	    fprintf(PS.fp, "%.1f %.1f w %.1f B\n",
		x - margin,  y - lc * dy - margin, y);
	    fprintf(PS.fp, "D\n");
	}

	/* make the legend */
	for ( j = h*lc; j < st; j++ ) { /* each row */
    	    G_debug (4, "  row = %d", j );
	    y -= dy; /* set position of next row */
	    for (k = 0; k < nvec[j]; k++) {
		i = vec[j][k]; 

		/* make a grey box if needed */
		/* TODO */
		/*
		if ((vector.layer[i].hwidth > 0. && vector.layer[i].hcolor == WHITE) ||
		    (vector.layer[i].hwidth < 1. && vector.layer[i].colors[0]  == WHITE))
		{
		    fprintf(PS.fp, "0.5 setgray ");
		    fprintf(PS.fp, "%.1f %.1f %.1f %.1f B fill \n", 
			x, y, x + 72.0, y + fontsize);
		}
		*/

		if ( vector.layer[i].type == VAREAS ) {  /* added for areas */
		    /* plot rectangle */
		    yo = y - 0.1 * fontsize;

		    if(vector.layer[i].pat != NULL || !(color_none(&vector.layer[i].fcolor))) {

			if( vector.layer[i].pat != NULL ) {   /* use pattern */
			    sc = 0.5 * vector.layer[i].scale;  /* half scale */

			    /* load pattern */
			    eps_bbox( vector.layer[i].pat , &llx, &lly, &urx, &ury);
			    sprintf ( pat, "APATTEPS%d", i);

			    fprintf(PS.fp, "<<  /PatternType 1\n    /PaintType 1\n    /TilingType 1\n");
			    fprintf(PS.fp, "    /BBox [%f %f %f %f]\n", llx*sc, lly*sc, urx*sc, ury*sc);
			    fprintf(PS.fp, "    /XStep %f\n    /YStep %f\n", (urx-llx)*sc, (ury-lly)*sc);
			    fprintf(PS.fp, "    /PaintProc\n      { begin\n");
			    fprintf(PS.fp, "        %f %f scale\n", sc, sc);
			    set_ps_color ( &(vector.layer[i].fcolor) );
			    fprintf(PS.fp, "        %.8f W\n", vector.layer[i].pwidth );
			    fprintf(PS.fp, "        %s\n", pat);
			    fprintf(PS.fp, "        end\n");
			    fprintf(PS.fp, "      } bind\n>>\n");
			    sprintf ( pat, "APATT%d", i);
			    fprintf(PS.fp, " matrix\n makepattern /%s exch def\n", pat);
			    fprintf(PS.fp, "/Pattern setcolorspace\n %s setcolor\n", pat);
			}
			else  /* solid fill color */
			    set_ps_color( &(vector.layer[i].fcolor) );

			fprintf(PS.fp, "%.1f %.1f %.1f %.1f rectfill\n",
		    	    x + width/5, yo , 3 * width / 5, 0.8 * fontsize);
		    }
		    if ( !color_none( &vector.layer[i].color) && vector.layer[i].width > 0 ) {	
			fprintf(PS.fp, "%.8f W\n", vector.layer[i].width );
			set_ps_color( &(vector.layer[i].color) );
			fprintf(PS.fp, "[] 0 setdash\n");
			fprintf(PS.fp, "%.1f %.1f %.1f %.1f rectstroke\n",
			    x + width/5, yo, 3 * width / 5, 0.8 * fontsize);
		    }	    
		} else if ( vector.layer[i].type == VLINES ) {
		    yo = y + 0.35 * fontsize - vector.layer[i].offset; 
		    /* do highlight, if any */
		    if (vector.layer[i].hwidth) {
			set_ps_color( &(vector.layer[i].hcolor) );
			fprintf(PS.fp, "%.8f W\n",  
			  vector.layer[i].width + 2 * vector.layer[i].hwidth);
			fprintf(PS.fp, "[] 0 setdash\n");
			fprintf(PS.fp, "%.1f %.1f %.1f %.1f L\n", x + width, yo, x, yo);
		    }

		    /* plot the primary color line */
		    set_ps_color( &(vector.layer[i].color) );
		    fprintf(PS.fp, "%.8f W\n", vector.layer[i].width );
		    fprintf(PS.fp, "%s setdash\n", vector.layer[i].setdash);
		    fprintf(PS.fp, "%.1f %.1f %.1f %.1f L\n", x + width, yo, x, yo);
		} else if ( vector.layer[i].type == VPOINTS ) {
		    /* TODO */
		    yo = y + 0.5 * fontsize - vector.layer[i].offset; 
            	    xo = x + width / 2;
		    symbol_draw ( vector.layer[i].symbol_ps, xo, yo, vector.layer[i].size, 
			      vector.layer[i].rotate, vector.layer[i].width);
		}

	    }

	    /* plot the text */
	    set_rgb_color(BLACK);
    	    fprintf(PS.fp, "a %d get %.1f %.1f MS\n", j - h*lc, x + width, y);
	}
    } /*h*/
    x = xs;
    y = ys - lc*dy;

    fprintf(PS.fp, "[] 0 setdash\n");

    if (PS.min_y > y) PS.min_y = y;

    return 0;
}

