/****************************************************************************
 *
 * MODULE:       s.in.ascii
 * AUTHOR(S):    Michael Shapiro - US Army CERL
 *               Improvements:
 *                     Markus Neteler - neteler@geog.uni-hannover.de
 *                     Eric Miller
 *                     added timestamp 1/2002 MN
 * PURPOSE:      Import ASCII sites lists and their descriptions into
 *               a GRASS sites list file. 
 * COPYRIGHT:    (C) 2000 by the GRASS Development Team
 *
 *               This program is free software under the GNU General Public
 *   	    	 License (>=v2). Read the file COPYING that comes with GRASS
 *   	    	 for details.
 *
 *****************************************************************************/

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

static int loop; /* added #cat support for site_list 11/99 M. Neteler
                  * required for s.to.vect and s.to.rast */

int 
main (int argc, char *argv[])
{
    char *me;
    char *output, *input;
    char *fs;
    int dims, i, has_cat;
    struct GModule *module;
    FILE *in_fd, *out_fd;
    Site *site;
    Site_head shead;
    struct TimeStamp ts;
    struct
    {
	struct Option *input, *output, *dims, *fs, *date;
    } parm;

    G_gisinit (me = argv[0]);

    module = G_define_module();
    module->keywords = _("sites");
    module->description = 
      "Convert an ASCII listing of site locations "
      "into a GRASS site list file.";

    parm.output = G_define_option();
    parm.output->key = "output";
    parm.output->type = TYPE_STRING;
    parm.output->required = YES;
    parm.output->description = "vector file to be created";
    parm.output->gisprompt = "any,vector,vector";

    parm.input = G_define_option();
    parm.input->key = "input";
    parm.input->type = TYPE_STRING;
    parm.input->required = NO;
    parm.input->description = "unix file containing sites";

    parm.dims = G_define_option();
    parm.dims->key = "d";
    parm.dims->type = TYPE_INTEGER;
    parm.dims->required = NO;
    parm.dims->description = "number of dimensions (default=2)";

    parm.fs = G_define_option();
    parm.fs->key = "fs";
    parm.fs->key_desc = "character|space|tab";
    parm.fs->type = TYPE_STRING;
    parm.fs->required = NO;
    parm.fs->description = "input field separator";
    parm.fs->answer = "space";

    parm.date = G_define_option();
    parm.date->key = "date";
    parm.date->key_desc = "timestamp";
    parm.date->required = NO;
    parm.date->type = TYPE_STRING;
    parm.date->description = "datetime or datetime1/datetime2";

    if (G_parser(argc,argv))
	exit(-1);
	
    if((input = parm.input->answer))
    {
	in_fd = fopen (input, "r");
	if (NULL == in_fd)
	{
	    fprintf (stderr, "%s - ", me);
	    perror (input);
	    exit(1);
	}
    }
    else
	in_fd = stdin;

    output = parm.output->answer;
    shead.name = G_store(parm.output->answer);
    shead.desc = G_store(G_recreate_command());
    shead.form = shead.labels = shead.stime = (char *)NULL;
      
    /* add here time parameter */
    if (parm.date->answer)
    {
	if(1 == G_scan_timestamp (&ts, parm.date->answer))
	    shead.time = &ts;
	else
	    G_fatal_error("Invalid timestamp");
    }
    else 
      shead.time = (struct TimeStamp*)NULL; 

    dims=2;
    loop=1; /* added 11/99 MNeteler*/

    if (parm.dims->answer!=NULL)
      if ((i = sscanf (parm.dims->answer, "%d", &dims)) != 1)
        G_fatal_error ("error scanning number of dimensions");
    if (dims<2)
      G_fatal_error ("number of dimensions must be greater than 1");

    if ( strlen(parm.fs->answer) < 1 )
      G_fatal_error ("field separator cannot be empty");
    else
    {   
        fs = parm.fs->answer;
	if(strcmp (fs, "space") == 0)
	    fs = NULL;
	else if(strcmp (fs, "tab") == 0)
	    fs = NULL;
    }

    out_fd = G_fopen_sites_new (output);
    if (out_fd == NULL)
        G_fatal_error ("can't create sites file [%s].", output);

    G_site_put_head (out_fd, &shead);
    
    while ((site = get_site (in_fd, dims, fs, &has_cat)))
      G_site_put (out_fd, site);
    
    G_sites_close (out_fd);
    exit(0);
}
static int 
format_double (double value, char *buf)
{
  int G_trim_decimal ();
  sprintf (buf, "%.8f", value);
  G_trim_decimal (buf);
  return 0;
}

