#ifndef IMESH_REC_CBIND_H__
#define IMESH_REC_CBIND_H__

#include "moab/MOABConfig.h"
#include "imesh_export.h"

#include "iMesh.h"
#include "iMesh_extensions_protos.h"
#ifdef MOAB_HAVE_MPI
#include "iMeshP.h"
#include "moab_mpi.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

    /**\brief  Get entities of specific type and/or topology in set or instance, recursive
     *
     * Get entities of specific type and/or topology in set or instance.  If recursive
     * is passed in non-zero, includes entities in owned sets.  All 
     * entities of a given type or topology are requested by specifying
     * iBase_ALL_TOPOLOGIES or iBase_ALL_TYPES, respectively.  Specified type
     * or topology must be a value in the iBase_EntityType or iMesh_EntityTopology
     * enumeration, respectively.
     * \param instance iMesh instance handle
     * \param entity_set_handle Entity set being queried
     * \param entity_type Type of entities being requested
     * \param entity_topology Topology of entities being requested
     * \param recursive If non-zero, gets entities in owned sets too
     * \param *entity_handles Pointer to array of entity handles returned 
     *        from function
     * \param *entity_handles_allocated Pointer to allocated size of 
     *        entity_handles array
     * \param *entity_handles_size Pointer to occupied size of entity_handles array
     * \param *err Pointer to error type returned from function
     */
  IMESH_EXPORT
  void iMesh_getEntitiesRec(iMesh_Instance instance,
                            /*in*/ const iBase_EntitySetHandle entity_set_handle,
                            /*in*/ const int entity_type,
                            /*in*/ const int entity_topology,
                            /*in*/ const int recursive,
                            /*out*/ iBase_EntityHandle** entity_handles,
                            /*out*/ int* entity_handles_allocated,
                            /*out*/ int* entity_handles_size,
                            /*out*/ int *err);

    /**\brief  Get the number of entities with the specified type in the instance or set, recursive
     *
     * Get the number of entities with the specified type in the instance 
     * or set.  If recursive is passed in non-zero, includes entities in owned sets.  
     * If entity set handle is zero, return information for instance, 
     * otherwise for set.  Value of entity type must be from the
     * iBase_EntityType enumeration.  If iBase_ALL_TYPES is specified,
     * total number of entities (excluding entity sets) is returned.
     * \param instance iMesh instance handle
     * \param entity_set_handle Entity set being queried
     * \param entity_type Type of entity requested
     * \param recursive If non-zero, includes entities in owned sets too
     * \param num_type Pointer to number of entities, returned from function
     * \param *err Pointer to error type returned from function
     */
  IMESH_EXPORT
  void iMesh_getNumOfTypeRec(iMesh_Instance instance,
                             /*in*/ const iBase_EntitySetHandle entity_set_handle,
                             /*in*/ const int entity_type,
                             /*in*/ const int recursive,
                             /*out*/ int *num_type, 
                             /*out*/ int *err);

    /**\brief  Get the number of entities with the specified topology in the instance or set
     *
     * Get the number of entities with the specified topology in the instance 
     * or set.  If recursive is passed in non-zero, includes entities in owned sets.  
     * If entity set handle is zero, return information for instance,
     * otherwise for set.  Value of entity topology must be from the
     * iMesh_EntityTopology enumeration.  If iMesh_ALL_TOPOLOGIES is specified,
     * total number of entities (excluding entity sets) is returned.
     * \param instance iMesh instance handle
     * \param entity_set_handle Entity set being queried
     * \param entity_topology Topology of entity requested
     * \param recursive If non-zero, includes entities in owned sets too
     * \param num_topo Pointer to number of entities, returned from function
     * \param *err Pointer to error type returned from function
     */
  IMESH_EXPORT
  void iMesh_getNumOfTopoRec(iMesh_Instance instance,
                             /*in*/ const iBase_EntitySetHandle entity_set_handle,
                             /*in*/ const int entity_topology,
                             /*in*/ const int recursive,
                             /*out*/ int *num_topo, 
                             /*out*/ int *err);


    /**\brief  Get entities with specified type, topology, tag(s) and (optionally) tag value(s)
     *
     * Get entities with the specified type, topology, tag(s), and optionally tag value(s).
     * If tag values pointer is input as zero, entities with specified tag(s) are returned,
     * regardless of their value.
     * \param instance iMesh instance handle
     * \param entity_set_handle Entity set being queried
     * \param entity_type Type of entities being requested
     * \param entity_topology Topology of entities being requested
     * \param tag_handles Array of tag handles
     * \param tag_vals Array of tag values (zero if values not requested)
     * \param num_tags_vals Number of tags and optionally values
     * \param recursive If non-zero, gets entities in owned sets too
     * \param *entity_handles Pointer to array of entity handles returned 
     *        from function
     * \param *entity_handles_allocated Pointer to allocated size of 
     *        entity_handles array
     * \param *entity_handles_size Pointer to occupied size of entity_handles array
     * \param *err Pointer to error type returned from function
     */
  IMESH_EXPORT
  void iMesh_getEntsByTagsRec(iMesh_Instance instance,
                              /*in*/ const iBase_EntitySetHandle entity_set_handle,
                              /*in*/ const int entity_type,
                              /*in*/ const int entity_topology,
                              /*in*/ const iBase_TagHandle *tag_handles,
                              /*in*/ const char * const *tag_vals,
                              /*in*/ const int num_tags_vals,
                              /*in*/ const int recursive,
                              /*out*/ iBase_EntityHandle** entity_handles,
                              /*out*/ int* entity_handles_allocated,
                              /*out*/ int* entity_handles_size,
                              /*out*/ int *err);

    /**\brief  Get entity sets with specified tag(s) and (optionally) tag value(s)
     *
     * Get entity sets with the specified tag(s) and optionally tag value(s).
     * If tag values pointer is input as zero, entities with specified tag(s) are returned,
     * regardless of their value.
     * \param instance iMesh instance handle
     * \param entity_set_handle Entity set being queried
     * \param tag_handles Array of tag handles
     * \param tag_vals Array of tag values (zero if values not requested)
     * \param num_tags_vals Number of tags and optionally values
     * \param recursive If non-zero, gets entities in owned sets too
     * \param *set_handles Pointer to array of entity handles returned 
     *        from function
     * \param *set_handles_allocated Pointer to allocated size of 
     *        set_handles array
     * \param *set_handles_size Pointer to occupied size of entity_handles array
     * \param *err Pointer to error type returned from function
     */
  IMESH_EXPORT
  void iMesh_getEntSetsByTagsRec(iMesh_Instance instance,
                                 /*in*/ const iBase_EntitySetHandle entity_set_handle,
                                 /*in*/ const iBase_TagHandle *tag_handles,
                                 /*in*/ const char * const *tag_vals,
                                 /*in*/ const int num_tags_vals,
                                 /*in*/ const int recursive,
                                 /*out*/ iBase_EntitySetHandle** set_handles,
                                 /*out*/ int* set_handles_allocated,
                                 /*out*/ int* set_handles_size,
                                 /*out*/ int *err);

    /**\brief Get MBCN type corresponding to iMesh topology value
     *
     * Get MBCN type corresponding to iMesh topology value.  Required for input
     * to MBCN canonical numbering functions, which are written in terms of 
     * MBCN entity types.  Returns -1 for type if entity topology is out of
     * bounds, or MBMAXTYPE if no corresponding MBCN type exists.
     * \param imesh_entity_topology iMesh_EntityTopology value
     * \param mbcn_type MBEntityType corresponding to entity topology
     */
  IMESH_EXPORT
  void iMesh_MBCNType(/*in*/ const int imesh_entity_topology,
                      /*out*/ int *mbcn_type);
    

  /**\brief Access tag data via direct pointer into contiguous blocks
   *
   * Iteratively obtain direct access to contiguous blocks of tag
   * storage.  This function cannot be used with bit tags because
   * of the compressed bit storage.  This function cannot be used
   * with variable length tags because it does not provide a mechanism
   * to determine the length of the value for each entity.  This
   * function may be used with sparse tags, but if it is used, it
   * will return data for a single entity at a time.  
   *
   *\Note If this function is called for entities for which no tag value
   *      has been set, but for which a default value exists, it will 
   *      force the allocation of explicit storage for each such entity
   *      even though MOAB would normally not explicitly store tag values
   *      for such entities.
   *
   *\Example:
   *\code
   *\endcode
   */
  IMESH_EXPORT
  void iMesh_tagIterate(iMesh_Instance instance,
                          /**< [in] iMesh instance */
                        const iBase_TagHandle tag_handle,
                          /**< [in] Tag being queried */
                        iBase_EntityArrIterator entArr_iterator, 
                          /**< [in] Iterator being queried */
                        void* tag_value, 
                          /**< [out] Pointer to pointer that will be set to tag data memory */
                        int* count,
                          /**< [out] Number of contiguous entities in this subrange */
                        int* err  
                          /**< [out] Returned Error status (see iBase_ErrorType) */
                        );

  /**\brief Access connectivity data via direct pointer into contiguous blocks
   *
   * Iteratively obtain direct access to contiguous blocks of connectivity
   * storage.
   *
   */
  IMESH_EXPORT
  void iMesh_connectIterate(iMesh_Instance instance,
                              /**< [in] iMesh instance */
                            iBase_EntityArrIterator entArr_iterator, 
                              /**< [in] Iterator being queried */
                            iBase_EntityHandle **connect,
                              /**< [out] Pointer to pointer that will be set to connectivity data memory */
                            int* verts_per_entity,
                              /**< [out] Number of vertices per entity in this subrange */
                            int* count,
                              /**< [out] Number of contiguous entities in this subrange */
                            int* err  
                              /**< [out] Returned Error status (see iBase_ErrorType) */
                            );

  /**\brief Access coordinates data via direct pointer into contiguous blocks
   *
   * Iteratively obtain direct access to contiguous blocks of coordinate
   * storage.
   *
   */
  IMESH_EXPORT
  void iMesh_coordsIterate(iMesh_Instance instance,
                             /**< [in] iMesh instance */
                           iBase_EntityArrIterator entArr_iterator, 
                             /**< [in] Iterator being queried */
                           double **coordsx,
                             /**< [out] Pointer to pointer x coordinates */
                           double **coordsy,
                             /**< [out] Pointer to pointer y coordinates */
                           double **coordsz,
                             /**< [out] Pointer to pointer z coordinates */
                           int* count,
                             /**< [out] Number of contiguous entities in this subrange */
                           int* err  
                             /**< [out] Returned Error status (see iBase_ErrorType) */
                           );

