#include "pch.h"
#include "MxHead.h"
#include "MxWriteOpt.h"
#include "MxOptLayerTable.h"
#include "DxfLib\dl_codes.h"
#include "DxfLib\dl_dxf.h"
#include "DxfLib\dl_writer_ascii.h"
#include "Tool.h"
#include "MxWriteContext.h"
#include "MxOptLineTypeTable.h"
#include "MxDxfData.h"
#include "MxOptBlockTable.h"

MxWriteOpt::MxWriteOpt(void)
{
}

MxWriteOpt::~MxWriteOpt(void)
{
}

bool MxWriteOpt::Do(McDbDatabase* pSrcDatabase,
		LPCTSTR pszFileName
		)
{
	MxString sFilePath(pszFileName);
	if(sFilePath.IsEmpty() )
	{
		m_sError.Format(_T("文件路径为空"));
		return false;
	}

	ASSERT(pSrcDatabase != NULL);

	MxDocArx* pDoc = NULL;
	if(pSrcDatabase->GetDocument() != NULL)
		pDoc = pSrcDatabase->GetDocument()->Doc();
	///..



	// set version for DXF filter:
	DL_Codes::version exportVersion  = DL_Codes::AC1015;

	DL_Dxf* pDxf = new DL_Dxf;
	if(pDxf == NULL)
	{
		mx_console_log(_T("memory faild"));
		return false;
	}
	std::auto_ptr<DL_Dxf> spDxf(pDxf);

	//MxStringA sFileNameA(MXDXF_W2A(pszFileName));
	
	//DL_WriterA* dw = pDxf->out((const char*)(sFileNameA), exportVersion);
	DL_WriterA* dw = pDxf->out(pszFileName, exportVersion);
	if (dw == NULL) 
	{
		return false;
	}

	MxWriteContext  writeContext(pSrcDatabase,pDxf);

	// Header
	
	pDxf->writeHeader(*dw);

	// Variables
	WriteVariables(&writeContext,dw);

	// Section TABLES
	dw->sectionTables();

	// VPORT:
	pDxf->writeVPort(*dw);

	// Line types:
	{
		MxOptLineTypeTable lineTypeTable(&writeContext);
		lineTypeTable.Mx2Dxf(dw);
	}

	// Layers:	
	{
		MxOptLayerTable layerTable(&writeContext);
		layerTable.Mx2Dxf(dw);
	}

	// Text STYLE:
	pDxf->writeStyle(*dw);

	//
	// VIEW:

	pDxf->writeView(*dw);

	// UCS:
	pDxf->writeUcs(*dw);

	// AppName:
	dw->tableAppid(1);
	pDxf->writeAppid(*dw, "ACAD");
	dw->tableEnd();

	// DIMSTYLE:
	pDxf->writeDimStyle(*dw,2.5,1.25,0.625,0.625,2.5);

	// BLOCK_RECORD:

	pDxf->writeBlockRecord(*dw);

	while(true)
	{
		McDbBlockTablePointer  spBlkTable(pSrcDatabase,McDb::kForRead);
		if(spBlkTable.openStatus() != Mcad::eOk)
		{
			break;
		}

		McDbBlockTableIterator* pIterator = NULL;
		spBlkTable->newIterator(pIterator);
		if(pIterator == NULL)
			break;

		for(;!pIterator->done();pIterator->step() )
		{
			McDbObjectId recId;
			pIterator->getRecordId(recId);
			McDbObjectPointer<McDbBlockTableRecord> spBlkRec(recId,McDb::kForRead);
			if(spBlkRec.openStatus() != Mcad::eOk)
				continue;

			MxString sName;
			spBlkRec->getName(sName);

			if(sName.CompareNoCase(_T("*Model_Space")) == 0
				|| sName.CompareNoCase(_T("*Paper_Space")) == 0
				|| sName.CompareNoCase(_T("*Paper_Space0")) == 0
				)
			{
				// 这些块名，是系统中缺省的，已经在前面的
				// pDxf->writeBlockRecord(*dw); 写入。 
				continue;

			}

			std::string sNameA = MXDXF_W2A(sName);

			pDxf->writeBlockRecord(*dw,sNameA);
		}

		delete pIterator;
		break;
	}
	dw->tableEnd();

	// end of tables:
	dw->sectionEnd();
	

	MxOptBlockTable blockTable(&writeContext);
	blockTable.Mx2Dxf(dw);



	// Section ENTITIES:
	dw->sectionEntities();

	// ...
	blockTable.WriteBlockEntity(MCDB_MODEL_SPACE,dw);

	dw->sectionEnd();




	// Section Objects:
	pDxf->writeObjects(*dw);

	// ...
	pDxf->writeObjectsEnd(*dw);




	dw->dxfEOF();

	dw->close();

	delete dw;

	return true;
}


bool MxWriteOpt::WriteVariables(MxWriteContext* pWriteContext,
					DL_WriterA* dw
					)
{
	MxStringArray aryName;
	IMxDxf::GetAllSysVarName(aryName,pWriteContext->GetDatabase() );

	for(size_t i = 0; i < aryName.size();i++)
	{
		MxString sName = aryName[i];
		if (sName =="ACADVER" 
			|| sName == "HANDSEED"
			)
		{
			continue;
		}

		MrxDbgRbList spVal  = Mx::mcutNewRb(RTSHORT);
		struct resbuf* pVal = spVal.data();

		if(IMxDxf::GetSysVar(sName,pVal,pWriteContext->GetDatabase()) != RTNORM)
		{
			continue;
		}

		int iCode = 0;
		if(!MxDxfData::Instance().GetSysVarCode(sName,iCode) )
		{
			continue;
		}

		// 写变量值。
		int iType =   IMxDxf::DXFToType(pVal->restype);

		sName = _T("$") + aryName[i];
		string sKeyName = MXDXF_W2A(sName);

		//RTSTR,RTLONG,RT3DPOINT,RTPOINT,
		if(iType == RTREAL)
		{
			// 写一个RTREAL变量。
			dw->dxfString(9, sKeyName);
			dw->dxfReal(iCode, pVal->resval.rreal);
		}
		else if(iType == RTLONG)
		{
			dw->dxfString(9, sKeyName);
			dw->dxfInt(iCode, pVal->resval.rlong);
		}
		else if(iType == RTSHORT)
		{
			dw->dxfString(9, sKeyName);
			dw->dxfInt(iCode, pVal->resval.rint);
		}
		else if(iType == RTSTR)
		{
			dw->dxfString(9, sKeyName);

			string sVal = MXDXF_W2A(pVal->resval.rstring);
			dw->dxfString(iCode,sVal);
		}
		else if(iType == RT3DPOINT
			|| iType == RTPOINT
			)
		{
			dw->dxfString(9, sKeyName);

			dw->dxfReal(iCode,
				pVal->resval.rpoint[0]);

			dw->dxfReal(iCode + 10,
				pVal->resval.rpoint[1]);

			if (!(sKeyName	==	"$LIMMIN" ||
				sKeyName	==	"$LIMMAX" ||
				sKeyName	==	"$PLIMMIN" ||
				sKeyName	==	"$PLIMMAX" ||
				sKeyName	==	"$GRIDUNIT" ||
				sKeyName	==	"$VIEWCTR")
				) 
			{
				dw->dxfReal(iCode + 20,
					pVal->resval.rpoint[2]);
			} 
		}
	}

	dw->sectionEnd();
	return true;
}