#define DQUOTE '"'
#define SPACE ' '
#define BSLASH 92
#define PIPE '|'

#define ispipe(c) (c==PIPE)
#define isnull(c) (c==(char)NULL)
#define isquote(c) (c==DQUOTE)
#define isbslash(c) (c==BSLASH)

int 
G_site_put_new (FILE *fptr, Site *s, int has_cat)

/* Writes a site to file open on fptr. */
{
  char ebuf[MAX_SITE_STRING], nbuf[MAX_SITE_STRING];
  char xbuf[MAX_SITE_STRING], buf[MAX_SITE_LEN];
  static int format_double ();
  int fmt, i, j, k;
  int G_format_northing(), G_format_easting(), G_projection();

  fmt = G_projection ();

  G_format_northing (s->north, nbuf, fmt);
  G_format_easting (s->east, ebuf, fmt);
  sprintf (buf, "%s|%s|", ebuf, nbuf);
  for (i = 0; i < s->dim_alloc; ++i)
  {
    format_double (s->dim[i], nbuf);
    sprintf (xbuf, "%s|", nbuf);
    G_strcat (buf, xbuf);
  }

 if (has_cat)  
  {
    switch(s->cattype)
    {
     case CELL_TYPE:
      sprintf (xbuf, "#%d ", s->ccat);
      G_strcat (buf, xbuf);
      break;
     case FCELL_TYPE:
      sprintf (xbuf, "#%g ", s->fcat);
      G_strcat (buf, xbuf);
      break;
     case DCELL_TYPE:
      sprintf (xbuf, "#%g ", s->dcat);
      G_strcat (buf, xbuf);
      break;
    }
  }                                                    
  else /* no cat there, so data in plain x,y,z format will be imported   12/99 MN */
  {
     /* we create a #cat entry in site_list from the current site number 11/99 */
     sprintf (xbuf, "#%d ", loop);
     loop++;
     G_strcat (buf, xbuf);
  }

 /* now import attributes */
  for (i = 0; i < s->dbl_alloc; ++i)
  {
    format_double (s->dbl_att[i], nbuf);
    sprintf (xbuf, "%%%s ", nbuf);
    G_strcat (buf, xbuf);
  }
  
  for (i = 0; i < s->str_alloc; ++i)
  {
    if (strlen (s->str_att[i]) != 0)
    {
      /* escape double quotes */
      j = k = 0;
      if (G_index (s->str_att[i], DQUOTE) != (char *) NULL)
      {
	while (!isnull(s->str_att[i][j]))
	{
	  if (isquote(s->str_att[i][j]))
	  {
	    xbuf[k++] = BSLASH;
	    xbuf[k++] = DQUOTE;
	  }
	  else
	  if (isbslash(s->str_att[i][j]))
	  {
	    xbuf[k++] = BSLASH;
	    xbuf[k++] = BSLASH;
	  }
	  else
	    xbuf[k++] = s->str_att[i][j];
	  j++;
	}
	xbuf[k] = (char) NULL;
      }
      else
	G_strcpy (xbuf, s->str_att[i]);

      G_strcpy (s->str_att[i], xbuf);

      if (G_index (s->str_att[i], SPACE) != (char *) NULL)
	  sprintf (xbuf, "@\"%s\" ", s->str_att[i]);
        else
	  sprintf (xbuf, "@%s ", s->str_att[i]);

      G_strcat (buf, xbuf);
    }
  }
  fprintf (fptr, "%s\n", buf);
  return 0;
}
