 /*
  * Khoros: $Id$
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id$";
#endif

 /*
  * $Log$
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1991, University of New Mexico.  All rights reserved.
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as to the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including, for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"        /* Copyright 1991 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>  		        Legend I/O Routines
 >>>>
 >>>>			read_legend_file()
 >>>>			parse_legend_info()
 >>>>			write_legend_file()
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/

#include "spectrum.h"


/****************************************************************
*
* Routine Name: read_legend_file
*      Purpose: reads an ascii legend file 
*	 Input: filename - name of the legend file
*       Output: the global spc_legend structure
*   Written By: Danielle Argiro
*
****************************************************************/

int read_legend_file(filename)
char *filename;
{
	int  i, j, done, clusternum, class, ok; 
	int  maxclass = 0;
	char *text, *fullpath, temp[MaxLength];
	short red, green, blue;
	FILE *file;
	int  *clusters; 
        

	spc_lgd_classnum = 0;  

	/* expand filename */
	if (!(fullpath = vfullpath(filename, NULL, NULL)))
        {
           sprintf(temp, "Unable to expand '%s' in order to read legend.",
 		   filename);
           xvf_error_wait(temp, "read_legend_file", NULL);
           return(false);
	}

	/* open legend file */
	if (!(file = fopen(fullpath, "r")))
        {
           sprintf(temp, "Unable to open '%s' to read legend.", fullpath);
	   xvf_error_wait(temp, "read_legend_file", NULL);
           return(false);
        }

	/* premature end of file */
        if (feof(file))
           return(false);

	/* while not at end of file */
	done = false; i = 0; 
	while (!done)
	{
           j = 0;
	   i++;
    	        /* get a line of information */
           if (fgets(temp, MaxLength, file) == NULL) done = true;
	   else
	   {
	   	/* skip over any leading whitespace */
		while(temp[j] == ' ' || temp[j] == '\t') j++;

	   	/* skip over any blank lines;  comments have # symbol */
		if ((temp[j] != '\n') && (temp[j] != '#'))
		{
		       /* get legend information */
	 	        clusters = parse_legend_info(&temp[j], &clusternum,
						 &red, &green, &blue, 
						 &text, &class, &ok);

		        if (ok == false) 
			{
	                    sprintf(temp,"Error! Unable to a valid legend from file %s",
		                   filename);
	                    xvf_error_wait(temp, "read_legend_file", NULL);
			    return (false);
			}

	                if (class > maxclass) maxclass = class;

		        /* add a node to the legend structure */
		        (void) add_legend_node(class, red, green, blue, 
		    			       text, clusters, clusternum);  

		        spc_lgd_classes[spc_lgd_classnum++] = class; 
		}
	   }
	}
	
	/* number of classes in legend may be less than number of
	   classes specified in image - if so, need to create nodes
           in legend list */
	if (spc_lgd_classnum < spc_img_classnum)
	{
	     while (spc_lgd_classnum < spc_img_classnum)
	     {
                 clusters = construct_legend_info(&clusternum, &red,
						  &green, &blue, &text, &class);
		 if (class > maxclass) maxclass = class;

		 /* add a node to the legend structure */
                 (void) add_legend_node(class, red, green, blue,
                                               text, clusters, clusternum);

		 spc_lgd_classes[spc_lgd_classnum++] = class; 
	     } 
	}

	find_unused_classnums(maxclass);
	return(true);
}


/****************************************************************
*
* Routine Name: parse_legend_info
*
*      Purpose: parses one line of info from the ascii legend file 
*
*	 Input: line       - line of info of the legend file
*
*        -------------------------------------------
*        |    RGB   |   Text       |  Class Number |
*        |    .     |      .       |    .          |
*        |    .     |      .       |    2          |
*        | 80 255 0 |"CLASS 1"     |    3          |
*        |    .     |      .       |    4          |
*
*       Output: returns an array of cluster numbers of size clusternum
*		clusternum - amount of cluster numbers 
*		red        - red value of RGB triple
*		green      - green value of RGB triple
*		blue       - blue value of RGB triple
*		text       - string assoc. w/ legend info
*
*   Written By: Danielle Argiro
*
****************************************************************/

char *legend_scan = "%d%d%d%*[ ]%*['`]%[^'`]%*['`]%*[ ]%d";
#define MaxClusterNum 4096

int *parse_legend_info(line, clusternum, red, green, 
		       blue, text, class, return_flag)
char *line;
int  *clusternum;
short *red, *green, *blue;
char **text;
int  *class;
int  *return_flag;
{
	char tmp_text[MaxLength]; 
	int  i, j, status;
        int  clusters[MaxClusterNum], *return_clusters;
	int  r, g, b;


	status = sscanf(line, legend_scan, &r, &g, &b, tmp_text, class);
	*red   = (short) r;
	*green = (short) g;
	*blue  = (short) b;

	if (status < 5)
	{
	      *return_flag = false;
	      return(NULL);
	}

	if ((strcmp(tmp_text," ")) == 0) *text = NULL;
	else *text = xvf_strcpy(tmp_text);

	j = 0;
	if (spc_classes == NULL) 
	{
	    *return_flag = true;
	    return(NULL);
	}

	for (i = 0; i < spc_map_rownum; i++)
	{
	    if (spc_classes[i] == *class) 
		clusters[j++] = i;
	}
	*clusternum = j;
	if (j == 0) return(NULL);
	return_clusters = (int *) malloc (*clusternum * sizeof(int));
	for (i = 0; i < *clusternum; i++)
	    return_clusters[i] = clusters[i];

	*return_flag = true;
	return(return_clusters);
}


