#pragma once

#include "McDbEntity.h"
#include "McDbDatabase.h"
#include "Mdsdef.h"
#include "McDbObjectId.h"
#include "McDbObjectPointer.h"

class McDbDatabase;
class McDbRadialDimension;
class McDbDiametricDimension;
class ARXDLL MrxDbgUtils
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		实体的CAD颜色索引值
	// -------------------------------------------------------------------------
	enum Color
	{
		kByblock = 0,		//	随块
		kRed = 1,		//	红色
		kYellow = 2,		//	黄色
		kGreen = 3,		//	绿色
		kCyan = 4,		//	青色
		kBlue = 5,		//	蓝色
		kMagenta = 6,		//	洋红色
		kWhite = 7,		//	白色
		kBylayer = 256		//	随层
	};

	// -------------------------------------------------------------------------
	// Summary:
	// 	   判断实体所在图层是否被锁定
	// Parameters:
	// 		id - 实体的id.
	// Returns:
	// 		如果被锁定，返回true,否则返回false.
	// -------------------------------------------------------------------------
	static bool					isOnLockedLayer(McDbObjectId& id);

	// -------------------------------------------------------------------------
	// Summary:
	// 	   判断实体所在图层是否被锁定
	// Parameters:
	// 		pEnt - 指向实体对象
	// Returns:
	// 		如果被锁定，返回true,否则返回false.
	// -------------------------------------------------------------------------
	static bool					isOnLockedLayer(McDbEntity* pEnt);


	// ------------------------------------------------------------------------------------------------------------------------
	// Summary: 
	//		添加实体到当前模型空间。
	// Parameters:
	//		newEnt		- 新的实体。
	//		db			- 数据库指针。 
	// Returns: 
	//		如果成功返回Mcad::eOk
	// ------------------------------------------------------------------------------------------------------------------------
	static Mcad::ErrorStatus addToCurrentSpace(McDbEntity* newEnt, McDbDatabase* db);

	// ------------------------------------------------------------------------------------------------------------------------
	// Summary: 
	//		添加实体到当前数据库的当前空间中。
	// Parameters:
	//		newEnt		- 新的实体。
	// Returns: 
	//		如果成功返回Mcad::eOk
	// ------------------------------------------------------------------------------------------------------------------------
	static Mcad::ErrorStatus addToCurrentSpace(McDbEntity* newEnt);

	// ------------------------------------------------------------------------------------------------------------------------
	// Summary: 
	//		添加实体到当前模型空间,并关闭对象。
	// Parameters:
	//		newEnt		- 新的实体。
	//		db			- 数据库指针。 
	// Returns: 
	//		如果成功返回Mcad::eOk
	// ------------------------------------------------------------------------------------------------------------------------
	static Mcad::ErrorStatus addToCurrentSpaceAndClose(McDbEntity* newEnt, McDbDatabase* db);

	// ------------------------------------------------------------------------------------------------------------------------
	// Summary: 
	//		添加实体到当前数据库的当前空间中,并关闭对象
	// Parameters:
	//		newEnt		- 新的实体
	// Returns: 
	//		如果成功返回Mcad::eOk
	// ------------------------------------------------------------------------------------------------------------------------
	static Mcad::ErrorStatus addToCurrentSpaceAndClose(McDbEntity* newEnt);

	// -------------------------------------------------------------------------
	// Summary:
	// 		将用户坐标系点转化为世界坐标系点。
	// -------------------------------------------------------------------------
	static McGePoint3d      ucsToWcs(const McGePoint3d& pt, McDbDatabase* db = NULL);

	// -------------------------------------------------------------------------
	// Summary:
	// 		将一个三维点从世界坐标系到用户坐标系
	// -------------------------------------------------------------------------
	static McGePoint3d      wcsToUcs(const McGePoint3d& pt, McDbDatabase* db = NULL);

	// ------------------------------------------------------------------------------------------------------------------------
	// Summary: 
	//		将实体数据库id转化为实体名。
	// Parameters:
	//		objId		- 实体数据库id。
	//		ent			- 输出变量，实体名。
	// Returns: 
	//		如果成功返回Mcad::eOk
	// ------------------------------------------------------------------------------------------------------------------------
	static Mcad::ErrorStatus objIdToEname(const McDbObjectId& objId, mds_name& ent);

	// ------------------------------------------------------------------------------------------------------------------------
	// Summary: 
	//		将实体名转化为实体数据库id
	// Parameters:
	//		ent		- 实体名。
	//		objId		- 输出变量，实体数据库id。
	// Returns: 
	//		如果成功返回Mcad::eOk
	// ------------------------------------------------------------------------------------------------------------------------
	static Mcad::ErrorStatus enameToObjId(mds_name ent, McDbObjectId& objId);

	// -------------------------------------------------------------------------
	// Summary:
	// 		向数据库增加一个图象定义.
	// Parameters:
	// 		sImageFile	-	图象文件名
	//		pszName		-	名称,如果为空，就取sImageFile的文件名
	//		pDatabase	-	数据库指针，如果为空，取当前数据库。
	// Returns:
	// 		返回新增加的McDbRasterImageDef对象id,如果已经有pszName名称的图象定义，就直接返回.
	// -------------------------------------------------------------------------
	static McDbObjectId addImageDefine(MxString sImageFile,
		LPCMSTR pszName = NULL,
		McDbDatabase* pDatabase = NULL);

	static McDbObjectId getImageDict(McDbDatabase* pDatabase, bool isNotExistCreate = false);

	// -------------------------------------------------------------------------
	// Summary:
	// 		在一定的精度范围内查找一个点处的实体
	// Parameters:
	// 		pt		-	搜索点,WCS坐标系统
	//		pFilter	-	过滤条件
	//		dTol		-   搜索范围,文档坐标
	// Returns:
	// 		返回最近实体的id,如果没有找到，就返回McDbObject::kNull
	// -------------------------------------------------------------------------
	static McDbObjectId findEntAtPoint(IN McGePoint3d pt,
		IN struct resbuf* pFilter = nullptr,
		IN mxreal dTol = -1.0, IN bool isFilterLockLayer = false);

	// -------------------------------------------------------------------------
	// Summary:
	// 		得到系统变量.支持int,double,LPCMSTR,McGePoint3d,McGePoint2d类型变量
	// Parameters:
	// 		varName - 变量名.
	// Returns:
	// 		成功返回Mcad::eOk;
	// -------------------------------------------------------------------------
	static Mcad::ErrorStatus    getSysVar(LPCMSTR varName, long& val, McDbDatabase* pDatabase = NULL);

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置系统变量.支持int,double,LPCMSTR,McGePoint3d,McGePoint2d类型变量
	// Parameters:
	// 		varName - 变量名.
	// Remarks:	
	// 		例如:   禁用动态输入功能，在创建控件窗口后调用.
	// 		<code>
	// 			MrxDbgUtils::setSysVar(_T("DYNINPUT"),0)
	// 		</code>
	// 		例如: 禁用动态追踪的代码:
	// 		<code>
	// 		     MrxDbgUtils::setSysVar(_T("DYNTRACE"),0);
	// 		</code>
	// 		例如: 设置当前线重
	// 		<code>
	// 				long lWdith = McDb::kLnWt015;
	// 				MrxDbgUtils::setSysVar(_T("CELWEIGHT"),lWdith);
	// 		</code>
	// Returns:
	// 		成功返回Mcad::eOk;
	// -------------------------------------------------------------------------
	static Mcad::ErrorStatus    setSysVar(LPCMSTR varName, long val, McDbDatabase* pDatabase = NULL);

	// -------------------------------------------------------------------------
	// Summary:
	// 		绘制Image对象
	// Parameters:
	// 		pszFileName - Image文件路径.
	// 		pt - 插入点的左下角.
	// 		dScale - 缩放比例
	// 		dAngle - 图片的旋转角度
	// Returns:
	// 		成功返回Mcad::eOk;
	// -------------------------------------------------------------------------
	static McDbObjectId         drawImage(LPCMSTR pszFileName, McGePoint3d pt, mxreal dScale, mxreal dAngle);


	static McDbObjectId         drawImage(LPCMSTR pszFileName, McGePoint3d pt1, McGePoint3d pt2, mxreal dAngle);
	//:Ignore


	static Mcad::ErrorStatus    getSysVar(LPCMSTR varName, mxreal& val, McDbDatabase* pDatabase = NULL);
	static Mcad::ErrorStatus    getSysVar(LPCMSTR varName, MxString& val, McDbDatabase* pDatabase = NULL);
	static Mcad::ErrorStatus    getSysVar(LPCMSTR varName, McGePoint3d& val, McDbDatabase* pDatabase = NULL);
	static Mcad::ErrorStatus    getSysVar(LPCMSTR varName, McGePoint2d& val, McDbDatabase* pDatabase = NULL);


	static Mcad::ErrorStatus    setSysVar(LPCMSTR varName, mxreal val, McDbDatabase* pDatabase = NULL);
	static Mcad::ErrorStatus    setSysVar(LPCMSTR varName, LPCMSTR val, McDbDatabase* pDatabase = NULL);
	static Mcad::ErrorStatus    setSysVar(LPCMSTR varName, const McGePoint3d& val, McDbDatabase* pDatabase = NULL);
	static Mcad::ErrorStatus    setSysVar(LPCMSTR varName, const McGePoint2d& val, McDbDatabase* pDatabase = NULL);

	static Mcad::ErrorStatus    setSysVar(LPCMSTR varName, int val, McDbDatabase* pDatabase = NULL);


	//:End Ignore

	// -------------------------------------------------------------------------
	// Summary:
	// 		得到符号表记录名称
	// Parameters:
	// 		recId - 符号表记录id
	// Returns:
	// 		失败返回空字符串
	// -------------------------------------------------------------------------
	static MxString getSymbolTableRecordName(McDbObjectId recId, bool isRetAnonymity = true);


	// -------------------------------------------------------------------------
	// Summary:
	// 		得到记录Id
	// Parameters:
	// 		sName		-	记录名称
	//		pDatabase	-	数据库指针，如果为，取当前数据库。
	// Returns:
	// 		失败返回空ID
	// -------------------------------------------------------------------------
	template<class T_OBJECT> static McDbObjectId
		getSymbolTableRecordId(
			MxString sName,
			McDbDatabase* pDatabase = NULL, bool openErased = false)
	{
		if (pDatabase == NULL)
			pDatabase = Mx::mcdbCurDwg();

		if (pDatabase == NULL)
		{
			MXASSERT(0);
			return McDbObjectId::kNull;
		}

		McDbSymbolTableRecordPointer<T_OBJECT> spRecord(sName, pDatabase, McDb::kForRead, openErased);
		if (spRecord.openStatus() != Mcad::eOk)
			return McDbObjectId::kNull;

		return spRecord->objectId();
	}

	static McDbObjectId addLayer(const MxString& sLayer,
		McDbObjectId lineType = McDbObjectId::kNull,
		McCmColor* pCorlor = NULL,
		McDbDatabase* pDatabase = NULL);


	// -------------------------------------------------------------------------
	// Summary:
	// 		向数据库增加一个块表记录，如果指定的块表记录名已经在数据库中，就直接返回它的id
	// Parameters:
	// 		sDwgFileName	-		DWG文件路径
	//		pszBlkName		-		块名,如果为空，就取sDwgFileName的文件名
	//		pDatabase		-		数据库指针，如果为空，取当前数据库。
	//		wszPassword		-		读取DWG文件时的密码,默认为密码为空
	//		rc				-		读取DWG文件时的读取内容,默认读取所有内容
	// Returns:
	// 		返回新增加的块表记录id,失败返回空的id
	// -------------------------------------------------------------------------
	static McDbObjectId addBlockRecord(MxString sDwgFileName, LPCMSTR pszBlkName = NULL,
		McDbDatabase* pDatabase = NULL,
		LPCMSTR wszPassword = NULL,
		int rc = Mcad::kReadDefault);


	static Mcad::ErrorStatus handleStrToObjId(McDbDatabase* db,
		LPCMSTR handleStr,
		McDbObjectId& objId);

	static Mcad::ErrorStatus handleToObjId(McDbDatabase* db,
		const McDbHandle& handle,
		McDbObjectId& objId);

	static MxIdIndex handleToIdIndex(McDbDatabase* db,
		const McDbHandle& handle);

	static McDbHandle objIdToHandle(const McDbObjectId& objId);


	static McDbObjectId IdIndexToObjId(MxIdIndex idIndex);

	static MxIdIndex     objIdToIdIndex(const McDbObjectId& objId);

	static mxuint32     objIdToIdIndex32(const McDbObjectId& objId);

	static McDbDatabase* getObjectDatabase(const McDbObjectId& objId);

	static McDbDatabase* getObjectDatabase(MxIdIndex idIndex);

	static bool  GetAllLayoutName(McDbDatabase* pDatabase,
		std::vector<MxString>& vecLayoutName, bool isRetModle = true);

	static bool				objIdToHandleStr(const McDbObjectId& objId, MxString& str);

	static bool				objToHandleStr(const McDbObject* obj, MxString& str);

	static bool    getTextBox(LPCMSTR pszText, double dTextHeight, double dWidthFactor, McDbObjectId textStyleId, McDbExtents& extents);

	static bool    getTextEntityBox(McDbEntity* pEntity, bool isTrimLastSpace, McDbExtents& extents);

	static McDbObjectId getLayoutId(McDbDatabase* pDatabase, LPCTSTR pszName);

