/*------------------------------------------------------------------------------*
 * File Name: famosFile.h				 										*
 * Creation: Sim 2006-12-4														*
 * Purpose: Header file for famosFile.c											*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Hong 12/18/09 QA80-14858 FAMOS_NEED_TRIGGER_TIME							*
 *------------------------------------------------------------------------------*/

#ifndef _FAMOS_FILE_H
#define _FAMOS_FILE_H

#include <..\originlab\file_utils.h>

#define idTWOCC( ch0, ch1 )	( (WORD)(BYTE)(ch0) | ( (WORD)(BYTE)(ch1) << 8 ) )

#define ADD_BLOCK_IN_TREE(_StructName_, _TreeParent_, _TreeChild_, _strName_) \
	TreeNode _TreeChild_= _TreeParent_.AddNode(_strName_); \
	_TreeChild_ = _StructName_;	
	
typedef enum{
	FAMOS_NUMTYPE_UNKNOWN = 0, 
	FAMOS_NUMTYPE_UBYTE ,
	FAMOS_NUMTYPE_BYTE ,
	FAMOS_NUMTYPE_USHORT,
	FAMOS_NUMTYPE_SHORT ,
	FAMOS_NUMTYPE_ULONG,
	FAMOS_NUMTYPE_LONG,
	FAMOS_NUMTYPE_FLOAT,
	FAMOS_NUMTYPE_DOUBLE,
	FAMOS_NUMTYPE_IMCREC,
	FAMOS_NUMTYPE_TIMEASC,
	FAMOS_NUMTYPE_2BYTED,
	FAMOS_NUMTYPE_ULONG48 = 13,
}FAMOS_NUMTYPE;

typedef enum{
	FAMOS_FIELDTYPE_UNKNOWN = 0, 
	FAMOS_FIELDTYPE_NORMAL_WAVE ,
	FAMOS_FIELDTYPE_XYMONO ,
	FAMOS_FIELDTYPE_XYUNMONO,
	FAMOS_FIELDTYPE_CPLXRI,
	FAMOS_FIELDTYPE_CPLXMP,
	FAMOS_FIELDTYPE_CPLXDP
}FAMOS_FIELDTYPE;

typedef enum{
	_KEYREAD_ERR_ENDFILE = -2,
	_KEYREAD_ERR_ERR = -1,
	_KEYREAD_ERR_OK = 0,
}_KEYREAD_ERR;

#define  FAMOS_KEYID_UNKNOWN		0
#define	 FAMOS_KEYID_DF idTWOCC('D', 'F')  ///---Sim 01-15-2007 SUPPORT_DEMO_FILE
#define	 FAMOS_KEYID_CF idTWOCC('C', 'F')  
#define	 FAMOS_KEYID_CK idTWOCC('C', 'K')  
#define	 FAMOS_KEYID_NO idTWOCC('N', 'O') 
#define	 FAMOS_KEYID_CB idTWOCC('C', 'B') 
#define	 FAMOS_KEYID_CT idTWOCC('C', 'T')
#define	 FAMOS_KEYID_CG idTWOCC('C', 'G')
#define	 FAMOS_KEYID_CD idTWOCC('C', 'D')
#define	 FAMOS_KEYID_NT idTWOCC('N', 'T')
#define	 FAMOS_KEYID_CZ idTWOCC('C', 'Z')
#define	 FAMOS_KEYID_CC idTWOCC('C', 'C')
#define	 FAMOS_KEYID_CP idTWOCC('C', 'P')
#define	 FAMOS_KEYID_Cb idTWOCC('C', 'b')
#define	 FAMOS_KEYID_CR idTWOCC('C', 'R')
#define	 FAMOS_KEYID_ND idTWOCC('N', 'D')
#define	 FAMOS_KEYID_CN idTWOCC('C', 'N')
#define	 FAMOS_KEYID_CS idTWOCC('C', 'S')
#define	 FAMOS_KEYID_NU idTWOCC('N', 'U')
#define	 FAMOS_KEYID_CI idTWOCC('C', 'I')
/// Hong 07/08/10 ORG-499-P1 FIX_FAIL_IMPORT_SPECAIL_FAMOS_FILE_WITH_UNKOWN_KEY
#define	 FAMOS_KEYID_Cv idTWOCC('C', 'v')
#define	 FAMOS_KEYID_CV idTWOCC('C', 'V')
/// end FIX_FAIL_IMPORT_SPECAIL_FAMOS_FILE_WITH_UNKOWN_KEY

struct KeyHdr{
	WORD wID;
	int nVer;
	int nParaSize; //in Bytes
};

struct CFPara{
	int nProcessor;
};

struct CKPara{
	int nCKResv;
	int nFinished;
};

struct NOPara{
	int nOrigin;
	string strName;
	string strComment;
};

struct CBPara{
	int nIndex;
	string strName;
	string strComment;
};

struct CTPara
{
	int nGroup;
	string strName;
	string strValue;
	string strComment;
};

struct CGPara{
	int nNumComponents;
	int nFieldType;
	int nDimension;
};

