#include <stdlib.h>
#include <grass/gis.h>
#include <grass/glocale.h>
#include "watershed.h"
#include "string.h"

/* make sure any useful info is transfered to the man page before ripping out the interactive help messages */
/* in addition there seem to be some useful user options here which are not currently available from the main parser */
int com_line_Gwater(INPUT * input, OUTPUT * output)
{
    struct Cell_head *window;
    char map_layer[48], buf[100], *prog_name, *mapset;
    double d;
    int i;

    window = &(output->window);
    if (0 == G_yes("Continue?", 1))
	exit(EXIT_SUCCESS);

    input->haf_name = (char *)G_calloc(40, sizeof(char));
    input->accum_name = (char *)G_calloc(40, sizeof(char));

    G_message(_("\nThis set of questions will organize the command line for the"));
    G_message(_("%s program to run properly for your application."),
	      NON_NAME);
    G_message(_("The first question is whether you want %s to run"),
	      NON_NAME);
    G_message(_("in its fast mode or its slow mode.  If you run %s"),
	      NON_NAME);
    G_message(_("in the fast mode, the computer will finish about 10 times faster"));
    G_message(_("than in the slow mode, but will not allow other programs to run"));
    G_message(_("at the same time.  The fast mode also places all of the data into"));
    G_message(_("RAM, which limits the size of window that can be run.  The slow"));
    G_message(_("mode uses disk space in the same hard disk partition as where GRASS is"));
    G_message(_("stored.  Thus, if the program does not work in the slow mode, you will"));
    G_message(_("need to remove unnecessary files from that partition.  The slow mode"));
    G_message(_("will allow other processes to run concurrently with %s.\n"),
	      NON_NAME);

    sprintf(buf, "Do you want to use the fast mode of %s?", NON_NAME);
    input->com_line_ram = input->com_line_seg = NULL;
    input->fast = 0;
    input->slow = 0;
    if (G_yes(buf, 1)) {
	input->fast = 1;
	input->com_line_ram = (char *)G_calloc(400, sizeof(char));
	prog_name = G_store(RAM_NAME);
	sprintf(input->com_line_ram,
		"\"%s/etc/water/%s\"", G_gisbase(), RAM_NAME);
	fprintf(stderr,
		"\nIf there is not enough ram for the fast mode (%s) to run,\n",
		RAM_NAME);
	sprintf(buf, "should the slow mode (%s) be run instead?", SEG_NAME);
	if (G_yes(buf, 1)) {
	    input->slow = 1;
	    input->com_line_seg = (char *)G_calloc(400, sizeof(char));
	    sprintf(input->com_line_seg,
		    "\"%s/etc/water/%s\"", G_gisbase(), SEG_NAME);
	}
    }
    else {
	input->slow = 1;
	prog_name = G_store(SEG_NAME);
	input->com_line_seg = (char *)G_calloc(400, sizeof(char));
	sprintf(input->com_line_seg,
		"\"%s/etc/water/%s\"", G_gisbase(), SEG_NAME);
    }

    G_message(_("\nIf you hit <return> by itself for the next question, this"));
    G_message(_("program will terminate."));

    mapset = G_ask_old("What is the name of the elevation map layer?",
		       map_layer, "cell", "cell");
    if (!mapset)
	exit(EXIT_FAILURE);
    if (input->fast)
	com_line_add(&(input->com_line_ram), " el=", map_layer, mapset);
    if (input->slow)
	com_line_add(&(input->com_line_seg), " el=", map_layer, mapset);

    G_message(_("\nOne of the options for %s is a `depression map'.  A"),
	      prog_name);
    G_message(_("depression map indicates all the locations in the current map window where"));
    G_message(_("water accumulates and does not leave by the edge of the map. Lakes without"));
    G_message(_("outlet streams and sinkholes are examples of `depressions'.  If you wish to"));
    G_message(_("have a depression map, prepare a map where non-zero values indicate the"));
    G_message(_("locations where depressions occur.\n"));
    G_message(_("Hit <return> by itself for the next question if there is no depression map."));

    mapset = G_ask_old("What is the name of the depression map layer?",
		       map_layer, "cell", "cell");
    if (mapset) {
	if (input->fast)
	    com_line_add(&(input->com_line_ram), " de=", map_layer, mapset);
	if (input->slow)
	    com_line_add(&(input->com_line_seg), " de=", map_layer, mapset);
    }

    G_message(_("\nThe %s program will divide the elevation map into a number of"),
	      prog_name);
    G_message(_("watershed basins.  The number of watershed basins is indirectly determined"));
    G_message(_("by the `basin threshold' value.  The basin threshold is the area necessary for"));
    G_message(_("%s to define a unique watershed basin.  This area only applies to"),
	      prog_name);
    G_message(_("`exterior drainage basins'.  An exterior drainage basin does not have any"));
    G_message(_("drainage basins flowing into it.  Interior drainage basin size is determined"));
    G_message(_("by the surface flow going into stream segments between stream interceptions."));
    G_message(_("Thus interior drainage basins can be of any size.  The %s program"),
	      prog_name);
    G_message(_("also allows the user to relate basin size to potential overland flow"));
    G_message(_("(i.e., areas with low infiltration capacities will need smaller areas to"));
    G_message(_("develop stream channels than neighboring areas with high infiltration rates)."));
    G_message(_("The user can create a map layer with potential overland flow values, and"));
    G_message(_("%s will accumulate those values instead of area.\n"),
	      prog_name);
    G_message(_("What unit of measure will you use for the basin threshold:"));

    do {
	G_message(_(" 1) acres,          2) meters sq., 3) miles sq., 4) hectares,"));
	G_message(_(" 5) kilometers sq., 6) map cells,  7) overland flow units"));
	fprintf(stderr, _("Choose 1-7 or 0 to exit this program: "));
	G_gets(map_layer);
	sscanf(map_layer, "%d", &i);
    } while (i > 7 || i < 0);

    if (!i)
	exit(EXIT_SUCCESS);

    output->type_area = (char)i;

    G_message(_("\nHow large an area (or how many overland flow units) must a drainage basin"));
    fprintf(stderr, _("be for it to be an exterior drainage basin: "));
    G_gets(map_layer);
    sscanf(map_layer, "%lf", &d);

    switch (i) {
    case 1:
	if (input->fast)
	    basin_com_add(&(input->com_line_ram), d, ACRE_TO_METERSQ, window);
	if (input->slow)
	    basin_com_add(&(input->com_line_seg), d, ACRE_TO_METERSQ, window);
	break;
    case 2:
	if (input->fast)
	    basin_com_add(&(input->com_line_ram), d, 1.0, window);
	if (input->slow)
	    basin_com_add(&(input->com_line_seg), d, 1.0, window);
	break;
    case 3:
	if (input->fast)
	    basin_com_add(&(input->com_line_ram), d, MILESQ_TO_METERSQ,
			  window);
	if (input->slow)
	    basin_com_add(&(input->com_line_seg), d, MILESQ_TO_METERSQ,
			  window);
	break;
    case 4:
	if (input->fast)
	    basin_com_add(&(input->com_line_ram), d, HECTACRE_TO_METERSQ,
			  window);
	if (input->slow)
	    basin_com_add(&(input->com_line_seg), d, HECTACRE_TO_METERSQ,
			  window);
	break;
    case 5:
	if (input->fast)
	    basin_com_add(&(input->com_line_ram), d, KILOSQ_TO_METERSQ,
			  window);
	if (input->slow)
	    basin_com_add(&(input->com_line_seg), d, KILOSQ_TO_METERSQ,
			  window);
	break;
    case 6:
	if (input->fast)
	    basin_com_add(&(input->com_line_ram), d,
			  (window->ns_res * window->ew_res), window);
	if (input->slow)
	    basin_com_add(&(input->com_line_seg), d,
			  (window->ns_res * window->ew_res), window);
	break;
    case 7:			/* needs an overland flow map */
	G_message(_("\nIf you hit <return> by itself for the next question, this"));
	G_message(_("program will terminate."));
	mapset = G_ask_old("What is the name of the overland flow map layer?",
			   map_layer, "cell", "cell");
	if (!mapset)
	    exit(EXIT_FAILURE);
	if (input->fast) {
	    com_line_add(&(input->com_line_ram), " ov=", map_layer, mapset);
	    basin_com_add(&(input->com_line_ram), d,
			  (window->ns_res * window->ew_res), window);
	}
	if (input->slow) {
	    com_line_add(&(input->com_line_seg), " ov=", map_layer, mapset);
	    basin_com_add(&(input->com_line_seg), d,
			  (window->ns_res * window->ew_res), window);
	}
	break;
    }

    G_message(_("\n%s must create a map layer of watershed basins"),
	      prog_name);
    G_message(_("before %s can run properly."), G_program_name());

    strcpy(buf, "Please name the output watershed basin map:");
    do {
	mapset = G_ask_new(buf, input->haf_name, "cell", "");
    } while (NULL == mapset);

    if (input->fast)
	com_line_add(&(input->com_line_ram), " ba=", input->haf_name, NULL);
    if (input->slow)
	com_line_add(&(input->com_line_seg), " ba=", input->haf_name, NULL);

    /* 
       This section queries the user about the armsed file input. If
       you want to make this an option,  the code below "COMMENT2" needs to be
       modified. 
     */

#ifdef ARMSED
    G_message(_("\n%s must create a file of watershed basin relationships"),
	      prog_name);
    G_message(_("before %s can run properly."), G_program_name());

    input->ar_file_name = NULL;
    while (input->ar_file_name == NULL) {
	fprintf(stderr, _("\nPlease name this file:"));
	G_gets(char_input);
	if (1 != G_legal_filename(char_input)) {
	    G_message(_("<%s> is an illegal file name"), char_input);
	}
	else
	    input->ar_file_name = G_store(char_input);
    }

    if (input->fast)
	com_line_add(&(input->com_line_ram), " ar=", input->ar_file_name,
		     NULL);
    if (input->slow)
	com_line_add(&(input->com_line_seg), " ar=", input->ar_file_name,
		     NULL);

    /*
       end of ARMSED comment code
     */

    /*
       COMMENT2 This section of code tells the program where to place the statistics
       about the watershed basin. GRASS users don't need this (w/ r.stats), but the
       format is suppossed to be "user-friendly" to hydrologists. For the stats to be
       created, the armsed file output needs to exist. For the stats to be an option
       in this program: 1) it should be querried before the armsed file query, and 2)
       make the armsed file query manditory if this option is invoked.
     */

    G_message(_("\n%s will generate a lot of output.  Indicate a file"),
	      G_program_name());
    G_message(_("name for %s to send the output to."), G_program_name());

    output->file_name = NULL;
    while (output->file_name == NULL) {
	fprintf(stderr, _("\nPlease name this file:"));
	G_gets(char_input);
	if (1 != G_legal_filename(char_input)) {
	    G_message(_("<%s> is an illegal file name"), char_input);
	}
	else
	    output->file_name = G_store(char_input);
    }

    /* 
       end of COMMENT2
     */
#endif

    G_message(_("\nThe accumulation map from %s must be present for"),
	      prog_name);
    G_message(_("%s to work properly."), G_program_name());
    strcpy(buf, "Please name the accumulation map:");
    do {
	mapset = G_ask_new(buf, input->accum_name, "cell", "");
    } while (NULL == mapset);

    if (input->fast)
	com_line_add(&(input->com_line_ram), " ac=", input->accum_name, NULL);
    if (input->slow)
	com_line_add(&(input->com_line_seg), " ac=", input->accum_name, NULL);

    G_message(_("\n%s can produce several maps not necessary for"),
	      prog_name);
    G_message(_("%s to function (stream channels, overland flow aspect, and"),
	      G_program_name());
    G_message(_("a display version of the accumulation map).  %s also has the"),
	      prog_name);
    G_message(_("ability to generate several variables in the Revised Universal Soil Loss"));
    G_message(_("Equation (Rusle): Slope Length (LS), and Slope Steepness (S).\n"));

    sprintf(buf, "Would you like any of these maps to be created?");
    if (G_yes(buf, 1)) {
	mapset = G_ask_new("", map_layer, "cell", "stream channel");
	if (mapset != NULL) {
	    if (input->fast)
		com_line_add(&(input->com_line_ram), " se=", map_layer, NULL);
	    if (input->slow)
		com_line_add(&(input->com_line_seg), " se=", map_layer, NULL);
	}
	mapset = G_ask_new("", map_layer, "cell", "half basin");
	if (mapset != NULL) {
	    if (input->fast)
		com_line_add(&(input->com_line_ram), " ha=", map_layer, NULL);
	    if (input->slow)
		com_line_add(&(input->com_line_seg), " ha=", map_layer, NULL);
	}
	mapset = G_ask_new("", map_layer, "cell", "overland aspect");
	if (mapset != NULL) {
	    if (input->fast)
		com_line_add(&(input->com_line_ram), " dr=", map_layer, NULL);
	    if (input->slow)
		com_line_add(&(input->com_line_seg), " dr=", map_layer, NULL);
	}
	mapset = G_ask_new("", map_layer, "cell", "display");
	if (mapset != NULL) {
	    if (input->fast)
		com_line_add(&(input->com_line_ram), " di=", map_layer, NULL);
	    if (input->slow)
		com_line_add(&(input->com_line_seg), " di=", map_layer, NULL);
	}
	i = 0;
	mapset = G_ask_new("", map_layer, "cell", "Slope Length");
	if (mapset != NULL) {
	    i = 1;
	    if (input->fast)
		com_line_add(&(input->com_line_ram), " LS=", map_layer, NULL);
	    if (input->slow)
		com_line_add(&(input->com_line_seg), " LS=", map_layer, NULL);
	}
	mapset = G_ask_new("", map_layer, "cell", "Slope Steepness");
	if (mapset != NULL) {
	    i = 1;
	    if (input->fast)
		com_line_add(&(input->com_line_ram), " S=", map_layer, NULL);
	    if (input->slow)
		com_line_add(&(input->com_line_seg), " S=", map_layer, NULL);
	}

	if (i) {
	    G_message(_("\nThe Slope Length factor (LS) and Slope Steepness (S) are influenced by"));
	    G_message(_("disturbed land.  %s reflects this with an optional map layer or value"),
		      prog_name);
	    G_message(_("where the value indicates the percent of disturbed (barren) land in that cell."));
	    G_message(_("Type <return> if you do not have a disturbed land map layer."));

	    mapset = G_ask_old("", map_layer, "cell", "disturbed land");
	    if (mapset != NULL) {
		if (input->fast)
		    com_line_add(&(input->com_line_ram), " r=", map_layer,
				 NULL);
		if (input->slow)
		    com_line_add(&(input->com_line_seg), " r=", map_layer,
				 NULL);
	    }
	    else {
		G_message(_("\nType the value indicating the percent of disturbed land.  This value will"));
		G_message(_("be used for every cell in the current region."));
		i = -6;
		while (i < 0 || i > 100) {
		    fprintf(stderr, _("\nInput value here [0-100]: "));
		    fgets(buf, 80, stdin);
		    sscanf(buf, "%d", &i);
		}
		if (input->fast)
		    com_add(&(input->com_line_ram), " r=", i);
		if (input->slow)
		    com_add(&(input->com_line_seg), " r=", i);
	    }

	    /*       12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
	    G_message(_("\nOverland surface flow only occurs for a set distance before swales form."));
	    G_message(_("Because of digital terrain model limitations, %s cannot pick up"),
		      prog_name);
	    G_message(_("these swales.  %s allows for an input (warning: kludge factor)"),
		      prog_name);
	    G_message(_("that prevents the surface flow distance from getting too long.  Normally,"));
	    G_message(_("maximum slope length is around 600 feet (about 183 meters)."));

	    i = -1;
	    while (i < 0) {
		fprintf(stdout,
			"\nInput maximum slope length here (in meters): ");
		fgets(buf, 80, stdin);
		sscanf(buf, "%d", &i);
	    }
	    if (input->fast)
		com_add(&(input->com_line_ram), " ms=", i);
	    if (input->slow)
		com_add(&(input->com_line_seg), " ms=", i);

	    /*       12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
	    G_message(_("\nRoads, ditches, changes in ground cover, and other factors will stop"));
	    G_message(_("slope length.  You may input a raster map indicating the locations of these"));
	    G_message(_("blocking factors.\n"));
	    G_message(_("Hit <return> by itself for the next question if there is no blocking map."));

	    mapset = G_ask_old("What is the name of the blocking map layer?",
			       map_layer, "cell", "cell");
	    if (mapset) {
		if (input->fast)
		    com_line_add(&(input->com_line_ram), " ob=", map_layer,
				 mapset);
		if (input->slow)
		    com_line_add(&(input->com_line_seg), " ob=", map_layer,
				 mapset);
	    }
	}
    }

    return 0;
}

int com_line_add(char **com_line, char *prompt, char *map_layer, char *mapset)
{
    strcat(*com_line, prompt);
    strcat(*com_line, "\"");
    strcat(*com_line, map_layer);
    if (mapset) {
	strcat(*com_line, "@");
	strcat(*com_line, mapset);
    }
    strcat(*com_line, "\"");

    return 0;
}

int basin_com_add(char **com_line, double d, double modifier,
		  struct Cell_head *window)
{
    int i;
    char buf[20];

    i = (int)(.5 + modifier * d / window->ns_res / window->ew_res);
    if (i < 1)
	i = 1;
    sprintf(buf, " t=%d", i);
    strcat(*com_line, buf);

    return 0;
}

int com_add(char **com_line, char *prompt, int ril_value)
{
    char buf[20];

    strcat(*com_line, prompt);
    sprintf(buf, "%d", ril_value);
    strcat(*com_line, buf);

    return 0;
}
