
/****************************************************************************
 *
 * MODULE:       i.photo.elev
 * AUTHOR(S):    Mike Baba (original contributor)
 *               Markus Neteler <neteler itc.it>, 
 *               Roberto Flor <flor itc.it>, 
 *               Bernhard Reiter <bernhard intevation.de>, 
 *               Glynn Clements <glynn gclements.plus.com>
 *               Hamish Bowman
 *               Markus Metz
 *
 * PURPOSE:      Select the elevation model
 * COPYRIGHT:    (C) 1999-2012 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.
 *
 *****************************************************************************/

/* read the target for the block and cast it into the alternate GRASS env */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <grass/gis.h>
#include <grass/imagery.h>
#include <grass/glocale.h>
#include "orthophoto.h"

static int which_env;

int select_current_env(void);
int select_target_env(void);

int main(int argc, char *argv[])
{

    struct GModule *module;
    struct Option *group_opt, *loc_opt, *mapset_opt, *elev_opt;
    struct Option *math_opt, *unit_opt, *nd_opt;
    struct Flag *print_flag;

    char location[GMAPSET_MAX];
    char mapset[GMAPSET_MAX];
    char group[GNAME_MAX];

    char *elev_layer;
    char *mapset_elev, *mapset_elev_old;
    char *location_elev, *location_elev_old;
    char *math_exp;
    char *units;
    char *nd;

    char buf[GPATH_MAX];
    int stat;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("imagery"));
    G_add_keyword(_("orthorectify"));
    module->description =
	_("Select or modify the target elevation model.");

    group_opt = G_define_standard_option(G_OPT_I_GROUP);
    group_opt->description =
	_("Name of imagery group for ortho-rectification");

    loc_opt = G_define_standard_option(G_OPT_M_LOCATION);
    loc_opt->required = NO;
    loc_opt->description =
	_("Name of the target location");

    mapset_opt = G_define_standard_option(G_OPT_M_MAPSET);
    mapset_opt->required = NO;
    mapset_opt->description =
	_("Name of the target mapset");

    elev_opt = G_define_standard_option(G_OPT_R_ELEV);
    elev_opt->required = NO;
    elev_opt->description =
	_("Name of elevation map to use for ortho-rectification");

    math_opt = G_define_standard_option(G_OPT_M_NULL_VALUE);
    math_opt->key = "math_expression";
    math_opt->required = NO;
    math_opt->description =
	_("Math expression to convert to real elevation");

    unit_opt = G_define_standard_option(G_OPT_M_UNITS);
    unit_opt->required = NO;
    unit_opt->description =
	_("Unit of the elevation map");

    nd_opt = G_define_standard_option(G_OPT_M_NULL_VALUE);
    nd_opt->required = NO;
    nd_opt->description =
	_("No data value");

    print_flag = G_define_flag();
    print_flag->key = 'p';
    print_flag->description =
	_("Print currently selected elevation map and exit");

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

    elev_layer = (char *)G_malloc(GNAME_MAX * sizeof(char));
    mapset_elev = (char *)G_malloc(GMAPSET_MAX * sizeof(char));
    mapset_elev_old = (char *)G_malloc(GMAPSET_MAX * sizeof(char));
    location_elev = (char *)G_malloc(80 * sizeof(char));
    location_elev_old = (char *)G_malloc(80 * sizeof(char));
    math_exp = (char *)G_malloc(80 * sizeof(char));
    units = (char *)G_malloc(80 * sizeof(char));
    nd = (char *)G_malloc(80 * sizeof(char));

    *elev_layer = 0;
    *mapset_elev = 0;
    *mapset_elev_old = 0;
    *location_elev = 0;
    *location_elev_old = 0;
    *math_exp = 0;
    *units = 0;
    *nd = 0;

    strcpy(group, group_opt->answer);
    if (loc_opt->answer)
    	strcpy(location_elev, loc_opt->answer);
    if (mapset_opt->answer)
    	strcpy(mapset_elev, mapset_opt->answer);
    /*if(elev_opt->answer)
    	strcpy(elev_layer, elev_opt->answer);*/
    if (math_opt->answer)
    	strcpy(math_exp, math_opt->answer);
    if (unit_opt->answer)
    	strcpy(units, unit_opt->answer);
    if (nd_opt->answer)
    	strcpy(nd, nd_opt->answer);
	
    if (!I_get_target(group, location, mapset)) {
	G_fatal_error(_("Please select a target for group [%s] first"), group);
    }

    sprintf(buf, "%s/%s", G_gisdbase(), location);
    if (access(buf, 0) != 0) {
	G_fatal_error(_("Target location [%s] not found\n"), location);
    }

    /*Report the contents of the ELEVATION file as in the GROUP */
    if (print_flag->answer) {
	/*If the content is empty report an error */
	if (!I_get_group_elev(group, elev_layer, mapset_elev, location_elev, math_exp, units, nd)) {
		G_fatal_error(_("Cannot find default elevation map for target in group [%s]"),group);
	}
	/*If there is a content, print it */
	else {
	    fprintf(stdout, "map:\t\t\t%s\n",elev_layer);
	    fprintf(stdout, "mapset:\t\t\t%s\n",mapset_elev);
	    fprintf(stdout, "location:\t\t%s\n",location_elev);
	    fprintf(stdout, "math expression:\t%s\n",math_exp);
	    fprintf(stdout, "units:\t\t\t%s\n",units);
	    fprintf(stdout, "nodata value:\t\t%s\n",nd);
	    exit(EXIT_SUCCESS);
	}    
    }

    /*Creating a Target environment*/
    G_create_alt_env();
    /*Set an alternate Location */
    G_setenv_nogisrc("LOCATION_NAME", location);
    /*Check for permissions in mapset */
    stat = G_mapset_permissions(mapset);
    /*We have permissions on the mapset */
    if (stat > 0) {
	/*Set the alternate mapset */
	G_setenv_nogisrc("MAPSET", mapset);
	/*Make an alternate search path */
	G_create_alt_search_path();
	/*Switch from current to alternate environment */
	G_switch_env();
	/*Switch to alternate search path */
	G_switch_search_path();
	/*Source Env = 0 ; Target Env = 1 */
	which_env = 0;
        /*Select the target environment */
	select_target_env();
	/*Start working on the Target mapset */
        if (!elev_opt->answer) {
	    /* select current location */
	    select_current_env();
	    G_fatal_error(_("Elevation map name is missing. Please set '%s' option"),
	        elev_opt->key);
	}
	
	/* return to current Location/mapset to write in the group file */
	select_current_env();
	
	/* load information from the ELEVATION file in the GROUP */
	if (I_find_group_elev_file(group)) {
	    I_get_group_elev(group, elev_layer, mapset_elev_old, location_elev_old,
	                     math_exp, units, nd);
	    if (*location_elev == 0)
		strcpy(location_elev, location_elev_old);
	    if (*mapset_elev == 0)
		strcpy(mapset_elev, mapset_elev_old);
	}
	/* if location and/or mapset of elevation are not set, use target */
	if (*mapset_elev == 0)
	    strcpy(mapset_elev, mapset);
	if (*location_elev == 0)
	    strcpy(location_elev, location);

	/* select target location */
	select_target_env();
	/* elevation map exists in target ? */
	if (G_find_raster2(elev_opt->answer, mapset_elev) == NULL) {
            /* select current location */
	    select_current_env();
	    G_fatal_error(_("Raster map <%s> not found"), elev_opt->answer);
	}
	/* select current location */
	select_current_env();

	/* Modify ELEVATION file in source GROUP */
	I_put_group_elev(group, elev_opt->answer, mapset_elev, location_elev, 
			 math_exp, units, nd);

        G_message(_("Group [%s] in location [%s] mapset [%s] now uses elevation map [%s]"),
	          group, G_location(), G_mapset(), elev_opt->answer);
    }
    else {
	G_fatal_error(_("Mapset [%s] in target location [%s] - %s "),
                  mapset, location,
		  stat == 0 ? _("permission denied\n") : _("not found\n"));
    }

    return(EXIT_SUCCESS);
}


int select_current_env(void)
{
    if (which_env != 0) {
	G_switch_env();
	G_switch_search_path();
	which_env = 0;
    }

    return 0;
}

int select_target_env(void)
{
    if (which_env != 1) {
	G_switch_env();
	G_switch_search_path();
	which_env = 1;
    }

    return 0;
}
