#include "UnstructuredElemSeq.hpp"
#include "SequenceData.hpp"
#include "moab/CN.hpp"

namespace moab {

UnstructuredElemSeq::UnstructuredElemSeq( EntityHandle shandle, 
                                          EntityID entity_count, 
                                          unsigned nodes_per_entity,
                                          SequenceData* dat )
  : ElementSequence( shandle, entity_count, nodes_per_entity, dat )
  {}
  

UnstructuredElemSeq::UnstructuredElemSeq( EntityHandle shandle, 
                                          EntityID entity_count, 
                                          unsigned nodes_per_entity,
                                          EntityID data_size )
  : ElementSequence( shandle, entity_count, nodes_per_entity,
                      new SequenceData( 1, shandle, shandle + data_size - 1))
{
  data()->create_sequence_data( 0, nodes_per_entity * sizeof(EntityHandle) );
}


UnstructuredElemSeq::~UnstructuredElemSeq()
{}


int UnstructuredElemSeq::values_per_entity() const
  { return nodes_per_element(); }


EntitySequence*
UnstructuredElemSeq::split( EntityHandle here )
{
  if (here <= start_handle() || here > end_handle())
    return 0;
  
  return new UnstructuredElemSeq( *this, here );
}


SequenceData*
UnstructuredElemSeq::create_data_subset( EntityHandle start, EntityHandle end ) const
{
  int esize = nodes_per_element() * sizeof(EntityHandle);
  return data()->subset(start, end, &esize );
}


void
UnstructuredElemSeq::get_const_memory_use( unsigned long& bytes_per_entity,
                                           unsigned long& size_of_sequence ) const
{
  bytes_per_entity = nodes_per_element() * sizeof(EntityHandle);
  size_of_sequence = sizeof(this);
}

ErrorCode
UnstructuredElemSeq::get_connectivity( EntityHandle handle,
                                       std::vector<EntityHandle>& connect,
                                       bool topological ) const
{
  EntityHandle const* conn = get_array() + nodes_per_element() * (handle - start_handle());
  int len = topological ? CN::VerticesPerEntity(type()) : nodes_per_element();
  connect.reserve( connect.size() + len );
  std::copy( conn, conn+len, std::back_inserter( connect ) );
  return MB_SUCCESS;
}


ErrorCode
UnstructuredElemSeq::get_connectivity( EntityHandle handle,
                                       EntityHandle const*& conn_ptr,
                                       int& len,
                                       bool topological,
                                       std::vector<EntityHandle>* ) const
{
  conn_ptr = get_array() + nodes_per_element() * (handle - start_handle());
  len = topological ? CN::VerticesPerEntity(type()) : nodes_per_element();
  return MB_SUCCESS;
}


ErrorCode
UnstructuredElemSeq::set_connectivity( EntityHandle handle,
                                       EntityHandle const* connect,
                                       int connect_length )
{
  if ((unsigned)connect_length != nodes_per_element())
    return MB_INDEX_OUT_OF_RANGE;
  EntityHandle* conn_ptr = get_array() + nodes_per_element() * (handle - start_handle());
  std::copy( connect, connect+connect_length, conn_ptr );
  return MB_SUCCESS;
}


EntityHandle* UnstructuredElemSeq::get_connectivity_array()
  { return get_array(); }

ErrorCode UnstructuredElemSeq::push_back( EntityID count )
  { return EntitySequence::append_entities(count); }

ErrorCode UnstructuredElemSeq::push_front( EntityID count )
  { return EntitySequence::prepend_entities(count); }


} // namespace moab
