#include "global.h"

/**
   \brief Parser stuff

   \param[in] argc number of arguments
   \param[in] argv arguments array
   \param[in] params GRASS paramenters
   \param[out] action mode selected tool

   \return 1
*/
int parser(int argc, char *argv[], struct GParams *params,
	   enum mode *action_mode)
{
    char *desc_tool, *desc_query, *desc_snap;

    /* parameters */
    params->map = G_define_standard_option(G_OPT_V_MAP);
    params->map->label = _("Name of vector map to edit");

    params->fld = G_define_standard_option(G_OPT_V_FIELD);
    params->fld->gisprompt = "old,layer,layer";
    params->fld->guisection = _("Selection");

    params->type = G_define_standard_option(G_OPT_V_TYPE);
    params->type->options = "point,line,boundary,centroid";
    params->type->answer = "point,line,boundary,centroid";
    params->type->guisection = _("Selection");

    params->tool = G_define_option();
    params->tool->key = "tool";
    params->tool->type = TYPE_STRING;
    params->tool->required = YES;
    params->tool->multiple = NO;
    params->tool->description = _("Tool");
    desc_tool = NULL;
    G_asprintf(&desc_tool,
	       "create;%s;"
	       "add;%s;"
	       "delete;%s;"
	       "move;%s;"
	       "vertexmove;%s;"
	       "vertexdel;%s;"
	       "vertexadd;%s;"
	       "merge;%s;"
	       "break;%s;"
	       "select;%s;"
	       "catadd;%s;"
	       "catdel;%s;"
	       "copy;%s;"
	       "snap;%s;"
	       "flip;%s;"
	       "connect;%s;"
	       "extend;%s;"
	       "extendstart;%s;"
	       "extendend;%s;"
	       "zbulk;%s;"
	       "chtype;%s;"
	       "areadel;%s",
	       _("Create new (empty) vector map"),
	       _("Add new features to existing vector map"),
	       _("Delete selected features from vector map"),
	       _("Move selected features in vector map"),
	       _("Move vertex of selected vector lines"),
	       _("Remove vertex from selected vector lines"),
	       _("Add new vertex to selected vector lines"),
	       _("Merge selected vector lines"),
	       _("Break/split vector lines"),
	       _("Select lines and print their ID's"),
	       _("Set new categories to selected vector features "
		 "for defined layer"),
	       _("Delete categories from selected vector features "
		 "for defined layer"),
	       _("Copy selected features"),
	       _("Snap vector features in given threshold"),
	       _("Flip direction of selected vector lines"),
	       _("Connect two lines"),
	       _("Extend lines"),
	       _("Extend start nodes"),
	       _("Extend end nodes"),
	       _("Z bulk-labeling (automated assignment of z coordinate to "
		 "vector lines)"),
	       _("Change feature type (point<->centroid, line<->boundary)"),
	       _("Delete selected areas from vector map (based on selected centroids)"));
    params->tool->descriptions = desc_tool;
    params->tool->options = "create,add,delete,copy,move,flip,catadd,catdel,"
	"merge,break,snap,connect,extend,extendstart,extendend,chtype,"
	"vertexadd,vertexdel,vertexmove,areadel,zbulk,select";

    params->in = G_define_standard_option(G_OPT_F_INPUT);
    params->in->required = NO;
    params->in->label = _("Name of file containing data in GRASS ASCII vector format");
    params->in->description =
	_("'-' for standard input");
    params->in->guisection = _("Input");

    params->move = G_define_option();
    params->move->key = "move";
    params->move->key_desc = "x,y,z";
    params->move->type = TYPE_DOUBLE;
    params->move->required = NO;
    params->move->multiple = NO;
    params->move->description =
	_("Difference in x,y,z direction for moving feature or vertex");

    params->maxdist = G_define_option();
    params->maxdist->key = "threshold";
    params->maxdist->type = TYPE_DOUBLE;
    params->maxdist->required = NO;
    params->maxdist->multiple = YES;
    params->maxdist->label = _("Threshold distance (coords,snap,query)");
    params->maxdist->description =
	_("'-1' for threshold based on the current resolution settings");
    params->maxdist->answer = "-1,0,0";

    params->id = G_define_standard_option(G_OPT_V_IDS);
    params->id->guisection = _("Selection");

    params->cat = G_define_standard_option(G_OPT_V_CATS);
    params->cat->required = NO;
    params->cat->guisection = _("Selection");

