#pragma once
#include "McRxObject.h"
#include "McDbObjectId.h"
class McCmColor;

class McDbIdMapping;
class McDbObject;
class MxStringVariable;
class McDbCloneIdMapping;

// -------------------------------------------------------------------------
// Summary:
// 		这是个抽象类,提供对DWG信息格式进行I/O操作的接口，用于实现undo,对象拷贝等操作
// -------------------------------------------------------------------------
class ARXDLL McDbDwgFiler : public McRxObject  
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		申明类型信息
	// -------------------------------------------------------------------------
	MCDB_DECLARE_MEMBERS(McDbDwgFiler);

	McDbDwgFiler(McDb::FilerType filerType = McDb::kFileFiler,
		McDb::McDbMxEntityFileVersion version = McDb::kMEV_CURRENT, mxint16 iEntityVersion = 1);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回filer的实际类型
	// -------------------------------------------------------------------------
	virtual  McDb::FilerType   filerType() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回实体对象版式
	// -------------------------------------------------------------------------
	virtual  McDb::McDbMxEntityFileVersion getEntityFileVersion() const;

	virtual short							getEntityVersion() const;

	virtual Mcad::ErrorStatus   readInt(mxint32*) = 0;

	virtual Mcad::ErrorStatus   writeInt(mxint32) = 0;

	virtual Mcad::ErrorStatus   readObjectId( McDbObjectId& objId) = 0;

	virtual Mcad::ErrorStatus   writeObjectId( const McDbObjectId& objId) = 0;

	//
	virtual Mcad::ErrorStatus   readVector3d(McGeVector3d*) = 0 ;

	virtual Mcad::ErrorStatus   writeVector3d(const McGeVector3d&)  = 0;

	virtual Mcad::ErrorStatus   readVector2d(McGeVector2d*) = 0 ;

	virtual Mcad::ErrorStatus   writeVector2d(const McGeVector2d&)  = 0;

	virtual Mcad::ErrorStatus   readPoint3d(McGePoint3d*) = 0 ;

	virtual Mcad::ErrorStatus   writePoint3d(const McGePoint3d&)  = 0;

	virtual Mcad::ErrorStatus   read3dPoint3d(McGePoint3d*) = 0 ;

	virtual Mcad::ErrorStatus   write3dPoint3d(const McGePoint3d&)  = 0;

	virtual Mcad::ErrorStatus   readLong(long* pLong) = 0;


	virtual Mcad::ErrorStatus   writeLong(long lVal) = 0;


	virtual Mcad::ErrorStatus   readHardOwnershipId(McDbHardOwnershipId*) = 0 ;


	virtual Mcad::ErrorStatus   writeHardOwnershipId(
		const McDbHardOwnershipId&)  = 0;


	virtual Mcad::ErrorStatus   readSoftOwnershipId(McDbSoftOwnershipId*) = 0;


	virtual Mcad::ErrorStatus   writeSoftOwnershipId(
		const McDbSoftOwnershipId&)  = 0;


	virtual Mcad::ErrorStatus   readHardPointerId(McDbHardPointerId*) = 0 ;


	virtual Mcad::ErrorStatus   writeHardPointerId(const McDbHardPointerId&)  = 0;


	virtual Mcad::ErrorStatus   readSoftPointerId(McDbSoftPointerId*)  = 0;


	virtual Mcad::ErrorStatus   writeSoftPointerId(const McDbSoftPointerId&)  = 0;


	virtual Mcad::ErrorStatus   readColor( McCmColor& color) = 0;


	virtual Mcad::ErrorStatus   writeColor( const McCmColor& color) = 0;

	virtual Mcad::ErrorStatus   readDouble(mxdouble* pDouble) = 0;


	virtual Mcad::ErrorStatus   writeDouble(mxdouble dVal) = 0;

	virtual Mcad::ErrorStatus   readFloat(mxfloat* pDouble) = 0;


	virtual Mcad::ErrorStatus   writeFloat(mxfloat dVal) = 0;


	virtual Mcad::ErrorStatus   readReal(mxreal* pReal) = 0;


	inline Mcad::ErrorStatus readReal_p(mxreal_p* pRead) {
		mxreal dTmp = 0;
		Mcad::ErrorStatus ret = readReal(&dTmp);
		*pRead = (mxreal_p)dTmp;
		return ret;
	}

	inline Mcad::ErrorStatus writeReal_p(mxreal_p dVal) {
		return writeReal((mxreal)dVal);
	}


	inline Mcad::ErrorStatus readVector3d_p(McGeVector3dFloat* pRead) {
		McGeVector3d vec;
		Mcad::ErrorStatus ret = this->readVector3d(&vec);
		*pRead = McGeVector3dFloat(vec);
		return ret;
	}

	inline Mcad::ErrorStatus writeVector3d_p(const McGeVector3dFloat& val) {
		return this->writeVector3d(McGeVector3d(val));
	}


	virtual Mcad::ErrorStatus   writeReal(mxreal dVal) = 0;

	virtual Mcad::ErrorStatus   readString(MCHAR** ppszString) = 0 ;


	virtual Mcad::ErrorStatus   readString(LPCMSTR& pszSring)  = 0;


	virtual Mcad::ErrorStatus   writeString(const MCHAR* ppszString)  = 0;

	virtual Mcad::ErrorStatus   readString(MxString& str) = 0;


	virtual Mcad::ErrorStatus   readStringVar(MxStringVariable& str) = 0;

	virtual Mcad::ErrorStatus   writeStringVar(const MxStringVariable& str) = 0;

	virtual Mcad::ErrorStatus   writeString(const MxString& str) =0 ;

	virtual Mcad::ErrorStatus   readBigString(MxString& str);

	virtual Mcad::ErrorStatus   writeBigString(const MxString& str);


	virtual Mcad::ErrorStatus   readScale3d(McGeScale3d*) = 0 ;


	virtual Mcad::ErrorStatus   writeScale3d(const McGeScale3d&)  = 0;


	virtual Mcad::ErrorStatus   readPoint2d(McGePoint2d* point) = 0	;


	virtual Mcad::ErrorStatus   writePoint2d(const McGePoint2d& point)	 = 0;


	///
	virtual Mcad::ErrorStatus   readInt32(mxint32*) = 0;

	virtual Mcad::ErrorStatus   writeInt32(mxint32) = 0;

	virtual Mcad::ErrorStatus   readInt64(mxint64*) = 0;

	virtual Mcad::ErrorStatus   writeInt64(mxint64) = 0;

	virtual Mcad::ErrorStatus   readUInt64(mxuint64*) = 0;

	virtual Mcad::ErrorStatus   writeUInt64(mxuint64) = 0;



	virtual Mcad::ErrorStatus   readInt16(mxint16*) = 0;


	virtual Mcad::ErrorStatus   writeInt16(mxint16) = 0;


	virtual Mcad::ErrorStatus   readUInt32(mxuint32*) = 0;


	virtual Mcad::ErrorStatus   writeUInt32(mxuint32) = 0;


	virtual Mcad::ErrorStatus   readUInt16(mxuint16*) = 0;


	virtual Mcad::ErrorStatus   writeUInt16(mxuint16) = 0;


	virtual Mcad::ErrorStatus   readUInt8(mxuint8*) = 0;


	virtual Mcad::ErrorStatus   writeUInt8(mxuint8) = 0;

	virtual Mcad::ErrorStatus   readInt8(mxint8*) = 0;


	virtual Mcad::ErrorStatus   writeInt8(mxint8) = 0;


	virtual Mcad::ErrorStatus   readBoolean(mxbool*) = 0;



	virtual Mcad::ErrorStatus   writeBoolean(mxbool) = 0;


	virtual Mcad::ErrorStatus   readBool(mxbool*) = 0;

	virtual Mcad::ErrorStatus   writeBool(mxbool) = 0;

	virtual Mcad::ErrorStatus   readBChunk(mds_binary*) = 0;


	virtual Mcad::ErrorStatus   writeBChunk(const mds_binary&) = 0;

	virtual Mcad::ErrorStatus   writeXdata(const std::map<MxString,struct resbuf*>& mapXdata) = 0; 

	virtual Mcad::ErrorStatus   readXdata(std::map<MxString,struct resbuf*>& mapXdata) = 0;


	const McDbObject* getCurrentObject() const {
		return m_pCurrentObject;
	}

	void setCurrentObject(const McDbObject* pCurrentObject) {
		m_pCurrentObject = pCurrentObject;
	}