/***************************************************************************//**
 * \ingroup  EntityIterators
 * \brief  Step the iterator a specified number of entities
 *
 * Step the iterator a specified number of entities.  If this number is greater
 * than the number of entities left in the iterator, the iterator is placed
 * at the end and at_end is returned non-zero; otherwise at_end is returned zero.
 ******************************************************************************/

IMESH_EXPORT
void iMesh_stepEntIter(
    iMesh_Instance instance, 
        /**< [in] iMesh instance handle */
    iBase_EntityIterator ent_iterator, 
        /**< [in] Iterator being queried */
    int step_length, 
        /**< [in] Number of entities to step the iterator */
    int* at_end, 
        /**< [out] Non-zero if iterator is at the end of the iteration */
    int* err  
        /**< [out] Returned Error status (see iBase_ErrorType) */
);

IMESH_EXPORT
void iMesh_stepEntArrIter(
    iMesh_Instance instance, 
        /**< [in] iMesh instance handle */
    iBase_EntityArrIterator entArr_iterator, 
        /**< [in] Iterator being queried */
    int step_length, 
        /**< [in] Number of entities to step the iterator */
    int* at_end, 
        /**< [out] Non-zero if iterator is at the end of the iteration */
    int* err  
        /**< [out] Returned Error status (see iBase_ErrorType) */
);

