//------------------------------------------------------------
// $Id: volumeInfile.h,v 1.1.1.1 1999/11/25 06:26:10 yamauchi Exp $
//------------------------------------------------------------
//	(M\pi)^2 volume infile 
//	1997年11月19日(水)
//	Copyright (C) 1997--1998 YAMAUCHI Hitoshi 山内 斉
//
// volume infile には volume の定義空間内の位置 (global) や，grid 数，
// PNM ファイル数，PNM ファイル名などが含まれている． 
// 詳細は以下のファイルにある．
// 
//	../../../mpi2doc/mpi2.volumedata.doc
//	../../../mpi2doc/mpi2.volumedata.sample 
//------------------------------------------------------------
#ifndef _volumeInfile_h
#define _volumeInfile_h 1

#include "config.h"
#include "IntVec3.h"
#include "myString.h"
#include "mpi2exit.h"
#include "volumeGridInfo.h"
#include "GridColor.h"

//------------------------------------------------------------
// class for keeping volume infile data (データの保持)
//	file 内部での local なクラス
//------------------------------------------------------------
class volumeInfileInfoClass {
private:
    volumeInfileInfoClass(const volumeInfileInfoClass& rhs);
    const volumeInfileInfoClass& operator=(const volumeInfileInfoClass& rhs);

protected:
    GlobalGridInfoClass mGlobalGridInfo;

    int		mDataType;
    int  	mSlicedir;

    int 	mFileSeqStart;	// for(i  = this->mFileSeqStart; 
    int 	mFileSeqEnd;	//     i <= this->mFileSeqEnd; 
    int 	mFileSeqIncrement; //  i += this->mFileSeqIncrement)
    myString    mFilenameFormat; // printf format (ex. "volin%03g.svol", i)

protected:
    void init(void)
    {
	this->mGlobalGridInfo.init();
 	this->mDataType 	= -1;
 	this->mSlicedir 	= -1;

 	this->mFileSeqIncrement = 0;
	this->mFileSeqEnd	= 0;
	this->mFileSeqIncrement = 0; // illegal value
	this->mFilenameFormat 	= myString("");

	// this->mSeqCounter	= 0;
    }

public:
    volumeInfileInfoClass(void) 	{	this->init();		}
    volumeInfileInfoClass(int volumeID)
    {
	this->init();		
	this->mGlobalGridInfo.setID(volumeID);
    }
    ~volumeInfileInfoClass(void)
    {
    }
    void setGlobalGridInfo(const GlobalGridInfoClass &aGGI)
    {
	this->mGlobalGridInfo = aGGI;
	// ggi は仮の場合があるので，ここで this->calcVoxelEdgeLen が
	// できない．
    }
    GlobalGridInfoClass getGlobalGridInfo(void) const 
    {
	return(this->mGlobalGridInfo);
    }

    void setDataType(int type)
    {
	if((type != 0)) // type != {slice}
	{
	    cerr << "Error! : data type must be 0 (slice), but type = " 
		<< type << endl;
	    commMpi2_exit(1);
	}
	this->mDataType = type;
    }
    int getDataType(void) const	{ return(this->mDataType);	}

    void setSliceDir(int dir)
    {
	if((dir != 0) && (dir != 1) && (dir != 2)) // dir != {x|y|z}
	{
	    cerr << "Error! : dir must be 0,1,2 (x, y, z), but dir = " 
		<< dir << endl;
	    commMpi2_exit(1);
	}
	this->mSlicedir = dir;
    }
    int getSliceDir(void) const 	{ return(this->mSlicedir);	}

