#pragma once
#include "McDbObject.h"
#include "Dbmain.h"
#include "McDbDatabase.h"
#include "McDbFullSubentPath.h"

class McDbEntityImp;
class McGiWorldDraw;
// -------------------------------------------------------------------------
// Summary:
// 		具有一个图形表示的所有数据库对象的基类，包括了显示实体的通用属性操作，如线型，图层，文字样式，颜色，几何外包等
// -------------------------------------------------------------------------
class ARXDLL McDbEntity : public McDbObject
{
protected:

	McDbEntity(McDbEntityImp* pImp);
public:
	

	// -------------------------------------------------------------------------
	// Summary:
	// 		申明类型信息
	// -------------------------------------------------------------------------
	MCDB_DECLARE_MEMBERS(McDbEntity);

	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McDbEntity();


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


	Mcad::ErrorStatus deepClone(
		McDbObject*& pClonedObject,
		McDbCloneIdMapping& idMap
	)  const override;

	// -------------------------------------------------------------------------
	// Summary:
	// 		把实体删除掉，并清除内存,该函数现在只能清除McDbEntity继承的实体
	//		如果启用了undo功能，就不能直接把对象内存释放了，这时该函数调用将失效.
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus  clear();

	// -------------------------------------------------------------------------
	// Summary:
	// 		虚函数，自定义实体重载该函数，返回夹点信息
	// Parameters:
	//		gripPoints    - 	返回的夹点数组
	//		osnapModes    -		暂没有使用
	//		geomIds       -		暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   getGripPoints(
                  McGePoint3dArray&  gripPoints,
				   McGeIntArray&  osnapModes,
				   McGeIntArray&  geomIds) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		虚函数，自定义实体重载该函数，处理夹点被移动事件
	// Parameters:
	// 		indices     	-		夹点的索引位置
	//		offset          -		移动方向向量
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// Remarks:
	// 		例如:sample\CustomEntity\CustomEntity.sln例程
	// 		<code>
	// 			Acad::ErrorStatus CLinkLine::moveGripPointsAt(const AcGeIntArray& indices,
	// 				const AcGeVector3d& offset)
	// 			{
	// 				assertWriteEnabled();
	// 				int iIndex = indices[0];
	// 				switch(iIndex)
	// 				{
	// 				case 0:
	// 					m_start = m_start + offset;
	// 					break;
	// 				case 1:
	// 					m_end = m_end + offset;
	// 					break;
	// 				case 2:
	// 					m_start = m_start + offset;
	// 					m_end = m_end + offset;
	// 					break;
	// 				}
	// 				return Mcad::eOk;
	// 			}
	// 		</code>
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus moveGripPointsAt(const McGeIntArray& indices,
											const McGeVector3d& offset);



	// -------------------------------------------------------------------------
	// Summary:
	// 		返回实体的最小外包矩形框
	// Parameters:
	// 		extents - 最小外包矩形框
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   getGeomExtents(McDbExtents& extents, bool roughCalculation = true) const;
		

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回颜色值
	// -------------------------------------------------------------------------
	McCmColor                   color() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置颜色值
	// Parameters:
	// 		color		-	颜色值
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   setColor(const McCmColor& color,
		Mdesk::Boolean doSubents = true);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回CAD的颜色索引值
	// -------------------------------------------------------------------------
	Mdesk::UInt16               colorIndex() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置CAD的颜色索引值
	// Parameters:
	// 		color		-	CAD的颜色索引值
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   setColorIndex(Mdesk::UInt16 color,
		Mdesk::Boolean doSubents = true);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回图层名字符串，不使用时，调用Mx::mcutDelString()释放内存
	// -------------------------------------------------------------------------
	LPCMSTR                       layer() const;

	
	// -------------------------------------------------------------------------
	// Summary:
	// 		返回图层id
	// -------------------------------------------------------------------------
	McDbObjectId                 layerId() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置图层名
	// Parameters:
	//		pszNewVal	-	图层名
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setLayer(LPCMSTR pszNewVal,
		Mdesk::Boolean doSubents = true);

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置图层Id
	// Parameters:
	//		newVal		-	图层id
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   setLayer(McDbObjectId newVal,
		Mdesk::Boolean doSubents = true);


	// -------------------------------------------------------------------------
	// Summary:
	// 		返回线型记录名字符串，不使用时，调用Mx::mcutDelString()释放内存
	// -------------------------------------------------------------------------
	LPCMSTR                       linetype() const;


	// -------------------------------------------------------------------------
	// Summary:
	// 		返回线型记录id
	// -------------------------------------------------------------------------
	McDbObjectId                linetypeId() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置线型记录名字符串
	// Parameters:
	// 		pszNewVal	-	线型记录名字符串 
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setLinetype(LPCMSTR pszNewVal,
		Mdesk::Boolean doSubents = true);


	// -------------------------------------------------------------------------
	// Summary:
	// 		设置线型记录id
	// Parameters:
	// 		newVal		-	线型记录id
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   setLinetype(McDbObjectId newVal,
		Mdesk::Boolean doSubents = true);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回线型缩放比例
	// -------------------------------------------------------------------------
	mxreal                      linetypeScale() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置线型缩放比例
	// Parameters:
	// 		newval		-	线型缩放比例
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   setLinetypeScale(mxreal newval,
		Mdesk::Boolean doSubents = true);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回实体是否可见
	// -------------------------------------------------------------------------
	McDb::Visibility            visibility() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置实体是否可见
	// Parameters:
	// 		newVal		-	实体是否可见 
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   setVisibility(McDb::Visibility newVal,
		Mdesk::Boolean doSubents = true);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回实体的线重,如果要支持线重显示，在控件初始函数后调用MxDraw::SetIsShowWeight设置显示线重
	// -------------------------------------------------------------------------
	McDb::LineWeight            lineWeight() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置实体的线重,如果要支持线重显示，在控件初始函数后调用MxDraw::SetIsShowWeight设置显示线重
	// Parameters:
	// 		newVal		-	新的线重
	//		doSubents	-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   setLineWeight(McDb::LineWeight newVal,
		Mdesk::Boolean doSubents = true);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回实体的文字风格记录id
	// -------------------------------------------------------------------------
	McDbObjectId        textStyle() const;

	
	// -------------------------------------------------------------------------
	// Summary:
	// 		设置实体的文字风格记录id
	// Parameters:
	// 		id	-	文字风格记录id
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setTextStyle(McDbObjectId id);

	//:Ignore

	virtual Mdesk::Boolean      cloneMeForDragging();
	

	McGeVector3d      normal() const;
	virtual Mcad::ErrorStatus setNormal(const McGeVector3d& newVal);


	bool  is2d() const;
	

	// -------------------------------------------------------------------------
	// Summary:
	// 		高亮显示实体
	// Parameters:
	// 		subId			-	暂没有使用
	// 		kNullSubent		-	暂没有使用
	// 		highlightAll		-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus highlight(const McDbFullSubentPath& subId 
		= McDbFullSubentPath::kNullSubent, const Mdesk::Boolean highlightAll 
		= false);

	// -------------------------------------------------------------------------
	// Summary:
	// 		取消高亮显示实体
	// Parameters:
	// 		subId			-	暂没有使用
	// 		kNullSubent		-	暂没有使用
	// 		highlightAll		-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus unhighlight(const McDbFullSubentPath& subId 
		= McDbFullSubentPath::kNullSubent, const Mdesk::Boolean highlightAll  
		= false);

	// -------------------------------------------------------------------------
	// Summary:
	// 		求两实体的交点
	// Parameters:
	// 		pEnt			-		另一个实体对象
	//		intType			-		求交点时，实体延伸求交，现在暂不支持实体延伸求交
	//		points			-		返回求到的交点
	//		thisGsMarker	-		暂没有使用
	//		otherGsMarker	-		暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	virtual  Mcad::ErrorStatus intersectWith(const McDbEntity* pEnt,
		McDb::Intersect intType, 
		McGePoint3dArray& points,
		int thisGsMarker = 0, 
		int otherGsMarker = 0,
		int iExtendDirection = McDb::kExAll
		) const;