struct CDPara{
	double dx;
	int nCalibrated;
	string strUnit;
	int nReduction;  //the below is not used in version 1
	int nIsMultiEvents;
	int nSortBUffer;
	double x0;
	int nPretriggerUse;
};

struct NTPara{
	int nDay;
	int nMonth;
	int nYear;
	int nHours;
	int nMinutes;
	double dSeconds;
};

struct CZPara{
	double dz;
	int ndzcali;
	double z0;
	int nz0cali;
	string strUnit;
	int nSegmentLengh;
};

struct CCPara{
	int nComIndx;
	int nAnalogDigital;
};

struct CPPara{
	int nBuffRef;
	int nBytes;
	int nNumberFormat;
	int nSignBits;
	short sMask;
	int nOffset;
	int nDirectSequenceNumber;
	int nIntervalByte;
};

struct CbPara{
	int nNumberBufferInKey;
	int nByteInUserInfo;
};

struct CbBuff{
	int nBufferRefence;
	int nIndexSamplesKey;
	int nOffsetBufferInSamplesKey;
	int nBufLength;
	int nOffsetFirstSampleInBuffer;
	int nBufferFilledBytes;
	int nReserve; //doc said always 0, but some data file not
	double x0;
	/// Hong 12/18/09 QA80-14858 FAMOS_NEED_TRIGGER_TIME
	//int nAddTime;
	double dAddTime;
	/// end FAMOS_NEED_TRIGGER_TIME
};

struct CRPara{
	int nTransformation;
	double dFactor;
	double dOffset;
	int nCalibrated;
	string strUnit;
};

struct NDPara{
	byte ColorR;
	byte ColorG;
	byte ColorB;
	double yMin;
	double yMax;
};
struct CNPara{
	int nIndxGroup;
	int nIndxBit;
	string strName;
	string strComment;
};

struct NUPara{
	int nIdenLen;
	string strKeyword;
	//vector<byte> vbData;
};

struct CIPara{
	int nBlockIndex;
	int nNumFormat;
	string strName;
	string strComment;
	string strUnit;
	double dTime;
};

struct CSPara{
	int nIndex;
	int nDataPos;
	int nDataSize;  //in byte
};

class BufferManager
{
public:
	bool GetBuffer(vector<char>& vcBuf, const vector<int> &vPos);
	void SetBuffer(const vector<char>& vcBuf, const vector<int> &vPos);
private:
	bool IsSameVector(const vector<int> &v1, const vector<int> &v2);
private:
	vector<char> m_vcBuf;
	vector<int> m_vPos; // (nOff1, nLen1, nOff2, nLen2, ... ) always a pair
};

class FamosFile: public BinFile
{
public:
	//FamosFile()
	//{
		//m_bReadFileInfo = false;
	//}
	
	FamosFile(LPCSTR lpcszFileName)
	:BinFile(lpcszFileName)
	{ 
		//m_bReadFileInfo = false;
		/// Sophy 5/04/2008 SHOW_WARNING_MESSAGE_WHEN_IMPORT_INVALID_DATA_FILE
		bHasImportedData = false;
		/// End SHOW_WARNING_MESSAGE_WHEN_IMPORT_INVALID_DATA_FILE
	}
	
public:
	int ReadInfo(TreeNode& trFileInfo);
	int Import(Layer& lyDest, TreeNode& trInfo, bool& bSampleInterval, int nC1 = 0);//, TreeNode& trFileInfo);
	/// Sophy 5/04/2008 SHOW_WARNING_MESSAGE_WHEN_IMPORT_INVALID_DATA_FILE
	bool HasImportedData();
	/// End SHOW_WARNING_MESSAGE_WHEN_IMPORT_INVALID_DATA_FILE
private:
	//search and read a key into a treenode from position pnFromPos and return the positon after this key
	//pnFromPos[Modify], for input, pnFromPos is the start postion to search, <0 means current postion; for output, return the postion after this key
	///---Sim 09-25-2007 SHOW_MSG_FOR_UNSUPPORTED_VERSION
	//int addNextKey(TreeNode& trParent, int* pnFromPos);  
	int addNextKey(TreeNode& trParent, TreeNode& trCurKey, int* pnFromPos);
	///---END SHOW_MSG_FOR_UNSUPPORTED_VERSION
	int readKeyHdr(KeyHdr& kyHdr, int* pParaPos, int nFromPos = -1);
	int readKeyPara(TreeNode& trKey, int pParaPos);

    int constructKeysInfo(TreeNode& trKeysArrange, const TreeNode& trKeysList);
	int getOrder(const TreeNode& trKey);
	TreeNode insertKey(TreeNode& trCurKey, const TreeNode& trInsKey);

