#pragma once
#include "Dbents.h"
class McGiWorldDrawImp;
class MxFilter;
class ARXDLL McDbAttribute: public McDbText
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McDbAttribute();

	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// Parameters:
	// 		position	-	文字的插入点
	//		text		-	文字内容字符串
	//		tag			-	标签字符串
	//		style		-	文字风格
	// -------------------------------------------------------------------------
	McDbAttribute(
		const McGePoint3d& position,
		LPCMSTR        text,
		LPCMSTR        tag,
		McDbObjectId       style = McDbObjectId::kNull);

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

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


	// -------------------------------------------------------------------------
	// Summary:
	// 		返回标签字符串
	// -------------------------------------------------------------------------
	LPCMSTR               tagConst() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置标签字符串
	// Parameters:
	// 		newTag	-	标签字符串 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setTag(LPCMSTR newTag);

	// -------------------------------------------------------------------------
	// Summary:
	// 		属性是否可见
	// -------------------------------------------------------------------------
	Mdesk::Boolean      isInvisible() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置是否可见
	// Parameters:
	// 		bInvisible	-	是否可见
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setInvisible(Mdesk::Boolean bInvisible);

	// -------------------------------------------------------------------------
	// Summary:
	// 		属性对象是否为常数
	// -------------------------------------------------------------------------
	Mdesk::Boolean      isConstant() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		属性对象是否设为校验用户输入
	// -------------------------------------------------------------------------
	Mdesk::Boolean      isVerifiable() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		属性对象有一个预设值且不提示用户输入
	// -------------------------------------------------------------------------
	Mdesk::Boolean      isPreset() const;

	//:Ignore



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

	virtual Mdesk::Boolean    worldDraw(McGiWorldDraw* mode);


	Mcad::ErrorStatus deepClone(
		McDbObject*& pClone,
		McDbCloneIdMapping& idMap) const override;
	//:End Ignore
private:
	MxStringVariable      m_sTag;
	mxint8        m_flag;


};


class McDbObjectIterator;
// -------------------------------------------------------------------------
// Summary:
// 		McDbBlockReference类表示在AutoCAD中INSERT实体,一个块参考用于放置、缩放和显示它参考的McDbBlockTableRecord中的一个实体集合的实例
// -------------------------------------------------------------------------
class  ARXDLL McDbBlockReference : public McDbEntity
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McDbBlockReference();


	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// Parameters:
	// 		position		-	块引用插入点
	//		blockTableRec	-	引用的块表记录id
	// -------------------------------------------------------------------------
	McDbBlockReference(const McGePoint3d&  position,
		McDbObjectId  blockTableRec);

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

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

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回块表记录id
	// -------------------------------------------------------------------------
	McDbObjectId      blockTableRecord() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置块表记录id
	// Parameters:
	// 		id	-	块表记录id 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus setBlockTableRecord(McDbObjectId id);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回块引用插入位置
	// -------------------------------------------------------------------------
	McGePoint3d       position() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置块引用插入位置
	// Parameters:
	// 		pos	-	块引用插入位置 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus setPosition(const McGePoint3d& pos);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回块的缩放比例
	// -------------------------------------------------------------------------
	McGeScale3d       scaleFactors() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置块的缩放比例
	// Parameters:
	// 		scale	-	块的缩放比例 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus setScaleFactors(const McGeScale3d& scale);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回块的旋转角度，单位弧度
	// -------------------------------------------------------------------------
	mxreal            rotation() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置块的旋转角度，单位弧度
	// Parameters:
	// 		newVal	-	旋转角度，单位弧度 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus setRotation(mxreal newVal);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回块记录中的实体坐标变换成wcs坐标的变换矩阵
	// -------------------------------------------------------------------------
	McGeMatrix3d      blockTransform(bool isIgnoreZ = false) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置块记录中的实体坐标变换成wcs坐标的变换矩阵
	// Parameters:
	// 		mat	-	块记录中的实体坐标变换成wcs坐标的变换矩阵
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus setBlockTransform(const McGeMatrix3d& mat);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回块的外包矩形框
	// Parameters:
	// 		extents			-	块的外包矩形框
	//		parentXform		-	暂没使用
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus geomExtentsBestFit( 
		McDbExtents& extents, 
		const McGeMatrix3d& parentXform = 
		McGeMatrix3d::kIdentity, bool roughCalculation = true) const;


	// -------------------------------------------------------------------------
	// Summary:
	// 		打碎块
	// Parameters:
	// 		entitySet - 打碎后新生成的实体
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// Remarks:
	// 		例如:打碎图块代码
	// 		<code>
	// 			void ExplodeBlockReference()
	// 			{
	// 				ads_name entName;
	// 				ads_point pt;
	// 				if(acedEntSel(_MXT("打碎的块引用:"),entName,pt) != RTNORM)
	// 				{
	// 					return;
	// 				}
	// 				AcDbObjectId objId;
	// 				if(acdbGetObjectId(objId,entName) != Acad::eOk)
	// 					return;
	// 
	// 				McDbObjectPointer<McDbBlockReference> spBlkRef(objId,AcDb::kForWrite);
	// 				if(spBlkRef.openStatus() != Acad::eOk)
	// 					return;
	// 
	// 				McDbVoidPtrArray entitySet;
	// 				if(spBlkRef->explode(entitySet) != Mcad::eOk)
	// 					return;
	// 
	// 				for(int i = 0; i < entitySet.length();i++)
	// 				{
	// 					McDbEntity* pEnt = (McDbEntity*)entitySet[i];
	// 					MrxDbgUtils::addToCurrentSpaceAndClose(pEnt);
	// 				}
	// 
	// 				spBlkRef->erase();
	// 			}
	// 		</code>
	// -------------------------------------------------------------------------
	virtual Mcad::ErrorStatus   explode(McDbVoidPtrArray& entitySet) const;

	//:Ignore

	bool  isSortDrawEntity() const;

	// 在worlddraw时，保证显示序顺是对的，使用排序算法先对对象排个序.
	void  setSortDrawEntity(bool isSort);


	Mdesk::Boolean worldDrawImp(McGiWorldDraw* mode, McGeMatrix3d* pMatBlockTransform);

	virtual Mdesk::Boolean    worldDraw(McGiWorldDraw* mode);

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

	virtual Mcad::ErrorStatus moveGripPointsAt(const McGeIntArray& indices,
		const McGeVector3d& offset);

	virtual Mcad::ErrorStatus getGripPoints(McGePoint3dArray& gripPoints,
		McGeIntArray& osnapModes,
		McGeIntArray& geomIds) const;



	MxString  getTzBlockName() const ;

	void  setTzBlockName(const MxString& pszName);

	Mcad::ErrorStatus appendAttribute(McDbAttribute*);

	void eraseAllAttribute();

	Mcad::ErrorStatus appendAttributeEx(McDbObjectId idAttributeDef, McGeMatrix3d* pBlkMat);

	McDbObjectIterator*  attributeIterator() const;

	Mcad::ErrorStatus   getGeomExtents(McDbExtents& extents, bool roughCalculation = true) const;



	virtual Mcad::ErrorStatus   transformBy(const McGeMatrix3d& xform);



	virtual Mcad::ErrorStatus   getOsnapPoints(
		McDb::OsnapMode     osnapMode,
		int                 gsSelectionMark,
		const McGePoint3d&  pickPoint,
		const McGePoint3d&  lastPoint,
		const McGeMatrix3d& viewXform,
		McGePoint3dArray&   snapPoints,
		McDbIntArray&       geomIds) const;

	virtual Mcad::ErrorStatus Mirror(McGePoint3d mirrorPt1,McGePoint3d mirrorPt2);

	//:End Ignore

	virtual McDbObjectId GetInnerId() const;

	virtual void         SetInnerId(McDbObjectId id);

	virtual void*        GetInnerListId() const;

	virtual void         SetInnerListId(void*);

	typedef std::list<McDbObjectId>					list_attribute_t;
	typedef list_attribute_t::iterator				list_attribute_iter;
	typedef list_attribute_t::const_iterator		list_attribute_constiter;


	void getMcDbSpatialFilterBoundary(McGePoint2dArray& points,bool& isInverted);


	bool isInstanceworldDraw();

	Mcad::ErrorStatus  addExplode(McDbObjectIdArray& aryId) const;


	McDbObjectId getSpatialFilter() const;

	bool copySpatialFilter(McDbObjectId idFilter);
	bool copySpatialFilter(McDbBlockReference* pFormBlkRef);

	McDbObjectId createSpatialFilter();


	Mcad::ErrorStatus createAttribute();

	Mcad::ErrorStatus   setReFindFilter(Mdesk::Boolean v);

	Mcad::ErrorStatus copyAttribute(McDbBlockReference* pToBlkRef) const;



	bool deepCloneAttribute(
		McDbBlockReference* pToObj,
		McDbCloneIdMapping& idMap);

	virtual  Mcad::ErrorStatus intersectWith(const McDbEntity* pEnt,
		McDb::Intersect intType,
		McGePoint3dArray& points,
		int thisGsMarker = 0,
		int otherGsMarker = 0,
		int iExtendDirection = McDb::kExAll
	) const;