    params->coord = G_define_option();
    params->coord->key = "coords";
    params->coord->key_desc = "x,y";
    params->coord->type = TYPE_DOUBLE;
    params->coord->required = NO;
    params->coord->multiple = YES;
    params->coord->description = _("List of point coordinates");
    params->coord->guisection = _("Selection");

    params->bbox = G_define_option();
    params->bbox->key = "bbox";
    params->bbox->key_desc = "x1,y1,x2,y2";
    params->bbox->type = TYPE_DOUBLE;
    params->bbox->required = NO;
    params->bbox->multiple = NO;
    params->bbox->description = _("Bounding box for selecting features");
    params->bbox->guisection = _("Selection");

    params->poly = G_define_option();
    params->poly->key = "polygon";
    params->poly->key_desc = "x,y";
    params->poly->type = TYPE_DOUBLE;
    params->poly->required = NO;
    params->poly->multiple = YES;
    params->poly->description = _("Polygon for selecting features");
    params->poly->guisection = _("Selection");

    params->where = G_define_standard_option(G_OPT_DB_WHERE);
    params->where->guisection = _("Selection");

    params->query = G_define_option();
    params->query->key = "query";
    params->query->type = TYPE_STRING;
    params->query->options = "length,dangle";
    params->query->label = _("Query tool");
    params->query->description =
	_("For 'shorter' use negative threshold value, "
	  "positive value for 'longer'");
    desc_query = NULL;
    G_asprintf(&desc_query,
               "length;%s;"
	       "dangle;%s",
	       _("Select only lines or boundaries shorter"
		 "/longer than threshold distance"),
	       _("Select dangles shorter/longer than threshold distance"));
    params->query->descriptions = desc_query;
    params->query->guisection = _("Selection");

    params->bmaps = G_define_standard_option(G_OPT_V_MAPS);
    params->bmaps->key = "bgmap";
    params->bmaps->required = NO;
    params->bmaps->description = _("Name of background vector map(s)");

    params->snap = G_define_option();
    params->snap->key = "snap";
    params->snap->type = TYPE_STRING;
    params->snap->options = "no,node,vertex";
    params->snap->description =
	_("Snap added or modified features in the given threshold to the nearest existing feature");
    desc_snap = NULL;
    G_asprintf(&desc_snap,
	       "no;%s;"
	       "node;%s;"
	       "vertex;%s",
	       _("Not apply snapping"),
	       _("Snap only to node"),
	       _("Allow snapping also to vertex"));
    params->snap->descriptions = desc_snap;
    params->snap->answer = "no";

    params->zbulk = G_define_option();
    params->zbulk->key = "zbulk";
    params->zbulk->type = TYPE_DOUBLE;
    params->zbulk->key_desc = "value,step";
    params->zbulk->label = _("Starting value and step for z bulk-labeling");
    params->zbulk->description = _("Pair: value,step (e.g. 1100,10)");

    /* flags */
    params->reverse = G_define_flag();
    params->reverse->key = 'r';
    params->reverse->description = _("Reverse selection");
    params->reverse->guisection = _("Selection");

    params->close = G_define_flag();
    params->close->key = 'c';
    params->close->description =
	_("Close added boundaries (using threshold distance)");

    params->header = G_define_flag();
    params->header->key = 'n';
    params->header->description = _("Do not expect header of input data");
    params->header->guisection = _("Input");

    params->topo = G_define_standard_flag(G_FLG_V_TOPO);

    params->move_first = G_define_flag();
    params->move_first->key = '1';
    params->move_first->description =
	_("Modify only first found feature in bounding box");

    params->extend_parallel = G_define_flag();
    params->extend_parallel->key = 'p';
    params->extend_parallel->description =
	_("Connect parallel lines (using extend tools and threshold distance)");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    /* check for polygon param */
    if (params->poly->answers != NULL) {
	int i = 0;

	while (params->poly->answers[i++]) ;

	if (i < 6)
	    G_fatal_error(_("Polygon must have at least 3 coordinate pairs"));
    }