//:Ignore

	virtual  Mcad::ErrorStatus intersectWith(const McDbEntity* pEnt,
		McDb::Intersect intType, 
		const McGePlane& projPlane,
		McGePoint3dArray& points, 
		Mdesk::GsMarker thisGsMarker = 0,
		Mdesk::GsMarker otherGsMarker = 0,
		int iExtendDirection = McDb::kExAll) const;
//:End Ignore

	// -------------------------------------------------------------------------
	// Summary:
	// 		对实体做矩阵变换
	// Parameters:
	// 		xform	-	 变换矩阵
	// Returns:
	// 		如果成功返回Mcad::eOk
	// Remarks:
	// 		例如: 旋转实体代码
	// 		<code>
	// 			McGeMatrix2d tmpMat = McGeMatrix2d::rotation(fillLine.dAngle);
	// 			pEnt->transformBy(tmpMat);
	// 		</code>
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   transformBy(const McGeMatrix3d& xform);

	// -------------------------------------------------------------------------
	// Summary:
	// 		打碎实体，自定义实体函数需要实现该函数，用于保存自定义实体信息
	// Parameters:
	// 		entitySet	 -	返回打碎后新生成的实体
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   explode(McDbVoidPtrArray& entitySet) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回实体的捕捉点信息，自定义实体重载该函数，返回捕捉信息
	// Parameters:
	// 		osnapMode				-	捕捉类型
	//		gsSelectionMark			-	暂没有使用
	//		pickPoint				-	当前鼠标拾取点
	//		lastPoint				-	前一次的鼠标拾取点
	//		viewXform				-	暂没有使用
	//		snapPoints				-	返回捕捉的点坐标数组
	//		geomIds					-	暂没有使用
	// Returns:
	// 		如果成功返回Mcad::eOk
	// Remarks:
	// 		例如:参考samples\CustomEntity\CustomEntity.sln例程
	// 		<code>
	// 			Mcad::ErrorStatus   CLinkBlock::getOsnapPoints(
	// 				McDb::OsnapMode     osnapMode,
	// 				int                 gsSelectionMark,
	// 				const McGePoint3d&  pickPoint,
	// 				const McGePoint3d&  lastPoint,
	// 				const McGeMatrix3d& viewXform,
	// 				McGePoint3dArray&   snapPoints,
	// 				McDbIntArray&       geomIds) const
	// 			{
	// 				assertReadEnabled();
	// 
	// 				if(osnapMode == AcDb::kOsModeEnd )
	// 				{
	// 					McDbBlockReference tmpBlkRef;
	// 					tmpBlkRef.setPosition(m_pos);
	// 					tmpBlkRef.setScaleFactors(m_scale);
	// 					tmpBlkRef.setRotation(m_dRotation);
	// 					tmpBlkRef.setBlockTableRecord(m_idBlkRec);
	// 					McGeMatrix3d mat = tmpBlkRef.blockTransform();
	// 
	// 					for(int i =0; i < m_aryLinkPoint.length();i++)
	// 					{
	// 						AcGePoint3d tmp = m_aryLinkPoint[i];
	// 						tmp.transformBy(mat);
	// 
	// 						snapPoints.append(tmp);
	// 					}
	// 				}
	// 				else if(osnapMode == AcDb::kOsModeIns)
	// 				{
	// 					snapPoints.append(m_pos);
	// 				}
	// 				return Acad::eOk;
	// 			}
	// 		</code>
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   getOsnapPoints(
		McDb::OsnapMode     osnapMode,
		int                 gsSelectionMark,
		const McGePoint3d&  pickPoint,
		const McGePoint3d&  lastPoint,
		const McGeMatrix3d& viewXform,
		McGePoint3dArray&   snapPoints,
		McDbIntArray&       geomIds) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		镜向实体
	// Parameters:
	// 		mirrorPt1	 -	镜像直线的第一个点
	// 		mirrorPt1	 -	镜像直线的第二个点
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus Mirror(McGePoint3d mirrorPt1,McGePoint3d mirrorPt2);

	//:Ignore

	virtual Mcad::ErrorStatus dwgInFields (McDbDwgFiler* pFiler);

	virtual Mcad::ErrorStatus dwgOutFields(McDbDwgFiler* pFiler) const;


	virtual McDbObjectId GetInnerId() const;

	virtual void         SetInnerId(McDbObjectId id);

	virtual void*        GetInnerListId() const;

	virtual void         SetInnerListId(void*);


	virtual void*        GetInnerFileListId() const;

	virtual void         SetInnerFileListId(void*);

	
	long              DrawOrder() const;


	void              SetDrawOrder(long lOrder);

	
	
	// 临时禁用对象的关闭，自动更新显示功能有，
	// 将来把临时禁用对象记下来，可以在命令结束时，再调用统一调用对象更新显示.....
	void startTempDisableUpdateGraphics();
	void endTempDisableUpdateGraphics();

	// 在关闭时，立即调用是够新显示。
	//void setTempOnCloseImpUpdateGraphics(bool isImp);

	// 显示调用更新显示。
	void callUpdateGraphics();


	bool isPropertiesWindowCustom() const;
	void  setPropertiesWindowCustom(bool isCustom);

	void applyDatabaseCurrentyProperties(McDbDatabase* pDatabase);

	virtual const std::list<McDbObjectId>* getPreViewEntity();

