/****************************************************************************
 *
 * MODULE:       r.latlong
 * AUTHOR(S):    Yann Chemin - yann.chemin@gmail.com
 * PURPOSE:      Calculates the longitude of the pixels in the map.
 *
 * COPYRIGHT: (C) 2002-2008, 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.
 *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grass/gis.h>
#include <grass/raster.h>
#include <grass/gprojects.h>
#include <grass/glocale.h>

int main(int argc, char *argv[])
{
    struct Cell_head cellhd; /*region+header info */
    int nrows, ncols;
    int row, col;
    int not_ll = 0; /*if proj is not lat/long, it will be 1. */

    struct GModule *module;
    struct Option *input1, *output1;
    struct Flag *flag1;
    struct History history; /*metadata */
    struct pj_info iproj, oproj, tproj;
    struct Key_Value *in_proj_info, *in_unit_info;

    /************************************/
    char *result1; /*output raster name */

    int infd;
    int outfd1;
    char *in;
    double xmin, ymin;
    double xmax, ymax;
    double stepx, stepy;
    double latitude, longitude;
    void *inrast;
    DCELL *outrast1;
    DCELL d;

    /************************************/
    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("latitude"));
    G_add_keyword(_("longitude"));
    G_add_keyword(_("projection"));
    module->description = _("Creates a latitude/longitude raster map.");

    /* Define the different options */
    input1 = G_define_standard_option(G_OPT_R_INPUT);

    output1 = G_define_standard_option(G_OPT_R_OUTPUT);
    output1->description =
        _("Name for output latitude or longitude raster map");

    flag1 = G_define_flag();
    flag1->key = 'l';
    flag1->description = _("Longitude output");

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

    in = input1->answer;
    result1 = output1->answer;

    /***************************************************/
    infd = Rast_open_old(in, "");
    Rast_get_cellhd(in, "", &cellhd);
    inrast = Rast_allocate_d_buf();

    /***************************************************/
    xmin = cellhd.west;
    xmax = cellhd.east;
    ymin = cellhd.south;
    ymax = cellhd.north;
    nrows = Rast_window_rows();
    ncols = Rast_window_cols();
    stepx = fabs(xmax - xmin) / (double)ncols;
    stepy = fabs(ymax - ymin) / (double)nrows;

    /*Stolen from r.sun */
    /* Set up parameters for projection to lat/long if necessary */
    if ((G_projection() != PROJECTION_LL)) {
        not_ll = 1;

        if ((in_proj_info = G_get_projinfo()) == NULL)
            G_fatal_error(
                _("Unable to get projection info of current location"));
        if ((in_unit_info = G_get_projunits()) == NULL)
            G_fatal_error(
                _("Unable to get projection units of current location"));
        if (pj_get_kv(&iproj, in_proj_info, in_unit_info) < 0)
            G_fatal_error(
                _("Unable to get projection key values of current location"));
        G_free_key_value(in_proj_info);
        G_free_key_value(in_unit_info);

        oproj.pj = NULL;
        tproj.def = NULL;

        if (GPJ_init_transform(&iproj, &oproj, &tproj) < 0)
            G_fatal_error(_("Unable to initialize coordinate transformation"));
    } /* End of stolen from r.sun */

    outrast1 = Rast_allocate_d_buf();

    outfd1 = Rast_open_new(result1, DCELL_TYPE);

    for (row = 0; row < nrows; row++) {
        G_percent(row, nrows, 2);

        Rast_get_d_row(infd, inrast, row);

        for (col = 0; col < ncols; col++) {
            latitude = ymax - ((double)row * stepy);
            longitude = xmin + ((double)col * stepx);
            if (not_ll) {
                if (GPJ_transform(&iproj, &oproj, &tproj, PJ_FWD, &longitude,
                                  &latitude, NULL) < 0)
                    G_fatal_error(
                        _("Error in %s (projection of input coordinate pair)"),
                        "GPJ_transform()");
            }
            if (flag1->answer)
                d = longitude;
            else
                d = latitude;
            outrast1[col] = d;
        }
        Rast_put_d_row(outfd1, outrast1);
    }
    G_free(inrast);
    Rast_close(infd);
    G_free(outrast1);
    Rast_close(outfd1);

    Rast_short_history(result1, "raster", &history);
    Rast_command_history(&history);
    Rast_write_history(result1, &history);

    exit(EXIT_SUCCESS);
}
