/*
$Id: NeutronReadBinaryData.cc 1562 2006-06-08 10:27:20Z suzuki $
*/


#include "NeutronReadBinaryData.hh"

#ifndef  NEUTRONREADBINARYDATA_CC
#define  NEUTRONREADBINARYDATA_CC
//////////////////////////////////////////////////
template <class T>
NeutronReadBinaryData<T>::
NeutronReadBinaryData( std::string _SwapFlag  )
{
  if( _SwapFlag ==  "None" ){
    SwapFlag = 0;
  }

  if( _SwapFlag ==  "NoSwap" ){
    SwapFlag = 0;
  }

  else if( _SwapFlag ==  "Swap" ){
    SwapFlag = 1;
  }

  else if( _SwapFlag == "big" ){
    CollectArchitecture *ca = new CollectArchitecture();
    std::string endian = ca -> PutEndian();
    if( endian == "big" ){
      SwapFlag = 0;
    }
    else if( endian == "little" ){
      SwapFlag = 1;
    }
    delete ca;
  }

  else if( _SwapFlag == "little" ){
    CollectArchitecture *ca = new CollectArchitecture();
    std::string endian = ca -> PutEndian();
    if( endian == "little" ){
      SwapFlag = 0;
    }
    else if( endian == "big" ){
      SwapFlag = 1;
    }
    delete ca;
  }

  else{
    SwapFlag = 0;
  }

}
//////////////////////////////////////////////////
template <class T>
UInt8 NeutronReadBinaryData<T>::
ReadData( std::string FileName, T *&array )
{
  struct stat filestat;
  if( stat( FileName.c_str(), &filestat ) != 0 ){
    std::cout << "NeutronReadBinaryData::ReadData( Char, T ** )" << std::endl;
    std::cout << "The size of the target file cannot be obtained." << std::endl;
    std::cout << "Please check the existence of the data file." << std::endl;
    array = new T [ 1 ];
    array[0] = (T)0;
    return 0;
  }
  UInt8 FileSize = ( UInt8 )( filestat.st_size );
  if( FileSize % sizeof(T) != 0 ){
    std::cout << "NeutronReadBinaryData::ReadData( Char, T ** )" << std::endl;
    std::cout << "Your target file of " << FileName.c_str()
              << " may be broken. "
              << "Check its data type and file size !" << std::endl;
    array = new T [ 1 ];
    array[0] = (T)0;
    return 0;
  }

  if( FileSize == 0 ){
    std::cout << "NeutronReadBinaryData::ReadData( Char, T ** )" << std::endl;
    std::cout << "The size of " << FileName
              << " is zero." << std::endl;
    array = new T [ 1 ];
    array[0] = (T)0;
    return 0;
  }
  UInt8 Number = FileSize / sizeof( T );

  if( array != NULL ){
    delete [] array;
  }
  array = new T [ Number ];

  // Start reading the target file.
  FILE *fin;
  if( ( fin = fopen( FileName.c_str(), "r" ) ) == NULL )
    std::cout << "Can not open input file." << std::endl;
  else{
    size_t t = fread( array, sizeof(T), Number, fin );
    if (t!=Number)
      std::cout << "Can not read input file." << std::endl;
    fclose( fin );

    if( SwapFlag == 1 )
      {
        SwapBytes<T> *S = new SwapBytes<T>;
        S -> swap( array, Number );
        delete S;
      }
  }

  if( fin == NULL || Number == 1 ){
    array[0] = (T)0;
  }
  return Number;
}
//////////////////////////////////////////////////
template <class T>
std::vector< T > NeutronReadBinaryData<T>::
ReadData( std::string FileName )
{
  T* array = NULL;
  UInt8 size = ReadData( FileName, array );

  std::vector< T > v( size );

  for( UInt8 i=0; i<size; i++ ){
    v[i] = array[i];
  }
  delete array;
  return v;
}
//////////////////////////////////////////////////
template <class T>
std::vector< UInt4 > NeutronReadBinaryData<T>::
PutUInt4Vector( std::string FileName )
{
  T* array = NULL;
  UInt8 size = ReadData( FileName, array );

  std::vector< UInt4 > v( size );

  for( UInt8 i=0; i<size; i++ ){
    v[i] = ( UInt4 )array[i];
  }
  delete array;
  return v;
}
//////////////////////////////////////////////////
template <class T>
std::vector< Double > NeutronReadBinaryData<T>::
PutDoubleVector( std::string FileName )
{
  T* array = NULL;
  UInt8 size = ReadData( FileName, array );

  std::vector< Double > v( size );

  for( UInt8 i=0; i<size; i++ ){
    v[i] = ( Double )array[i];
  }
  delete array;
  return v;
}
//////////////////////////////////////////////////
template <class T>
PyObject* NeutronReadBinaryData<T>::
PutDoubleList( std::string FileName )
{
  CppToPython *converter = new CppToPython();
  PyObject *DoubleList =
    converter -> VectorToList( PutDoubleVector( FileName ) );
  delete converter;
  return DoubleList;
}
//////////////////////////////////////////////////
template <class T>
PyObject* NeutronReadBinaryData<T>::
PutUInt4List( std::string FileName )
{
  CppToPython *converter = new CppToPython();
  PyObject *UInt4List =
    converter -> VectorToList( PutUInt4Vector( FileName ) );
  delete converter;
  return UInt4List;
}
//////////////////////////////////////////////////
template <class T>
void NeutronReadBinaryData<T>::
PrintData( std::string FileName )
{
  std::vector<T> dat = ReadData( FileName );
  UInt4 size = dat.size();

  for( UInt4 i=0; i<size-1; i++ ){
    std::cout << dat[i] << ",";
  }
  std::cout << dat[size-1] << std::endl;
}
//////////////////////////////////////////////////

#endif