protected:
	McDb::FilerType m_filerType;

	McDb::McDbMxEntityFileVersion m_entityFileVersion;	// 系统实体的版式本。

	short            m_iEntityVersion;


	const McDbObject*     m_pCurrentObject;
};



class ARXDLL McDbDwgFilerImplement : public McDbDwgFiler
{
public:
	MCDB_DECLARE_MEMBERS(McDbDwgFilerImplement);

	McDbDwgFilerImplement(McDb::FilerType filerType,McDb::McDbMxEntityFileVersion version = McDb::kMEV_CURRENT);

	virtual ~McDbDwgFilerImplement();

	Mcad::ErrorStatus filerStatus() const;

	//设置使用数据
	void SetData(struct resbuf*& pData);

	struct resbuf* GetData();

	virtual  McDb::FilerType   filerType() const;

	// 释放对写数据控制权
	struct resbuf*  ReleaseData();

	// 读取一个链节数据,用局部Undo模块函数调用.
	struct resbuf* readResbuf();

	// 读写数据的定位
	Mcad::ErrorStatus seek(long offset, int method);

	// 返回数据数目
	long	tell() const;

	// 是否有数据
	bool IsHaveData() const;

	// 注意，当调用writeXXX函数后，将在函数内分配链表内存，所以必须记着
	// 调用getData函数取到链表数据，然后记着调用mcutRelRb释放链表