#ifdef MX_BUILD_APP_FUCTION
	// -------------------------------------------------------------------------
	// Summary:
	// 		带过滤条件单选择实体
	// Parameters:
	// 		strPrompt				-	选择时命令行提示
	//		pRbFilter				-	过滤条件
	//		objId					-   返回选择的实体id
	//		ptPick					-   返回选择实体时，点取点坐标,返回的是WCS坐标。
	//		isFilterLockedLayers	-	是否过滤在锁定图层上的实体,默认值为不过滤
	//		pSubEntitys				-	查到的块里面的实体
	// Returns:
	// 		返回RTERROR 没有选择到需要的实体
	//			RTNORM  成功返回
	//			RTNONE  空回车
	// -------------------------------------------------------------------------
	static int selectEnt(IN     const MxString&		strPrompt,
		OUT McDbObjectId& objId,
		OUT McGePoint3d&  ptPick,
		IN  struct resbuf* pRbFilter = 0,
		IN  bool isFilterLockedLayers = false,
		IN bool isOffsetInputPostion = false

	);
#endif

	static bool calculationRadialDimension(McDbRadialDimension* pDim, McDbEntity* pEnt, McGePoint3d ptPick);
	static bool calculationDiametricDimension(McDbDiametricDimension* pDim, McDbEntity* pEnt, McGePoint3d ptPick);

	static McDbObjectId cloneBlockRecord(McDbObjectId blkRecordId,LPCMSTR pszBlkName = 0);
protected:

	//:Ignore
	static Mcad::ErrorStatus setVar(LPCMSTR varName, const resbuf* newVal, McDbDatabase* pDatabase);

	static bool getNearestDistance(McDbObjectId id, McGePoint3d ptPick, mxreal& dDist);
	MrxDbgUtils() {};
	//:End Ignore

};