protected:
	virtual void OnObjectCloseEvent();

	virtual void OnObjectAttributeModiftEvent(DWORD dwFlag = McDbObject::kShapePropModify);

	virtual void objectClose    (const McDbObject* dbObj);

	bool worldDrawForODDrawingEntity(McGiWorldDraw * wd,int isODDrawingColor = 0,double stokeLineSize = -0.1);

	bool explodeForODDrawingEntity(McDbVoidPtrArray& entitySet, McGeMatrix3d* pMat,bool isExplodeFill,bool isExplodeLine) const;

	
	bool isEmptyODDrawingEntity() const;
public:

	void clearODDrawingOpenGLData();

	void internalSetOpenGLData(void* pVecGLData);

	void convertToSimplifyData2d();

	inline McDbEntityImp* getMcDbEntityImp() const {
		return (McDbEntityImp*)m_pImp;
	}
	
public:
	// iCodeVer当前存放了该数据版本。
	Mcad::ErrorStatus dwgInFieldsForExDrawingEntity(McDbDwgFiler* pFiler, int iCodeVer = McDb::kMEV_3);

	Mcad::ErrorStatus dwgOutFieldsForExDrawingEntity(McDbDwgFiler* pFiler, int iCodeVer = McDb::kMEV_3) const;

};