	Mcad::ErrorStatus   readVector3d(McGeVector3d*);
	Mcad::ErrorStatus   writeVector3d(const McGeVector3d&);

	Mcad::ErrorStatus   readVector2d(McGeVector2d*);
	Mcad::ErrorStatus   writeVector2d(const McGeVector2d&);


	Mcad::ErrorStatus   readPoint3d(McGePoint3d*);
	Mcad::ErrorStatus   writePoint3d(const McGePoint3d&);

	Mcad::ErrorStatus   read3dPoint3d(McGePoint3d*);

	Mcad::ErrorStatus   write3dPoint3d(const McGePoint3d&);

	Mcad::ErrorStatus   readInt(int*);
	Mcad::ErrorStatus   writeInt(int);

	Mcad::ErrorStatus   readLong(long* pLong);
	Mcad::ErrorStatus   writeLong(long lVal);

	Mcad::ErrorStatus   readObjectId(OUT McDbObjectId& objId);
	Mcad::ErrorStatus   writeObjectId(IN const McDbObjectId& objId);

	Mcad::ErrorStatus   readTempObject(void*& pObject);
	Mcad::ErrorStatus   writeTempObject(void*pObject);

	Mcad::ErrorStatus   readHardOwnershipId(McDbHardOwnershipId*);
	Mcad::ErrorStatus   writeHardOwnershipId(const McDbHardOwnershipId&);

	Mcad::ErrorStatus   readSoftOwnershipId(McDbSoftOwnershipId*);
	Mcad::ErrorStatus   writeSoftOwnershipId(const McDbSoftOwnershipId&);

	Mcad::ErrorStatus   readHardPointerId(McDbHardPointerId*);
	Mcad::ErrorStatus   writeHardPointerId(const McDbHardPointerId&);

	Mcad::ErrorStatus   readSoftPointerId(McDbSoftPointerId*);
	Mcad::ErrorStatus   writeSoftPointerId(const McDbSoftPointerId&);

	Mcad::ErrorStatus   readColor(OUT McCmColor& color);
	Mcad::ErrorStatus   writeColor(IN const McCmColor& color);

	Mcad::ErrorStatus   readDouble(double* pDouble);
	Mcad::ErrorStatus   writeDouble(double dVal);

	Mcad::ErrorStatus   readFloat(mxfloat* pDouble);
	Mcad::ErrorStatus   writeFloat(mxfloat dVal);


	Mcad::ErrorStatus   readReal(mxreal* pReal);
	Mcad::ErrorStatus   writeReal(mxreal dVal);

	Mcad::ErrorStatus   readString(MCHAR** ppszString);
	Mcad::ErrorStatus   readString(LPCMSTR& pszSring);

	Mcad::ErrorStatus   writeString(const MCHAR* pszString);

	Mcad::ErrorStatus   readString(MxString& str);

	Mcad::ErrorStatus   writeString(const MxString& str);


	Mcad::ErrorStatus   readStringVar(MxStringVariable& str);

	Mcad::ErrorStatus   writeStringVar(const MxStringVariable& str);


	Mcad::ErrorStatus   readScale3d(McGeScale3d*);
	Mcad::ErrorStatus   writeScale3d(const McGeScale3d&);

	Mcad::ErrorStatus   readPoint2d(McGePoint2d* point);
	Mcad::ErrorStatus   writePoint2d(const McGePoint2d& point);

