// $Id$
//
// Earth System Modeling Framework
// Copyright (c) 2002-2025, University Corporation for Atmospheric Research,
// Massachusetts Institute of Technology, Geophysical Fluid Dynamics
// Laboratory, University of Michigan, National Centers for Environmental
// Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
// NASA Goddard Space Flight Center.
// Licensed under the University of Illinois-NCSA License.
//
//=============================================================================

#define ESMC_FILENAME "ESMC_InfoCDefGeneric.C"

//=============================================================================
// DO NOT EDIT THIS FILE DIRECTLY. IT IS GENERATED FROM A JINJA2 TEMPLATE FILE.
//   - Template files located in scripts/jinja2_templating/templates
//   - The template file is: ESMC_InfoCDefGeneric.jinja2
//   - All code edits must be done in that template file then re-generated
//   - See scripts/jinja2_templating/README.md for guidance
//=============================================================================

// Info C-Fortran method implementation (body) file

// single blank line to make protex happy.
//BOPI

//EOPI
//-----------------------------------------------------------------------------
//
// !DESCRIPTION:
//
//-----------------------------------------------------------------------------

#include "ESMC.h"
#include "ESMCI_Base.h"
#include "ESMCI_Macros.h"
#include "ESMCI_Info.h"
#include "ESMCI_LogErr.h"
#include "ESMCI_Util.h"
#include "ESMCI_VM.h"
#include "json.hpp"

#include <iostream>
#include <vector>

using json = nlohmann::json;

//-----------------------------------------------------------------------------
 // leave the following line as-is; it will insert the cvs ident string
 // into the object file for tracking purposes.
 static const char *const version = "$Id$";
//-----------------------------------------------------------------------------