    /*
       check that the given arguments makes sense together
     */
    if (strcmp(params->tool->answer, "create") == 0) {
	*action_mode = MODE_CREATE;
    }
    else if (strcmp(params->tool->answer, "add") == 0) {
	*action_mode = MODE_ADD;
    }
    else if (strcmp(params->tool->answer, "delete") == 0) {
	*action_mode = MODE_DEL;
    }
    else if (strcmp(params->tool->answer, "move") == 0) {
	*action_mode = MODE_MOVE;
    }
    else if (strcmp(params->tool->answer, "merge") == 0) {
	*action_mode = MODE_MERGE;
    }
    else if (strcmp(params->tool->answer, "break") == 0) {
	*action_mode = MODE_BREAK;
    }
    else if (strcmp(params->tool->answer, "connect") == 0) {
	*action_mode = MODE_CONNECT;
    }
    else if (strcmp(params->tool->answer, "extend") == 0) {
	*action_mode = MODE_EXTEND;
    }
    else if (strcmp(params->tool->answer, "extendstart") == 0) {
	*action_mode = MODE_EXTEND_START;
    }
    else if (strcmp(params->tool->answer, "extendend") == 0) {
	*action_mode = MODE_EXTEND_END;
    }
    else if (strcmp(params->tool->answer, "vertexadd") == 0) {
	*action_mode = MODE_VERTEX_ADD;
    }
    else if (strcmp(params->tool->answer, "vertexdel") == 0) {
	*action_mode = MODE_VERTEX_DELETE;
    }
    else if (strcmp(params->tool->answer, "vertexmove") == 0) {
	*action_mode = MODE_VERTEX_MOVE;
    }
    else if (strcmp(params->tool->answer, "select") == 0) {
	*action_mode = MODE_SELECT;
    }
    else if (strcmp(params->tool->answer, "catadd") == 0) {
	*action_mode = MODE_CATADD;
    }
    else if (strcmp(params->tool->answer, "catdel") == 0) {
	*action_mode = MODE_CATDEL;
    }
    else if (strcmp(params->tool->answer, "copy") == 0) {
	*action_mode = MODE_COPY;
    }
    else if (strcmp(params->tool->answer, "snap") == 0) {
	*action_mode = MODE_SNAP;
    }
    else if (strcmp(params->tool->answer, "flip") == 0) {
	*action_mode = MODE_FLIP;
    }
    else if (strcmp(params->tool->answer, "zbulk") == 0) {
	*action_mode = MODE_ZBULK;
    }
    else if (strcmp(params->tool->answer, "chtype") == 0) {
	*action_mode = MODE_CHTYPE;
    }
    else if (strcmp(params->tool->answer, "areadel") == 0) {
	*action_mode = MODE_AREA_DEL;
    }
    else {
	G_fatal_error(_("Operation '%s' not implemented"),
		      params->tool->answer);
    }

    if ((*action_mode != MODE_CREATE && *action_mode != MODE_ADD &&
	 *action_mode != MODE_ZBULK) && (params->cat->answers == NULL) &&
	(params->coord->answers == NULL) && (params->poly->answers == NULL) &&
	(params->id->answers == NULL) && (params->bbox->answers == NULL) &&
	(params->where->answer == NULL) && (params->query->answer == NULL)) {
	G_fatal_error(_("At least one option from %s must be specified"),
		      "cats, ids, coords, bbox, polygon, where, query");
    }

    if (*action_mode == MODE_MOVE || *action_mode == MODE_VERTEX_MOVE) {
	if (params->move->answers == NULL) {
	    G_fatal_error(_("Tool %s requires option %s"),
			  params->tool->answer, params->move->key);
	}
    }

    if (*action_mode == MODE_VERTEX_ADD ||
	*action_mode == MODE_VERTEX_DELETE ||
	*action_mode == MODE_VERTEX_MOVE) {
	if (params->coord->answers == NULL) {
	    G_fatal_error(_("Tool %s requires option %s"),
			  params->tool->answer, params->coord->key);
	}
    }

    if (*action_mode == MODE_CATADD || *action_mode == MODE_CATDEL) {
	if (params->cat->answers == NULL) {
	    G_fatal_error(_("Tool %s requires option %s"),
			  params->tool->answer, params->cat->key);
	}
    }

    if (*action_mode == MODE_ZBULK) {
	if (params->bbox->answers == NULL) {
	    G_fatal_error(_("Tool %s requires option %s"),
			  params->tool->answer, params->bbox->key);
	}
	if (params->zbulk->answers == NULL) {
	    G_fatal_error(_("Tool %s requires option %s"),
			  params->tool->answer, params->zbulk->key);
	}
    }

    return 1;
}