	Mcad::ErrorStatus   writeXdata(const std::map<MxString,struct resbuf*>& mapXdata);
	Mcad::ErrorStatus   readXdata(std::map<MxString,struct resbuf*>& mapXdata);



	bool                getNextOwnedObject(McDbObjectId& id);

	bool                getNextDeepCloneObject(McDbObjectId& id);

	///
	Mcad::ErrorStatus   readInt32(mxint32*);
	Mcad::ErrorStatus   writeInt32(mxint32);

	Mcad::ErrorStatus   readInt64(mxint64*);
	Mcad::ErrorStatus   writeInt64(mxint64);

	Mcad::ErrorStatus   readUInt64(mxuint64*);
	Mcad::ErrorStatus   writeUInt64(mxuint64);



	Mcad::ErrorStatus   readInt16(mxint16*);
	Mcad::ErrorStatus   writeInt16(mxint16);

	Mcad::ErrorStatus   readUInt32(mxuint32*);
	Mcad::ErrorStatus   writeUInt32(mxuint32);

	Mcad::ErrorStatus   readUInt16(mxuint16*);
	Mcad::ErrorStatus   writeUInt16(mxuint16);

	Mcad::ErrorStatus   readUInt8(mxuint8*);
	Mcad::ErrorStatus   writeUInt8(mxuint8);

	Mcad::ErrorStatus   readInt8(mxint8*);
	Mcad::ErrorStatus   writeInt8(mxint8);


	Mcad::ErrorStatus   readBoolean(Mdesk::Boolean*);
	Mcad::ErrorStatus   writeBoolean(Mdesk::Boolean);

	Mcad::ErrorStatus   readBool(bool*);
	Mcad::ErrorStatus   writeBool(bool);


	Mcad::ErrorStatus   readBChunk(mds_binary*);

	Mcad::ErrorStatus   writeBChunk(const mds_binary&);
	///


	// 把链表数据中的Id替换成idMapping中与对应的新数据库中Id.
	// 该函数主要为了深度刻隆使用
	bool                replaceId(const McDbIdMapping& idMapping);

	// 用读取文件时，id替换.
	bool				replaceId(const McDbObjectIdArray& aryId);

	bool  replaceId(const McDbCloneIdMapping& idMapping);

	//
	void setEntityFileVersion(McDb::McDbMxEntityFileVersion version)
	{
		m_entityFileVersion = version;
	}


protected:
	void writeResbuf(struct resbuf* pVal);
	struct resbuf* readResbuf(int iType);

protected:
	struct resbuf m_data;					// 实体数据指针开始resbuf
	struct resbuf* m_pCurPos;				// 当前的操作位置,当前位置的下一个位置才是需要读取的位置
	struct resbuf* m_pCurOwnedObjectPos;	// 当前的拥有者对象Id.

};



// -------------------------------------------------------------------------
// Summary:
// 		读取一个变量，类型为Type,返回变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
#define DwgFilerReadItem(Type,Var,pFiler)	\
{	\
	mxuint16 iTmp = 0;	\
	pFiler->readUInt16(&iTmp);	\
	Var = (Type)iTmp;	\
}

// -------------------------------------------------------------------------
// Summary:
// 		写入一个变量，类型为Type,变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
#define DwgFilerWriteItem(Type,Var,pFiler)	\
	pFiler->writeUInt16((mxuint16)Var);


// -------------------------------------------------------------------------
// Summary:
// 		读取一个变量，类型为Type,返回变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
#define DwgFilerReadItem_Int16(Type,Var,pFiler)	\
{	\
	mxint16 iTmp = 0;	\
	pFiler->readInt16(&iTmp);	\
	Var = (Type)iTmp;	\
}

// -------------------------------------------------------------------------
// Summary:
// 		写入一个变量，类型为Type,变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
#define DwgFilerWriteItem_Int16(Type,Var,pFiler)	\
	pFiler->writeInt16((mxint16)Var);


// -------------------------------------------------------------------------
// Summary:
// 		读取一个bool变量，返回变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
/*
#define DwgFilerReadBoolItem(Var,pFiler)	\
{	\
	int iTmp = 0;	\
	pFiler->readInt(&iTmp);	\
	Var = (iTmp != 0);	\
}
*/

#define DwgFilerReadBoolItem(Var,pFiler)	\
{	\
	Var = false;	\
	pFiler->readBool(&Var);	\
}

// -------------------------------------------------------------------------
// Summary:
// 		写入一个bool变量,变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
/*
#define DwgFilerWriteBoolItem(Var,pFiler)	\
	pFiler->writeInt(Var ? 1 : 0);
	*/
