#ifndef REMAP_VARS_H
#define REMAP_VARS_H

#include <cstdio>  // size_t
#include <array>

#include "field.h"

class RemapGradients
{
public:
  Varray<double> grad_lat;
  Varray<double> grad_lon;
  Varray<double> grad_latlon;

  void
  init(size_t size)
  {
    grad_lat.resize(size);
    grad_lon.resize(size);
    grad_latlon.resize(size);
  }

  RemapGradients(size_t size) { init(size); }
  RemapGradients() {}
};

enum class RemapMethod
{
  UNDEF,
  BILINEAR,
  BICUBIC,
  DISTWGT,
  CONSERV,
  CONSERV_SCRIP
};

enum class NormOpt
{
  NONE,
  DESTAREA,
  FRACAREA
};

struct RemapLink
{
  bool option;
  size_t max_links;
  size_t num_blks;
  Varray<size_t> num_links;
  Varray2D<size_t> src_add;
  Varray2D<size_t> dst_add;
  Varray2D<size_t> w_index;
};

struct RemapVars
{
  bool sort_add;
  bool pinit;               // true: if the pointers are initialized
  RemapMethod mapType;      // identifier for remapping method
  NormOpt normOpt;          // option for normalization (conserv only)
  long links_per_value;
  size_t max_links;         // current size of link arrays
  size_t num_links;         // actual number of links for remapping
  size_t num_wts;           // num of weights used in remapping
  size_t resize_increment;  // default amount to increase array size

  Varray<size_t> src_cell_add;  // source grid address for each link
  Varray<size_t> tgt_cell_add;  // target grid address for each link
  Varray<double> wts;           // map weights for each link [max_links*num_wts]

  RemapLink links;
};

void remap(Field &field2, double missval, size_t gridsize2, const RemapVars &rv, const Field &field1, RemapGradients &gradients);
void remap_laf(Field &field2, double missval, size_t gridsize2, const RemapVars &rv, const Field &field1);
void remap_avg(Field &field2, double missval, size_t gridsize2, const RemapVars &rv, const Field &field1);
void remap_vars_init(RemapMethod mapType, int remapOrder, RemapVars &rv);
void remap_vars_ensure_size(RemapVars &rv, size_t size);
void remap_vars_resize(RemapVars &rv, size_t size);
void remap_vars_reorder(RemapVars &rv);
void remap_vars_free(RemapVars &rv);
void remap_vars_check_weights(const RemapVars &rv);

#endif /* REMAP_VARS_H */