/****************************************************************
*
* Routine Name: construct_legend_info
*
*      Purpose: When there are more classes defined in the image's class
*		column than are included in the current legend file,
*		we must construct the legend info (as much as possible)
*		from the class column.  That is, we can get the class number,
*		and the clusters in the class. The color will be black,
*		and the text will be assigned, "Un-named category %d"
*
*	 Input: none
*       Output: returns an array of cluster numbers of size clusternum
*		clusternum - number of clusters in the class
*		red        - red value associated w/ class color
*		green      - green value associated w/ class color
*		blue       - blue value associated w/ class color
*		text       - text associated w/ class category
*		class      - identifying class number
*
*   Written By: Danielle Argiro
*
****************************************************************/

int *construct_legend_info(clusternum, red, green, blue, text, class)
int   *clusternum;
short *red, *green, *blue;
char **text;
int   *class;
{
	int  i, j, clusters[MaxClusterNum], *return_clusters; 
 	int  get_unassigned_img_class();
	char temp[MaxLength];

	*class = get_unassigned_img_class();
fprintf(stderr, "Class %d unassigned\n", *class);
	sprintf(temp, "Un-named class category %d", *class);
	*text   = xvf_strcpy(temp);
	j = 0;
	for (i = 0; i < spc_map_rownum; i++)
	{
	    if (spc_classes[i] == *class) 
		clusters[j++] = i;
	}
	*clusternum = j;
	if (j == 0) return(NULL);
	return_clusters = (int *) malloc (*clusternum * sizeof(int));
	for (i = 0; i < *clusternum; i++)
	    return_clusters[i] = clusters[i];

	*red    =  (short) norm_red_col[clusters[0]];
	*green  =  (short) norm_green_col[clusters[0]];
	*blue   =  (short) norm_blue_col[clusters[0]];

	return(return_clusters);
}

int get_unassigned_img_class()
{
      int i, j, class, found = false;

      i = spc_img_classnum-1;
      while (i >= 0)
      {
	  class = spc_img_classes[i];
          j = 0;
          while (!found && j < spc_lgd_classnum)
          {
              if (spc_lgd_classes[j] == class) found = true;
	      j++;
          }
          if (!found) return(class);
          else 
	  {
	      i--; found = false;
	  }
      }
      return(class);
}
/****************************************************************
*
* Routine Name: write_legend_file
*      Purpose: writes an ascii legend file 
*		according to current legend info
*	 Input: filename - name of the legend file to create
*       Output: the new legend file
*   Written By: Danielle Argiro
*
****************************************************************/

int write_legend_file(filename)
char *filename;
{
	char *fullpath, temp[MaxLength];
	legend_list *legend_ptr; 
	FILE *fopen(), *file;

	legend_ptr = spc_legend_list;
	if (legend_ptr == NULL)
	{
	    xvf_error_wait("No current legend information to write!", 
			   "write_legend_file", NULL);
	    return(false);
	}

	/* expand filename */
	if (!(fullpath = vfullpath(filename, NULL, NULL)))
        {
           sprintf(temp, "Unable to expand '%s' in order to write legend.",
 		   filename);
           xvf_error_wait(temp, "write_legend_file", NULL);
           return(false);
	}

	/* see if legend file already exists/prompt to over-write*/
        if (file = fopen(fullpath, "r"))
        {
           sprintf(temp, "Over-write file '%s'?", fullpath);
           if (!(xvf_warn_wait(temp, "write_legend_file", "Yes", "No")))
	   {
	       fclose(file);
               return(false);
	   }
	   fclose(file);
        }


	/* open legend file */
	if (!(file = fopen(fullpath, "w")))
        {
           sprintf(temp, "Unable to open '%s' to write legend.", fullpath);
	   xvf_error_wait(temp, "write_legend_file", NULL);
           return(false);
        }

	while (legend_ptr != NULL)
	{
	     fprintf(file, "%d %d %d '%s' %d\n", legend_ptr->red, legend_ptr->green,
		     legend_ptr->blue, legend_ptr->text, 
		     legend_ptr->class, legend_ptr->class);
	     legend_ptr = legend_ptr->next;
	}
	fclose(file);
	free(fullpath);
        return(true);
}

register_image_classes()
{
	int  *clusters;
	short red, green, blue;
	int clusternum, class, maxclass = 0;
	char *text;


	/* number of classes in legend may be less than number of
	   classes specified in image - if so, need to create nodes
           in legend list */
	if (spc_lgd_classnum < spc_img_classnum)
	{
	     while (spc_lgd_classnum < spc_img_classnum)
	     {
                 clusters = construct_legend_info(&clusternum, &red,
						  &green, &blue, &text, &class);
		 if (class > maxclass) maxclass = class;

		 /* add a node to the legend structure */
                 (void) add_legend_node(class, red, green, blue,
                                               text, clusters, clusternum);

		 spc_lgd_classes[spc_lgd_classnum++] = class; 
	     } 
	}
	find_unused_classnums(maxclass);
}
