#pragma once
#include "McDbObject.h"
#include "McDbObjectId.h"
#include "McDbHostApplicationServices.h"
#include "Mcedads.h"
#include "McRxObject.h"

#ifdef MX_BUILD_APP_FUCTION
	class McEdCommandStack;
#endif
class McApDocManager;

namespace Mx
{

	// -------------------------------------------------------------------------
	// Summary:
	// 		读或写方式打开对象，得到对象指针，就可以操作对象
	//		使用该函数打对象时，建议使用智能指针McDbObjectPointer打开对象更为方便
	// Parameters:
	// 		pObj	-	返回打开的对象指针
	//		id		-	对象id
	//		mode	-	打开方式，McDb::kForRead读方式打开，McDb::kForkForWrite写方式打开
	//		openErasedObject	-	对象被删除了后，是否也能成功打开
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// Remarks:
	// 		例如:写方式打开实体，并高亮显示实体
	// 		<code>
	// 				if(isHightLightEntity)
	// 				{
	// 					McDbObject* pObject = NULL;
	// 					Mcad::ErrorStatus es = Mx::mcdbOpenMcDbObject(pObject, id, McDb::kForWrite);
	// 					if (es == Mcad::eOk) 
	// 					{
	// 						ASSERT(pObject != NULL);
	// 						McDbEntity* pEnt = McDbEntity::cast(pObject);
	// 						if(pEnt != NULL)
	// 						{
	// 							pEnt->highlight();
	// 						}
	// 						pObject->close();
	// 					}
	// 				}
	// 		</code>
	// -------------------------------------------------------------------------
	ARXDLL Mcad::ErrorStatus 
		mcdbOpenMcDbObject(McDbObject*& pObj, McDbObjectId id, McDb::OpenMode mode,
		bool openErasedObject = false);

	

#ifdef MX_BUILD_APP_FUCTION
	ARXDLL McEdCommandStack* mcedRegCmds();
#endif

	ARXDLL McApDocManager* mcDocManager();
	// -------------------------------------------------------------------------
	// Summary:
	// 		读或写方式打开对象，得到对象指针，就可以操作对象。
	//		这是一个模板函数，可以打开任一类型的对象
	//		使用该函数打对象时，建议使用智能指针McDbObjectPointer打开对象更为方便
	// Parameters:
	// 		pObj	-	返回打开的对象指针
	//		id		-	对象id
	//		mode	-	打开方式，McDb::kForRead读方式打开，McDb::kForkForWrite写方式打开
	//		openErasedObject	-	对象被删除了后，是否也能成功打开
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	template<class T_OBJECT> inline Mcad::ErrorStatus
		mcdbOpenObject(
		T_OBJECT *& pObj, McDbObjectId id, McDb::OpenMode mode,
		bool openErased = false)
	{
		McDbObject* pObject;
		Mcad::ErrorStatus es = mcdbOpenMcDbObject(pObject, id, mode, openErased);
		if (es == Mcad::eOk) 
		{
			pObj = T_OBJECT::cast(pObject);
			if (pObj == NULL) 
			{
				es = Mcad::eNotThatKindOfClass;
				pObject->close();
				
				/*if (pObject->close() != Mcad::eOk)
					acrx_abort(_MXT("Failed McDbObject::close()"));
			    */
			}
		}
		return es;
	}


	// -------------------------------------------------------------------------
	// Summary:
	// 		由对象的id得到实体名
	// Parameters:
	// 		objName		-	输出实体名
	//		objId		-   输入对象的id
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// Remarks:
	// 		例如:
	// 		<code>
	// 				Mcad::ErrorStatus
	// 					MrxDbgUtils::objIdToEname(const McDbObjectId& objId, mds_name& ent)
	// 				{
	// 					Mcad::ErrorStatus es = Mx::mcdbGetAdsName(ent, objId);
	// 
	// 					return es;
	// 				}
	// 		</code>
	// -------------------------------------------------------------------------

	ARXDLL Mcad::ErrorStatus mcdbGetAdsName(mds_name&  objName, McDbObjectId objId);

	// -------------------------------------------------------------------------
	// Summary:
	// 		由实体名得到对象的id
	// Parameters:
	// 		objName		-	输入实体名
	//		objId		-   输出对象的id
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// Remarks:
	// 		例如:
	// 		<code>
	// 			ads_name entName;
	// 			ads_point pt;
	// 			if(acedEntSel(_T("需要偏移的PL线:"),entName,pt) != RTNORM)
	// 			{
	// 				return;
	// 			}
	// 
	// 			AcDbObjectId objId;
	// 			if(acdbGetObjectId(objId,entName) != Acad::eOk)
	// 				return;
	// 		</code>
	// -------------------------------------------------------------------------
	ARXDLL Mcad::ErrorStatus mcdbGetObjectId(McDbObjectId& objId,
		const mds_name objName);

	// -------------------------------------------------------------------------
	// Summary:
	// 		得当前的应用服务对象，这个应用服务对象是全局唯一的
	// Returns:
	// 		返回McDbHostApplicationServices的指针，这个指针不需要释放
	// Remarks:
	// 		例如:得到当前数据库
	// 		<code>
	// 			McDbDatabase* pDatabase = Mx::mcdbHostApplicationServices()->workingDatabase();
	// 		</code>
	// -------------------------------------------------------------------------
	ARXDLL McDbHostApplicationServices *mcdbHostApplicationServices();
};

class ARXDLL McDbExtents
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McDbExtents();  
	// -------------------------------------------------------------------------
	// Summary:
	// 		拷贝构造函数
	// -------------------------------------------------------------------------
	McDbExtents(const McDbExtents& src);  
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// Parameters:
	// 		min - 初始化的左下角点
	//		max - 初始化的右上角点
	// -------------------------------------------------------------------------
	McDbExtents(const McGePoint3d& min, const McGePoint3d& max);  

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回最小外包的左下角点
	// -------------------------------------------------------------------------
	McGePoint3d       minPoint() const { return mMinPoint; }
	// -------------------------------------------------------------------------
	// Summary:
	// 		返回最小外包的右上角点
	// -------------------------------------------------------------------------
	McGePoint3d       maxPoint() const { return mMaxPoint; }

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置最小外包的左下角点和最小外包的右上角点
	// Parameters:
	// 		min - 返回最小外包的左下角点
	// 		max - 最小外包的右上角点
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus set(const McGePoint3d& min, const McGePoint3d& max);

	


	// -------------------------------------------------------------------------
	// Summary:
	// 		向最小外包范围内增一个点坐标，并更新最小外包范围，保证传入的点在范围内
	// Parameters:
	// 		pt - 点坐标
	// -------------------------------------------------------------------------
	void              addPoint (const McGePoint3d& pt);
	

	// -------------------------------------------------------------------------
	// Summary:
	// 		向最小外包范围内增一个新范围，并更新最小外包范围，保证传入的新范围在范围内
	// Parameters:
	// 		src - 另一个最小外包对象
	// -------------------------------------------------------------------------
	void              addExt   (const McDbExtents& src);

	
private:
	McGePoint3d    mMinPoint;
	McGePoint3d    mMaxPoint;
};
