#ifndef GRASS_RASTER_H
#define GRASS_RASTER_H

#include <grass/gis.h>

/*** defines ***/
#define RECLASS_TABLE 1
#define RECLASS_RULES 2
#define RECLASS_SCALE 3

#define CELL_TYPE 0
#define FCELL_TYPE 1
#define DCELL_TYPE 2

/*! \brief Interpolation methods

  For G_get_raster_sample(), INTERP_TYPE
*/
#define INTERP_UNKNOWN   0
#define INTERP_NEAREST   1		/* nearest neighbor interpolation  */
#define INTERP_BILINEAR  2		/* bilinear interpolation          */
#define INTERP_BICUBIC   3		/* bicubic interpolation           */

/*** typedefs ***/
typedef int RASTER_MAP_TYPE;

/* for G_get_raster_sample() */
typedef int INTERP_TYPE;

/*** structures ***/
struct Reclass
{
    char *name;			/* name of raster map being reclassed    */
    char *mapset;		/* mapset in which "name" is found      */
    int type;			/* type of reclass                      */
    int num;			/* size of reclass table                */
    CELL min;			/* table min                            */
    CELL max;			/* table max                            */
    CELL *table;		/* reclass table                        */
};

struct FPReclass_table
{
    DCELL dLow;			/* domain low */
    DCELL dHigh;		/* domain high */
    DCELL rLow;			/* range low */
    DCELL rHigh;		/* range high */
};

/* reclass structure from double to double used by r.recode to reclass */
/* between types: int to double, float to int,... */
struct FPReclass
{
    int defaultDRuleSet;	/* 1 if default domain rule set */
    int defaultRRuleSet;	/* 1 if default range rule set */
    int infiniteLeftSet;	/* 1 if negative infinite interval rule exists */
    int infiniteRightSet;	/* 1 if positive infinite interval rule exists */
    int rRangeSet;		/* 1 if range range (i.e. interval) is set */
    int maxNofRules;
    int nofRules;
    DCELL defaultDMin;		/* default domain minimum value */
    DCELL defaultDMax;		/* default domain maximum value */
    DCELL defaultRMin;		/* default range minimum value */
    DCELL defaultRMax;		/* default range maximum value */
    DCELL infiniteDLeft;	/* neg infinite rule */
    DCELL infiniteDRight;	/* neg infinite rule */
    DCELL infiniteRLeft;	/* pos infinite rule */
    DCELL infiniteRRight;	/* pos infinite rule */
    DCELL dMin;			/* minimum domain values in rules */
    DCELL dMax;			/* maximum domain values in rules */
    DCELL rMin;			/* minimum range values in rules */
    DCELL rMax;			/* maximum range values in rules */
    struct FPReclass_table *table;
};

struct Quant_table
{
    DCELL dLow;
    DCELL dHigh;
    CELL cLow;
    CELL cHigh;
};

struct Quant
{
    int truncate_only;
    int round_only;
    int defaultDRuleSet;
    int defaultCRuleSet;
    int infiniteLeftSet;
    int infiniteRightSet;
    int cRangeSet;
    int maxNofRules;
    int nofRules;
    DCELL defaultDMin;
    DCELL defaultDMax;
    CELL defaultCMin;
    CELL defaultCMax;
    DCELL infiniteDLeft;
    DCELL infiniteDRight;
    CELL infiniteCLeft;
    CELL infiniteCRight;
    DCELL dMin;
    DCELL dMax;
    CELL cMin;
    CELL cMax;
    struct Quant_table *table;

    struct
    {
	DCELL *vals;

	/* pointers to quant rules corresponding to the intervals btwn vals */
	struct Quant_table **rules;
	int nalloc;
	int active;
	DCELL inf_dmin;
	DCELL inf_dmax;
	CELL inf_min;
	CELL inf_max;
	/* all values smaller than inf_dmin become inf_min */
	/* all values larger than inf_dmax become inf_max */
	/* inf_min and/or inf_max can be NULL if there are no inf rules */
    } fp_lookup;
};

struct Categories
{
    CELL ncats;			/* total number of categories              */
    CELL num;			/* the highest cell values. Only exists    
				   for backwards compatibility = (CELL)
				   max_fp_values in quant rules          */
    char *title;		/* name of data layer                      */
    char *fmt;			/* printf-like format to generate labels   */
    float m1;			/* Multiplication coefficient 1            */
    float a1;			/* Addition coefficient 1                  */
    float m2;			/* Multiplication coefficient 2            */
    float a2;			/* Addition coefficient 2                  */
    struct Quant q;		/* rules mapping cell values to index in
				   list of labels                        */
    char **labels;		/* array of labels of size num             */
    int *marks;			/* was the value with this label was used? */
    int nalloc;
    int last_marked_rule;
    /* NOTE: to get a rule corresponfing to cats.labels[i], use */
    /* G_get_ith_c/f/d_raster_cat (pcats, i, val1, val2) */
    /* it calls */
    /* G_quant_get_ith_rule(&cats->q, i, val1, val2, &index, &index); */
    /* and idex ==i, because rule is added at the same time as a */
    /* label, and quant rules are never reordered. Olga apr,95 */
};

/*! \brief Raster history info (metadata)

  See History structure for implementation issues.
*/
enum History_field
{
    /*! \brief Raster name */
    HIST_MAPID,
    /*! \brief Raster title */
    HIST_TITLE,
    /*! \brief Raster mapset */
    HIST_MAPSET,
    /*! \brief User who creater raster map */
    HIST_CREATOR,
    /*! \brief Map type ("raster", "reclass", "GDAL-link", or "virtual") */
    HIST_MAPTYPE,
    /*! \brief Description of original data source (two lines) */
    HIST_DATSRC_1,
    HIST_DATSRC_2,
    /*! \brief One-line data description */
    HIST_KEYWRD,

    /*! \brief Number of fields to be defined in History structure */
    HIST_NUM_FIELDS
};

/*! \brief Raster history info (metadata) */
struct History
{
    /*! \brief Array of fields (see \ref History_field for details) */
    char *fields[HIST_NUM_FIELDS];
    /*! \brief Number of lines in lines array */
    int nlines;
    /*! \brief Lines array */
    char **lines;
};

struct Cell_stats
{
    struct Cell_stats_node
    {
	int idx;
	long *count;
	int left;
	int right;
    } *node;			/* tree of values */

    int tlen;			/* allocated tree size */
    int N;			/* number of actual nodes in tree */
    int curp;
    long null_data_count;
    int curoffset;
};

struct Histogram
{
    int num;

    struct Histogram_list
    {
	CELL cat;
	long count;
    } *list;
};

struct R_stats
{
    DCELL sum;
    DCELL sumsq;
    grass_int64 count;
};

struct Range
{
    CELL min;
    CELL max;
    int first_time;		/* whether or not range was updated */
    struct R_stats rstats;
};

struct FPRange
{
    DCELL min;
    DCELL max;
    int first_time;		/* whether or not range was updated */
    struct R_stats rstats;
};

struct FP_stats {
    int geometric;
    int geom_abs;
    int flip;
    int count;
    DCELL min, max;
    unsigned long *stats;
    unsigned long total;
};

struct GDAL_link;
struct R_vrt;

/*** prototypes ***/
#include <grass/defs/raster.h>

#endif /* GRASS_RASTER_H */