/***************************************************************************//**
 * \ingroup  EntityIterators
 * \brief  Initialize an array iterator over specified entity type, topology,
 *  and size, with an optional recursive flag.
 *
 * Initialize an array iterator over specified entity type, topology, and 
 * size, for a specified set or instance.  Iterator returned can be used 
 * as input to functions returning entities for the iterator.  If all 
 * entities of a specified type and/or topology are to be iterated, 
 * specify iBase_ALL_TYPES or iMesh_ALL_TOPOLOGIES, respectively.  
 * Specified type or topology must be a value in the iBase_EntityType or 
 * iMesh_EntityTopology enumerations, respectively.  If recursive is true,
 * entities are retrieved recursively through contained (but not child) sets.
 ******************************************************************************/

IMESH_EXPORT
void iMesh_initEntArrIterRec(
    iMesh_Instance instance, 
        /**< [in] iMesh instance handle */
    const iBase_EntitySetHandle entity_set_handle, 
        /**< [in] Entity set being iterated */
    const int requested_entity_type, 
        /**< [in] Type of entity to iterate */
    const int requested_entity_topology, 
        /**< [in] Topology of entity to iterate */
    const int requested_array_size, 
        /**< [in] Size of chunks of handles returned for each value of the
             iterator */
    const int resilient,
        /**< [in] If zero, return a non-resilient iterator.
                  Otherwise, a resilient iterator (\ref resilient) */
    const int recursive,
      /**< [in] If non-zero, entities retrieved recursively */
    iBase_EntityArrIterator* entArr_iterator, 
        /**< [out] Pointer to iterator returned from function */
    int* err  
        /**< [out] Returned Error status (see iBase_ErrorType) */
);