	/// Hong 03/04/10 QA80-14858 FIX_SOME_DATASET_LOST_COVERED_BY_FOLLOWING_DATASET
    //int importDataFields(Layer& lyDest, TreeNode& trCG, int& nFirstCol);
    int importDataFields(Layer& lyDest, TreeNode& trCG, int& nFirstCol, int& nWksIndex);
    /// end FIX_SOME_DATASET_LOST_COVERED_BY_FOLLOWING_DATASET
    /// Hong 12/18/09 QA80-14858 FAMOS_NEED_TRIGGER_TIME
	//int importComponent(Column& col, TreeNode& trCC, TreeNode& trCNLast = NULL);
	int importComponent(Column& col, TreeNode& trCC, TreeNode& trCNLast = NULL, TreeNode& trNT = NULL);
	/// end FAMOS_NEED_TRIGGER_TIME
	/// Hong 12/18/09 QA80-14858 FAMOS_NEED_TRIGGER_TIME
	double	getTriggerTime(TreeNode& trNT, int nBuffRef);
	double	getAddTime(int nBuffRef);
	TreeNode	getBufInCb(int nBuffRef);
	/// end FAMOS_NEED_TRIGGER_TIME
	int importDataMatrix(MatrixLayer& ml, TreeNode& trCC, TreeNode& trCZ, TreeNode& trCD);
	
	int getBuffer(vector<char>& vc, int nBuffRef);
	void filtrateBuffer(vector<char>& vcBuf, int nSampleBytes, int nOffset, int nIntervalByte);
	void setSignificantBuffer(vector<char>& vcBuf, int nSampleBytes, int nSignBits, short sMask);

	void setSampleInterval(Worksheet& wks, int nC1, int nNumCols, const TreeNode& trCD, int nBuffRef);
	void setXColData(Column& colX, int nDataSize, const TreeNode& trCD, int nBuffRef);
	double getX0FromBufDesc(const TreeNode& trCD, int nBuffRef);
	double getX0FromBufDesc(int nBuffRef);
	
	string getComponentType(int nDataFieldType, int nComponentIndex);
	int getDataPosition(int nIndexSamplesKey);
	int setDataFormat(Column& col, int nNumberFormat, int nBytes);
	int setDataFormat(MatrixLayer& ml, int nNumberFormat, int nBytes);
	bool isXYDataField(int nDataFieldType);
	bool isComplexDataField(int nDataFieldType);
	
	void addSingleText(TreeNode& trSingleText, const TreeNode& trCT);
	void addSingleValue(TreeNode& trSingleValue, const TreeNode& trCI);

	// read key functions
	bool extractCFPara(vector<char>& vBuf, TreeNode& trCFPara);
	bool extractCKPara(vector<char>& vBuf, TreeNode& trCKPara);
	bool extractNOPara(vector<char>& vBuf, TreeNode& trNOPara);
	bool extractCBPara(vector<char>& vBuf, TreeNode& trCBPara);
	bool extractCTPara(vector<char>& vBuf, TreeNode& trCTPara);
	bool extractCGPara(vector<char>& vBuf, TreeNode& trCGPara);
	bool extractCDPara(vector<char>& vBuf, TreeNode& trCDPara);
	bool extractNTPara(vector<char>& vBuf, TreeNode& trNTPara);
	bool extractCZPara(vector<char>& vBuf, TreeNode& trCZPara);
	bool extractCCPara(vector<char>& vBuf, TreeNode& trCCPara);
	bool extractCPPara(vector<char>& vBuf, TreeNode& trCPPara);
	bool extractCbPara(vector<char>& vBuf, TreeNode& trCbPara);
	bool extractCRPara(vector<char>& vBuf, TreeNode& trCRPara);
	bool extractNDPara(vector<char>& vBuf, TreeNode& trNDPara);
	bool extractCNPara(vector<char>& vBuf, TreeNode& trCNPara);
	bool extractNUPara(vector<char>& vBuf, TreeNode& trNUPara);
	bool extractCIPara(vector<char>& vBuf, TreeNode& trCIPara);
	bool extractCSPara(int nParaPos, TreeNode& trCSPara);
	
	bool getValueFromBuf(TreeNode& trValue, vector<char>& vBuf, int nNumFormat, int* pnStart);
	
	int readStringUntilFindAChar(string& strDest, const string strCharContainer, char *pchFound = NULL);
	int seekToAfterChar(char cEndChar = '|', int iFromPos = -1);
private:
	Tree m_trFileInfo;
	//bool m_bReadFileInfo;
	BufferManager m_BufMag;
	
	bool m_bSampleInterval;
	/// Sophy 5/04/2008 SHOW_WARNING_MESSAGE_WHEN_IMPORT_INVALID_DATA_FILE
	bool	bHasImportedData;
	/// End SHOW_WARNING_MESSAGE_WHEN_IMPORT_INVALID_DATA_FILE
	WorksheetPage m_wp;
	MatrixPage m_mp;
};

int readIntFromBuf( vector<char>& vBuf, int* pnStart, char chSeprator = 'a');  //bug: can't set default chSeprator with ','
double readDoubleFromBuf(vector<char>& vBuf, int* pnStart, char chSeprator = 'a');
/*
read a string from the format: " ..., string length, string,...", such as "...,5,abcde,..", result is "abcde"
pnStart[modify], for input, the start position; for output, the start posion of next vaible, > bufferSize is permitted; 
*/
string readStringFromBuf(vector<char>& vBuf, int* pnStart);

#endif //_FAMOS_FILE_H