extern "C" {

//-----------------------------------------------------------------------------
// InfoGet --------------------------------------------------------------------
//-----------------------------------------------------------------------------

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetR4()"
void ESMC_InfoGetR4(ESMCI::Info *info, char *key, float &value, int &esmc_rc, float *def, int *index, int &fortran_bool_recursive) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    value = info->get<float>(local_key, def, index, recursive, nullptr, false);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetR8()"
void ESMC_InfoGetR8(ESMCI::Info *info, char *key, double &value, int &esmc_rc, double *def, int *index, int &fortran_bool_recursive) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    value = info->get<double>(local_key, def, index, recursive, nullptr, false);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetI4()"
void ESMC_InfoGetI4(ESMCI::Info *info, char *key, int &value, int &esmc_rc, int *def, int *index, int &fortran_bool_recursive) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    value = info->get<int>(local_key, def, index, recursive, nullptr, false);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetI8()"
void ESMC_InfoGetI8(ESMCI::Info *info, char *key, long long int &value, int &esmc_rc, long long int *def, int *index, int &fortran_bool_recursive) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    value = info->get<long long int>(local_key, def, index, recursive, nullptr, false);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetLG()"
void ESMC_InfoGetLG(ESMCI::Info *info, char *key, bool &value, int &esmc_rc, bool *def, int *index, int &fortran_bool_recursive) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    value = info->get<bool>(local_key, def, index, recursive, nullptr, false);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetArrayR4()"
void ESMC_InfoGetArrayR4(ESMCI::Info *info, char *key, float *value, int &count, int &esmc_rc, int &fortran_bool_recursive, bool &fortran_bool_scalarToArray, int &expected_size) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    bool scalar_to_array = fortran_bool_scalarToArray == 1;
    const json *j = info->getPointer(local_key, recursive);
    bool is_array = j->is_array();
    if (!is_array && !scalar_to_array) {
      std::string msg = "Array requested but type in JSON storage is not an array. Key is: " + local_key;
      ESMC_CHECK_RC("ESMF_RC_ATTR_WRONGTYPE", ESMF_RC_ATTR_WRONGTYPE, msg)
    }
    if (is_array) {
      const json::array_t *ap = j->get_ptr<const json::array_t *>();
      count = (int)ap->size();
      // If the expected size is a negative one, the data request is for an allocatable
      // and the expected size is irrelevant since the outgoing array will be allocated
      // in Fortran.
      if (expected_size != -1 && count != expected_size) {
        ESMC_CHECK_RC("ESMF_RC_ATTR_ITEMSOFF", ESMF_RC_ATTR_ITEMSOFF, "values allocation size does not match size in Info storage")
      }
      for (int ii=0; ii<count; ++ii) {
        try {
          value[ii] = ap->at(ii);
        }
        catch (std::out_of_range &exc) {
          ESMC_CHECK_RC("ESMF_RC_ARG_OUTOFRANGE", ESMF_RC_ARG_OUTOFRANGE, std::string(exc.what()))
        }
        ESMC_CATCH_ERRPASSTHRU
      }
    } else {
      value[0] = info->get<float>(local_key, nullptr, nullptr, recursive, nullptr, false);
    }
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetArrayR8()"
void ESMC_InfoGetArrayR8(ESMCI::Info *info, char *key, double *value, int &count, int &esmc_rc, int &fortran_bool_recursive, bool &fortran_bool_scalarToArray, int &expected_size) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    bool scalar_to_array = fortran_bool_scalarToArray == 1;
    const json *j = info->getPointer(local_key, recursive);
    bool is_array = j->is_array();
    if (!is_array && !scalar_to_array) {
      std::string msg = "Array requested but type in JSON storage is not an array. Key is: " + local_key;
      ESMC_CHECK_RC("ESMF_RC_ATTR_WRONGTYPE", ESMF_RC_ATTR_WRONGTYPE, msg)
    }
    if (is_array) {
      const json::array_t *ap = j->get_ptr<const json::array_t *>();
      count = (int)ap->size();
      // If the expected size is a negative one, the data request is for an allocatable
      // and the expected size is irrelevant since the outgoing array will be allocated
      // in Fortran.
      if (expected_size != -1 && count != expected_size) {
        ESMC_CHECK_RC("ESMF_RC_ATTR_ITEMSOFF", ESMF_RC_ATTR_ITEMSOFF, "values allocation size does not match size in Info storage")
      }
      for (int ii=0; ii<count; ++ii) {
        try {
          value[ii] = ap->at(ii);
        }
        catch (std::out_of_range &exc) {
          ESMC_CHECK_RC("ESMF_RC_ARG_OUTOFRANGE", ESMF_RC_ARG_OUTOFRANGE, std::string(exc.what()))
        }
        ESMC_CATCH_ERRPASSTHRU
      }
    } else {
      value[0] = info->get<double>(local_key, nullptr, nullptr, recursive, nullptr, false);
    }
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetArrayI4()"
void ESMC_InfoGetArrayI4(ESMCI::Info *info, char *key, int *value, int &count, int &esmc_rc, int &fortran_bool_recursive, bool &fortran_bool_scalarToArray, int &expected_size) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    bool scalar_to_array = fortran_bool_scalarToArray == 1;
    const json *j = info->getPointer(local_key, recursive);
    bool is_array = j->is_array();
    if (!is_array && !scalar_to_array) {
      std::string msg = "Array requested but type in JSON storage is not an array. Key is: " + local_key;
      ESMC_CHECK_RC("ESMF_RC_ATTR_WRONGTYPE", ESMF_RC_ATTR_WRONGTYPE, msg)
    }
    if (is_array) {
      const json::array_t *ap = j->get_ptr<const json::array_t *>();
      count = (int)ap->size();
      // If the expected size is a negative one, the data request is for an allocatable
      // and the expected size is irrelevant since the outgoing array will be allocated
      // in Fortran.
      if (expected_size != -1 && count != expected_size) {
        ESMC_CHECK_RC("ESMF_RC_ATTR_ITEMSOFF", ESMF_RC_ATTR_ITEMSOFF, "values allocation size does not match size in Info storage")
      }
      for (int ii=0; ii<count; ++ii) {
        try {
          value[ii] = ap->at(ii);
        }
        catch (std::out_of_range &exc) {
          ESMC_CHECK_RC("ESMF_RC_ARG_OUTOFRANGE", ESMF_RC_ARG_OUTOFRANGE, std::string(exc.what()))
        }
        ESMC_CATCH_ERRPASSTHRU
      }
    } else {
      value[0] = info->get<int>(local_key, nullptr, nullptr, recursive, nullptr, false);
    }
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetArrayI8()"
void ESMC_InfoGetArrayI8(ESMCI::Info *info, char *key, long long int *value, int &count, int &esmc_rc, int &fortran_bool_recursive, bool &fortran_bool_scalarToArray, int &expected_size) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    bool scalar_to_array = fortran_bool_scalarToArray == 1;
    const json *j = info->getPointer(local_key, recursive);
    bool is_array = j->is_array();
    if (!is_array && !scalar_to_array) {
      std::string msg = "Array requested but type in JSON storage is not an array. Key is: " + local_key;
      ESMC_CHECK_RC("ESMF_RC_ATTR_WRONGTYPE", ESMF_RC_ATTR_WRONGTYPE, msg)
    }
    if (is_array) {
      const json::array_t *ap = j->get_ptr<const json::array_t *>();
      count = (int)ap->size();
      // If the expected size is a negative one, the data request is for an allocatable
      // and the expected size is irrelevant since the outgoing array will be allocated
      // in Fortran.
      if (expected_size != -1 && count != expected_size) {
        ESMC_CHECK_RC("ESMF_RC_ATTR_ITEMSOFF", ESMF_RC_ATTR_ITEMSOFF, "values allocation size does not match size in Info storage")
      }
      for (int ii=0; ii<count; ++ii) {
        try {
          value[ii] = ap->at(ii);
        }
        catch (std::out_of_range &exc) {
          ESMC_CHECK_RC("ESMF_RC_ARG_OUTOFRANGE", ESMF_RC_ARG_OUTOFRANGE, std::string(exc.what()))
        }
        ESMC_CATCH_ERRPASSTHRU
      }
    } else {
      value[0] = info->get<long long int>(local_key, nullptr, nullptr, recursive, nullptr, false);
    }
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoGetArrayLG()"
void ESMC_InfoGetArrayLG(ESMCI::Info *info, char *key, bool *value, int &count, int &esmc_rc, int &fortran_bool_recursive, bool &fortran_bool_scalarToArray, int &expected_size) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    bool recursive = fortran_bool_recursive == 1;
    bool scalar_to_array = fortran_bool_scalarToArray == 1;
    const json *j = info->getPointer(local_key, recursive);
    bool is_array = j->is_array();
    if (!is_array && !scalar_to_array) {
      std::string msg = "Array requested but type in JSON storage is not an array. Key is: " + local_key;
      ESMC_CHECK_RC("ESMF_RC_ATTR_WRONGTYPE", ESMF_RC_ATTR_WRONGTYPE, msg)
    }
    if (is_array) {
      const json::array_t *ap = j->get_ptr<const json::array_t *>();
      count = (int)ap->size();
      // If the expected size is a negative one, the data request is for an allocatable
      // and the expected size is irrelevant since the outgoing array will be allocated
      // in Fortran.
      if (expected_size != -1 && count != expected_size) {
        ESMC_CHECK_RC("ESMF_RC_ATTR_ITEMSOFF", ESMF_RC_ATTR_ITEMSOFF, "values allocation size does not match size in Info storage")
      }
      for (int ii=0; ii<count; ++ii) {
        try {
          value[ii] = ap->at(ii);
        }
        catch (std::out_of_range &exc) {
          ESMC_CHECK_RC("ESMF_RC_ARG_OUTOFRANGE", ESMF_RC_ARG_OUTOFRANGE, std::string(exc.what()))
        }
        ESMC_CATCH_ERRPASSTHRU
      }
    } else {
      value[0] = info->get<bool>(local_key, nullptr, nullptr, recursive, nullptr, false);
    }
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

//-----------------------------------------------------------------------------
// InfoSet --------------------------------------------------------------------
//-----------------------------------------------------------------------------

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetR4()"
void ESMC_InfoSetR4(ESMCI::Info *info, char *key, float &value, bool &force, int &esmc_rc, int *index, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<float>(local_key, value, force, index, local_pkeyp);
    info->set_32bit_type_storage(local_key, true, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetR8()"
void ESMC_InfoSetR8(ESMCI::Info *info, char *key, double &value, bool &force, int &esmc_rc, int *index, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<double>(local_key, value, force, index, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetI4()"
void ESMC_InfoSetI4(ESMCI::Info *info, char *key, int &value, bool &force, int &esmc_rc, int *index, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<int>(local_key, value, force, index, local_pkeyp);
    info->set_32bit_type_storage(local_key, true, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetI8()"
void ESMC_InfoSetI8(ESMCI::Info *info, char *key, long long int &value, bool &force, int &esmc_rc, int *index, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<long long int>(local_key, value, force, index, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetLG()"
void ESMC_InfoSetLG(ESMCI::Info *info, char *key, bool &value, bool &force, int &esmc_rc, int *index, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<bool>(local_key, value, force, index, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetArrayR4()"
void ESMC_InfoSetArrayR4(ESMCI::Info *info, char *key, float *value, int &count, bool &force, int &esmc_rc, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<float>(local_key, value, count, force, local_pkeyp);
    info->set_32bit_type_storage(local_key, true, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetArrayR8()"
void ESMC_InfoSetArrayR8(ESMCI::Info *info, char *key, double *value, int &count, bool &force, int &esmc_rc, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<double>(local_key, value, count, force, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetArrayI4()"
void ESMC_InfoSetArrayI4(ESMCI::Info *info, char *key, int *value, int &count, bool &force, int &esmc_rc, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<int>(local_key, value, count, force, local_pkeyp);
    info->set_32bit_type_storage(local_key, true, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetArrayI8()"
void ESMC_InfoSetArrayI8(ESMCI::Info *info, char *key, long long int *value, int &count, bool &force, int &esmc_rc, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<long long int>(local_key, value, count, force, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

#undef  ESMC_METHOD
#define ESMC_METHOD "ESMC_InfoSetArrayLG()"
void ESMC_InfoSetArrayLG(ESMCI::Info *info, char *key, bool *value, int &count, bool &force, int &esmc_rc, char *pkey) {
  ESMC_CHECK_INIT(info, esmc_rc)
  esmc_rc = ESMF_FAILURE;
  try {
    std::string local_key(key);
    std::string local_pkey(pkey);
    std::string *local_pkeyp = nullptr;
    if (local_pkey.size() != 0) {local_pkeyp = &local_pkey;}
    info->set<bool>(local_key, value, count, force, local_pkeyp);
    esmc_rc = ESMF_SUCCESS;
  }
  ESMC_CATCH_ISOC
}

}  // extern "C"