#define DwgFilerWriteBoolItem(Var,pFiler)	\
	pFiler->writeBool(Var);


// -------------------------------------------------------------------------
// Summary:
// 		读取一个字符串变量，返回变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
#define DwgFilerReadStringItem(Var,pFiler)	\
{	\
	LPCMSTR pszVar = NULL;	\
	pFiler->readString(pszVar);	\
	if(pszVar != NULL)	\
		Var = pszVar;	\
}

// -------------------------------------------------------------------------
// Summary:
// 		写入一个字符串变量,变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
#define DwgFilerWriteStringItem(Var,pFiler)	\
{	\
	pFiler->writeString(Var);	\
}


// -------------------------------------------------------------------------
// Summary:
// 		写入一个3d矩阵变量,变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------

#define WirteMcGeMatrix3d(mat,pFiler)	\
	pFiler->writeDouble(mat(0,0) );	\
	pFiler->writeDouble(mat(0,1) );	\
	pFiler->writeDouble(mat(0,2) );	\
	pFiler->writeDouble(mat(0,3) );	\
	pFiler->writeDouble(mat(1,0) );	\
	pFiler->writeDouble(mat(1,1) );	\
	pFiler->writeDouble(mat(1,2) );	\
	pFiler->writeDouble(mat(1,3) );	\
	pFiler->writeDouble(mat(2,0) );	\
	pFiler->writeDouble(mat(2,1) );	\
	pFiler->writeDouble(mat(2,2) );	\
	pFiler->writeDouble(mat(2,3) );	\
	pFiler->writeDouble(mat(3,0) );	\
	pFiler->writeDouble(mat(3,1) );	\
	pFiler->writeDouble(mat(3,2) );	\
	pFiler->writeDouble(mat(3,3) );	\


// -------------------------------------------------------------------------
// Summary:
// 		读取一个3d矩阵变量，返回变量为Var,Filer对象为pFiler
// -------------------------------------------------------------------------
#define ReadMcGeMatrix3d(mat,pFiler)	\
	pFiler->readDouble(&mat.entry[0][0] );	\
	pFiler->readDouble(&mat.entry[0][1] );	\
	pFiler->readDouble(&mat.entry[0][2] );	\
	pFiler->readDouble(&mat.entry[0][3] );	\
	pFiler->readDouble(&mat.entry[1][0] );	\
	pFiler->readDouble(&mat.entry[1][1] );	\
	pFiler->readDouble(&mat.entry[1][2] );	\
	pFiler->readDouble(&mat.entry[1][3] );	\
	pFiler->readDouble(&mat.entry[2][0] );	\
	pFiler->readDouble(&mat.entry[2][1] );	\
	pFiler->readDouble(&mat.entry[2][2] );	\
	pFiler->readDouble(&mat.entry[2][3] );	\
	pFiler->readDouble(&mat.entry[3][0] );	\
	pFiler->readDouble(&mat.entry[3][1] );	\
	pFiler->readDouble(&mat.entry[3][2] );	\
	pFiler->readDouble(&mat.entry[3][3] );	\



#define DwgFilerWriteBaseClass(CLASS,BASS_CLASS)	\
Mcad::ErrorStatus es;	\
if ((es = BASS_CLASS::dwgOutFields(pFiler)) != Mcad::eOk)	\
{	\
	return es;	\
}	\
pFiler->writeInt8(CLASS##_VER);	\


#define DwgFilerReadBaseClass(CLASS,BASS_CLASS)	\
Mcad::ErrorStatus es;	\
if ((es = BASS_CLASS::dwgInFields(pFiler)) != Mcad::eOk)	\
{	\
	return es;	\
}	\
mxint8 iVer = 1;	\
pFiler->readInt8(&iVer);	\


// -------------------------------------------------------------------------
// Summary:
// 		深度克隆I/O操作的接口
// -------------------------------------------------------------------------
class  ARXDLL McDbDeepCloneFiler : public McDbDwgFilerImplement
{
	// -------------------------------------------------------------------------
	// Summary:
	// 		申明类型信息
	// -------------------------------------------------------------------------
	MCDB_DECLARE_MEMBERS(McDbDeepCloneFiler);
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McDbDeepCloneFiler();

	// -------------------------------------------------------------------------
	// Summary:
	// 		析构函数
	// -------------------------------------------------------------------------
	virtual ~McDbDeepCloneFiler();

};