/// NiftiVolume.cpp
/**
*/

#include "NiftiVolume.h"

using namespace jcs;

///
/**
*/
void
NiftiHeader::InitHeader()
{ 
  memset(&hdr, 0, sizeof(hdr)); 
  memset(&extender, 0, sizeof(extender));
}


///
/**
*/
void
NiftiHeader::SetDimInfo(char freq_dim, char phase_dim, char slice_dim)
{
  hdr.dim_info = (freq_dim  & 0x03) | ((phase_dim & 0x03) << 2) | ((slice_dim & 0x03) << 4);
}


///
/**
 */
NiftiVolume::NiftiVolume(const char* filename, 
const char* header_extension,
const char* raw_extension) 
: BasicVolumeFormat(filename, header_extension, raw_extension), mByteOrder(aLITTLE_ENDIAN)
{
  mInitHeader();
}


///
/**
 */
NiftiVolume::~NiftiVolume()
{
}


///
/**
*/
void
NiftiVolume::WriteHeader(Basic3DHeader* header)
{ 
  NiftiHeader* nifti_header = dynamic_cast<NiftiHeader*>(header);
  mHeader = *nifti_header;
  if (mWriteHeaderFile() == 1) {
    if (verbose && !quiet) {
      std::cout << "Wrote " << mFileName.GetFullPath() << std::endl;
    }
  }
}


///
/**
*/
int
NiftiVolume::mWriteHeaderFile() 
{
  if (!mOpenHeaderFile(std::ios::out|std::ios::binary)) {
    wxLogError(_T("Cannot create header file %s"), mFileName.GetFullName().c_str());
    return 0;
  }

  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.sizeof_hdr), sizeof(mHeader.hdr.sizeof_hdr));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.data_type), sizeof(mHeader.hdr.data_type));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.db_name), sizeof(mHeader.hdr.db_name));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.extents), sizeof(mHeader.hdr.extents));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.session_error), sizeof(mHeader.hdr.session_error));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.regular), sizeof(mHeader.hdr.regular));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.dim_info), sizeof(mHeader.hdr.dim_info));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.dim), sizeof(mHeader.hdr.dim));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.intent_p1), sizeof(mHeader.hdr.intent_p1));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.intent_p2), sizeof(mHeader.hdr.intent_p2));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.intent_p3), sizeof(mHeader.hdr.intent_p3));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.intent_code), sizeof(mHeader.hdr.intent_code));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.datatype), sizeof(mHeader.hdr.datatype));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.bitpix), sizeof(mHeader.hdr.bitpix));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.slice_start), sizeof(mHeader.hdr.slice_start));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.pixdim), sizeof(mHeader.hdr.pixdim));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.vox_offset), sizeof(mHeader.hdr.vox_offset));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.scl_slope), sizeof(mHeader.hdr.scl_slope));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.scl_inter), sizeof(mHeader.hdr.scl_inter));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.slice_end), sizeof(mHeader.hdr.slice_end));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.slice_code), sizeof(mHeader.hdr.slice_code));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.xyzt_units), sizeof(mHeader.hdr.xyzt_units));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.cal_max), sizeof(mHeader.hdr.cal_max));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.cal_min), sizeof(mHeader.hdr.cal_min));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.slice_duration), sizeof(mHeader.hdr.slice_duration));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.toffset), sizeof(mHeader.hdr.toffset));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.glmax), sizeof(mHeader.hdr.glmax));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.glmin), sizeof(mHeader.hdr.glmin));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.descrip), sizeof(mHeader.hdr.descrip));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.aux_file), sizeof(mHeader.hdr.aux_file));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.qform_code), sizeof(mHeader.hdr.qform_code));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.sform_code), sizeof(mHeader.hdr.sform_code));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.quatern_b), sizeof(mHeader.hdr.quatern_b));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.quatern_c), sizeof(mHeader.hdr.quatern_c));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.quatern_d), sizeof(mHeader.hdr.quatern_d));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.qoffset_x), sizeof(mHeader.hdr.qoffset_x));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.qoffset_y), sizeof(mHeader.hdr.qoffset_y));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.qoffset_z), sizeof(mHeader.hdr.qoffset_z));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.srow_x), sizeof(mHeader.hdr.srow_x));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.srow_y), sizeof(mHeader.hdr.srow_y));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.srow_z), sizeof(mHeader.hdr.srow_z));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.intent_name), sizeof(mHeader.hdr.intent_name));
  mHeaderFile.write(reinterpret_cast <const char*> (&mHeader.hdr.magic), sizeof(mHeader.hdr.magic));

  // write extension if necessary
  if (strcmp(mHeader.hdr.magic,"n+1") == 0) {
    mHeaderFile.write(mHeader.extender.extension, sizeof(mHeader.extender.extension));
  }

  mCloseHeaderFile();

  return 1;
}