    // ファイル番号の並びについてのセット
    void setFileSequence(int start, int end, int increment) 	
    { 
	const char *emes = "Error! : volumeInfileInfoClass : ";
	if(increment == 0)
	{
	    cout << emes << "increment must be != 0." << endl;
	    exit(1);
	}
	else if(((increment > 0) && (start > end)) || 
		((increment < 0) && (start < end)))
	{
	    cout << emes << "illegal parameters [start, end; incr] = [" 
	    << start << ", " << end << "; " << increment << "]" << endl;
	    exit(1);
	}

	if(this->mFileSeqIncrement != 0)
	{
	    cout << "Warning! : volumeInfileInfoClass::setFileSequence called"
	    " more than 2 times." << endl;
	}
 	this->mFileSeqStart 	= start;
	this->mFileSeqEnd	= end;
	this->mFileSeqIncrement = increment;
    }
    // int  getNumberOfFiles(void) const { return(this->mNumberOfFiles);}
    void setFileNameFormat(myString filename)
    {
	// print format like "volimg%03g.svol"
	this->mFilenameFormat = filename;
    }
    myString getFileNameFormat(void) const
    {
	return(this->mFilenameFormat);
    }
    void calcVoxelEdgeLen(void)
    {
	this->mGlobalGridInfo.calcVoxelEdgeLen();
    }

    // get sequnece start number
    int getSeqStart(void) const {	return(this->mFileSeqStart);	}
    int getSeqEnd(void)   const {	return(this->mFileSeqEnd);	}
    int getSeqInc(void)   const {	return(this->mFileSeqIncrement);}

    const char* getFileName(int seqnum) const
    {
	int filenamenum = 
		this->mFileSeqStart + this->mFileSeqIncrement * seqnum;
	if((filenamenum < this->mFileSeqStart) || 
	   (filenamenum > this->mFileSeqEnd))
	{
	    cout << "Error! : volumeInfileInfoClass::getFileName : "
	    "illegal seqnum" << endl;
	    exit(1);
	}

	const int BSIZE = 256;
	static char buf[BSIZE];
#ifdef HAVE_SNPRINTF
 	snprintf(buf, BSIZE, (const char*)this->mFilenameFormat, filenamenum);
#else
 	sprintf(buf, (const char*)this->mFilenameFormat, filenamenum);
#endif
 	return(buf);
    }

    // get total number of files
    int getNumberOfFiles(void) const 
    {
	int filenum = 
	(this->mFileSeqEnd - this->mFileSeqStart) / this->mFileSeqIncrement;

	if((this->mFileSeqEnd - this->mFileSeqStart) % this->mFileSeqIncrement
	   == 0)
	{
	    filenum++;		// 割り切れれば端が入る
	}
	return(filenum);
    }


    // print out 
    void print(const char *pHead)
    {
	cout << pHead << "----- read VolumeInfileInfo" << endl;
	this->mGlobalGridInfo.print(pHead);

	cout << pHead << " datatype\t";
	switch(this->mDataType)
	{
	case 0:			// 今は 0 = slice のみサポート
	    cout << " slice";
	    break;
	default:
	    cerr << "Error! : no such datatype volumeInfileInfoClass::print()"
		<< endl;
	    commMpi2_exit(1);
	}
	cout << endl;
	cout << pHead; 
	if((0 <= this->mSlicedir) && (this->mSlicedir < 3))
	{
	    const char *pSliceDir[] = { "x", "y", "z", };
	    cout << " silicedir\t" << pSliceDir[this->mSlicedir] << endl;
	}else
	{
	    cerr << "Error! : illegal slicedir volumeInfileInfoClass::print()"
		<< endl;
	    commMpi2_exit(1);
	}

	cout << pHead << " sequence number : for(int i = "  << 
	this->mFileSeqStart << "; i <= " << this->mFileSeqEnd << 
	"; i+= " << this->mFileSeqIncrement << ")" << endl;
	cout << pHead << " filename format [" << this->mFilenameFormat << 
	"]" << endl;
	
	char buf[256];
	sprintf(buf, (const char*)this->mFilenameFormat, this->mFileSeqStart);
	cout << pHead << " start filename  [" << buf << "]" << endl;
	sprintf(buf, (const char*)this->mFilenameFormat, this->mFileSeqEnd);
	cout << pHead << " end   filename  [" << buf << "]" << endl;
    }
};

extern YorN readVolumeInfile(const char *pVolInfileName, 
			     volumeInfileInfoClass *pVolInfileInfo);

#endif				// #ifndef _volumeInfile_h 1