protected:

	Mcad::ErrorStatus   explodeImp(McDbVoidPtrArray& entitySet,
		std::map<McDbBlockReference*, McDbObjectId>* pMapBlkRef = NULL,
		std::map<void*, McDbObjectId>* pMapObject = NULL, bool isOnlyExlodeCurve = false
	) const;


	Mcad::ErrorStatus   explodeImpEx(const std::function<bool(McDbEntity*)>& callbackp, std::set<const McRxClass*>* pSetFilter) const;

	McDbBlockReference* MyClone() const;

	Mcad::ErrorStatus   transformByexplode(const McGeMatrix3d& xform, McGeScale3d srcscale);

	Mdesk::Boolean worldDrawSelectInstance(McGiWorldDraw* mode);

	Mdesk::Boolean    isReFindFilter() const;



	void InitFilter(McGeMatrix3d blockTransMat);

	Mdesk::Boolean  getClipPoints(McGePoint2dArray& aryClipPoints);

	Mdesk::Boolean CreateBlockReferenceDisplayTable_worldDraw(McGiWorldDrawImp* mode);

	Mcad::ErrorStatus   getGeomExtentsImp(McDbExtents& extents,bool isOsnapCall =false) const;

protected:
	Mdesk::Boolean worldDrawForDragDisplay(McGiWorldDraw* mode);

	inline list_attribute_t* getListAttribate() {
		if (!m_pLstAtrribute) {
			m_pLstAtrribute = new list_attribute_t();
		}
		return m_pLstAtrribute;
	}

	bool copyAtrributeImp(McDbBlockReference* pToObj) const;
private:
	McGePoint3d				m_pos;				// 块引用的位置
	mxreal				        m_dRotation;		// 块引用的旋转角度
	McGeVector3dFloat		m_scale;			// 块引用的缩放比例
	list_attribute_t*         m_pLstAtrribute;
	MxFilter*                   m_pFilter;
	McDbHardPointerId    m_idBlkRec;			// 块记录的ID.
	mxint8                      m_flag;
};
