#include "DamselUtil.hpp"
#include "moab/Range.hpp"

#include "damsel.h"

namespace moab {

damsel_entity_type DamselUtil::mtod_entity_type[] = {
  DAMSEL_ENTITY_TYPE_VERTEX, // MBVERTEX
  DAMSEL_ENTITY_TYPE_EDGE, // MBEDGE
  DAMSEL_ENTITY_TYPE_TRI, // MBTRI
  DAMSEL_ENTITY_TYPE_QUAD, // MBQUAD
  DAMSEL_ENTITY_TYPE_POLYGON, // MBPOLYGON
  DAMSEL_ENTITY_TYPE_TET, // MBTET
  DAMSEL_ENTITY_TYPE_PYRAMID, // MBPYRAMID
  DAMSEL_ENTITY_TYPE_PRISM, // MBPRISM
  DAMSEL_ENTITY_TYPE_UNDEFINED, // MBKNIFE
  DAMSEL_ENTITY_TYPE_HEX, // MBHEX,
  DAMSEL_ENTITY_TYPE_POLYHEDRON, // MBPOLYHEDRON
  DAMSEL_ENTITY_TYPE_UNDEFINED // MBENTITYSET
};

EntityType DamselUtil::dtom_entity_type[] = {
  MBVERTEX, // MBVERTEX
  MBEDGE, // MBEDGE
  MBTRI, // MBTRI
  MBQUAD, // MBQUAD
  MBPOLYGON, // MBPOLYGON
  MBTET, // MBTET
  MBPRISM, // MBPRISM
  MBPYRAMID, // MBPYRAMID
  MBHEX, // MBHEX,
  MBPOLYHEDRON, // MBPOLYHEDRON
  MBMAXTYPE, // MBENTITYSET
  MBMAXTYPE // MBMAXTYPE
};

damsel_data_type DamselUtil::mtod_data_type[] = {
  DAMSEL_DATA_TYPE_BYTES, // MB_TYPE_OPAQUE
  DAMSEL_DATA_TYPE_INTEGER, // MB_TYPE_INTEGER
  DAMSEL_DATA_TYPE_DOUBLE, // MB_TYPE_DOUBLE
  DAMSEL_DATA_TYPE_INVALID, // MB_TYPE_BIT
  DAMSEL_DATA_TYPE_HANDLE // MB_TYPE_HANDLE
};

DataType DamselUtil::dtom_data_type[] = {
  MB_TYPE_OPAQUE, // DAMSEL_DATA_TYPE_INVALID = 0,
  MB_TYPE_OPAQUE, // DAMSEL_DATA_TYPE_BYTES = 1,
  MB_TYPE_INTEGER, // DAMSEL_DATA_TYPE_INTEGER = 2,
  MB_TYPE_OPAQUE, // DAMSEL_DATA_TYPE_INT64 = 3,
  MB_TYPE_OPAQUE, // DAMSEL_DATA_TYPE_FLOAT = 4,
  MB_TYPE_DOUBLE, // DAMSEL_DATA_TYPE_DOUBLE = 5,
  MB_TYPE_HANDLE, // DAMSEL_DATA_TYPE_HANDLE = 6,
  MB_TYPE_OPAQUE, // DAMSEL_DATA_TYPE_ID_T = 7,
  MB_TYPE_OPAQUE, // DAMSEL_DATA_TYPE_SHORTINT = 8,
  MB_TYPE_OPAQUE // DAMSEL_DATA_TYPE_PREDEFINED_WATERMARK = 9;
};

DamselUtil::DamselUtil()
  : dmslLib(DAMSEL_LIBRARY_INVALID), dmslModel(DAMSEL_MODEL_INVALID),
    moabHandleType(DAMSEL_HANDLE_TYPE_INVALID)
{}

//! Convert handles in a container to a range; assumes EntityHandle and Damsel
//! entity handles are the same size
ErrorCode DamselUtil::container_to_range(damsel_model m, damsel_container &c, Range &r)
{
  if (DMSLcontainer_get_type(c) == DAMSEL_HANDLE_CONTAINER_TYPE_SEQUENCE) {
    damsel_handle start;
    size_t count, stride;
    damsel_err_t err = DMSLcontainer_sequence_get_contents(m, c, &start, &count, &stride);CHK_DMSL_ERR_NM(err);
    for (damsel_handle i = start + (count - 1)*stride; i >= start; i-=stride)
      r.insert(i);
  }
  else if (DMSLcontainer_get_type(c) == DAMSEL_HANDLE_CONTAINER_TYPE_VECTOR) {
    damsel_handle *handle_ptr;
    size_t count;
    damsel_err_t err = DMSLcontainer_vector_get_contents(m, c, &handle_ptr, &count);CHK_DMSL_ERR_NM(err);
    for (int i = count-1; i >= 0; i--)
      r.insert(handle_ptr[i]);
  }
  else if (DMSLcontainer_get_type(c) == DAMSEL_HANDLE_CONTAINER_TYPE_TREE) {
    damsel_handle_ptr node_ptr = NULL;
    damsel_container cont = NULL;
    damsel_err_t err = DMSLcontainer_tree_get_contents(m, c, &node_ptr, &cont);
    while (err.id == DMSL_OK.id && cont) {
      ErrorCode rval = container_to_range(m, c, r);
      if (MB_SUCCESS != rval)
        return rval;
      err = DMSLcontainer_tree_get_contents(m, c, &node_ptr, &cont);
    }
  }

  return MB_SUCCESS;
}

}