/***************************************************************************//**
 * \ingroup  Tags 
 * \brief  Get all the tags associated with the entire interface
 *
 * Get all the tags associated with the entire interface
 ******************************************************************************/

IMESH_EXPORT
void iMesh_getAllIfaceTags(iMesh_Instance instance,
                           /*inout*/ iBase_TagHandle **tag_handles,
                           /*inout*/ int *tag_handles_allocated,
                           /*out*/ int *tag_handles_size,
                           /*out*/ int *err
);

/***************************************************************************//**
 * \ingroup  Tags
 * \brief  Create a tag with options
 *
 * Create a tag with options; allows creation of Dense and Bit tags through iMesh
 * Allowable options are:
 * TAG_STORAGE_TYPE={DENSE | SPARSE | BIT | MESH}
 * TAG_DEFAULT_VALUE=<value> (data type of value should match tag data type)
 ******************************************************************************/

IMESH_EXPORT
void iMesh_createTagWithOptions(iMesh_Instance instance,
                                  /**< [in] iMesh instance handle */
                                  /*in*/ const char* tag_name,
                                  /**< [in] tag name*/
                                  /*in*/ const char* tmp_tag_options,
                                  /**< [in] options string */
                                  /*in*/ const int tag_size,
                                  /**< [in] tag size, in number of values */
                                  /*in*/ const int tag_type,
                                  /**< [in] tag data type (int, double, etc.) */
                                  /*out*/ iBase_TagHandle* tag_handle, 
                                  /**< [out] handle of new tag */
                                  /*out*/ int *err,
                                  /**< [out] error */
                                  /*in*/ const int tag_name_len,
                                  /**< [in] length of tag name string */
                                  /*in*/ const int tag_options_len);
                                  /**< [in] length of options string */
    
/***************************************************************************//**
 * \ingroup  ScdMesh
 * \brief  Create a structured mesh
 *
 * Create a structured mesh, with local and (optionally) global ijk parameters and
 * optional physical positions.  If running in parallel, can request shared vertex resolution
 * and optional number and type of ghost layers of elements.  Global parameters are used to compute
 * global ids, which are used in shared vertex resolution.
 ******************************************************************************/

IMESH_EXPORT
void iMesh_createStructuredMesh(
        iMesh_Instance instance,
          /**< [in] iMesh instance handle */
        int *local_dims,
          /**< [in] Min/max corners of local ijk parameters, -1 for unused dimensions; specified as
                    ilo, jlo, klo, ihi, jhi, khi. */
        int *global_dims,
          /**< [in] Min/max corners of global ijk parameters, -1 for unused dimensions; NULL if running in serial. 
                    Order similar to local_dims. */
        double *i_vals,
          /**< [in] Physical positions of i values, NULL if not placed in physical space. */
        double *j_vals,
          /**< [in] Physical positions of j values, NULL if not placed in physical space. */
        double *k_vals,
          /**< [in] Physical positions of k values, NULL if not placed in physical space. */
        int resolve_shared,
          /**< [in] Non-zero if running in parallel and resolution of shared vertices is desired, zero otherwise. */
        int ghost_dim,
          /**< [in] Dimension of entities to ghost, -1 if none desired. */
        int bridge_dim,
          /**< [in] Dimension of bridge entities used to compute ghosts, -1 if no ghosts desired. */
        int num_layers,
          /**< [in] Number of layers of ghosts desired, -1 if no ghosts desired. */
        int addl_ents,
          /**< [in] Dimension of addition entities adjacent to ghosts to exchange. */
        int vert_gids,
          /**< [in] If non-zero, assigns global ids to vertices, according to global parameterization. */
        int elem_gids,
          /**< [in] If non-zero, assigns global ids to elements, according to global parameterization. */
        iBase_EntitySetHandle* set_handle, 
          /**< [inout] A set to which the underlying ScdBox set will be added.  NULL if not desired. 
           *           If *NULL, will be set directly to the underlying ScdBox's set. */
        int *err
          /**< [out] Error flag. */
);
/***************************************************************************//**
 * \brief  Free memory allocated with malloc
 *
 ******************************************************************************/

IMESH_EXPORT
void iMesh_freeMemory(
        iMesh_Instance instance,
          /**< [in] iMesh instance handle */
         void ** ptrToMem);

/***************************************************************************//**
 * \defgroup ScdMesh Structured Mesh
 * \ingroup iMeshExtensions
 ******************************************************************************/

/***************************************************************************//**
 * \defgroup iMeshExtensions iMesh Extensions
 * \ingroup iMesh
 ******************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
