#pragma once
#include "McDbEntity.h"
#include "McDbDatabase.h"

// -------------------------------------------------------------------------
// Summary:
// 		多文本的显示片段数据，把多文字格式分析后，生成的显示数据
// -------------------------------------------------------------------------
struct McDbMTextFragment
{
	enum  Flag
	{
		kunderlined = 0x01,
		koverlined = 0x02,
		kbold = 0x04,
		kitalic = 0x08,

		kstackTop = 0x10,
		kstackBottom = 0x20
	};
	McGePoint3d* m_pUnder_OverPoints;
	McGePoint3d   location;		//	文字的位置
	MxStringVariable        text;		//	文字内容
	MxStringVariable        font;		//	西文字体shx文件
	MxStringVariable        bigfont;		//	中文字体shx文件
	MxStringVariable  fontname;				// 文字显示的TrueType字体
	// 这个direction变量，好像没啥用，就是一个角度mxreal_p.
	McGeVector3dFloat direction;
	mxreal_p       capsHeight;		//	文字高度
	mxreal_p       widthFactor;		//	宽度引放比例
	mxreal_p       obliqueAngle;		//	文字显示的倾斜角度
	McCmColor     color;				//	文字颜色

	mxbyte     flag;

	
	McDbMTextFragment()
	{
		capsHeight		= 1.0f;
		widthFactor		= 1.0f;
		obliqueAngle	= 0.0f;	
		flag = 0;
		m_pUnder_OverPoints = 0;
	}

	~McDbMTextFragment() {
		delete m_pUnder_OverPoints;
	}

	McDbMTextFragment(const McDbMTextFragment& data)
	{
		location = data.location;	
		text=data.text;
		font= data.font;
		bigfont= data.bigfont;
		fontname= data.fontname;
		direction= data.direction;
		color= data.color;
		capsHeight = data.capsHeight;
		widthFactor = data.widthFactor;
		obliqueAngle = data.obliqueAngle;
		flag = data.flag;
		m_pUnder_OverPoints = 0;
		if (data.m_pUnder_OverPoints) {
			m_pUnder_OverPoints = new McGePoint3d[4];
			m_pUnder_OverPoints[0] = data.m_pUnder_OverPoints[0];
			m_pUnder_OverPoints[1] = data.m_pUnder_OverPoints[1];
			m_pUnder_OverPoints[2] = data.m_pUnder_OverPoints[2];
			m_pUnder_OverPoints[3] = data.m_pUnder_OverPoints[3];
		}
	}

	McDbMTextFragment& operator=(const McDbMTextFragment& data)
	{
		if (m_pUnder_OverPoints) delete m_pUnder_OverPoints;

		location = data.location;
		text = data.text;
		font = data.font;
		bigfont = data.bigfont;
		fontname = data.fontname;
		direction = data.direction;
		color = data.color;
		capsHeight = data.capsHeight;
		widthFactor = data.widthFactor;
		obliqueAngle = data.obliqueAngle;
		flag = data.flag;
		m_pUnder_OverPoints = 0;
		if (data.m_pUnder_OverPoints) {
			m_pUnder_OverPoints = new McGePoint3d[4];
			m_pUnder_OverPoints[0] = data.m_pUnder_OverPoints[0];
			m_pUnder_OverPoints[1] = data.m_pUnder_OverPoints[1];
			m_pUnder_OverPoints[2] = data.m_pUnder_OverPoints[2];
			m_pUnder_OverPoints[3] = data.m_pUnder_OverPoints[3];
		}

		return *this;
	}



	inline void getPointsVar(
		McGePoint3d* underPoints,
		McGePoint3d* overPoints) const
	{
		if (m_pUnder_OverPoints) {
			underPoints[0] = m_pUnder_OverPoints[0];
			underPoints[1] = m_pUnder_OverPoints[1];

			overPoints[0] = m_pUnder_OverPoints[2];
			overPoints[1] = m_pUnder_OverPoints[3];
		}
	}

	inline void setPointsVar(McGePoint3d* underPoints,
		McGePoint3d* overPoints, mxint8 underlined, mxint8 overlined) {
		if (underlined) {
			flag |= kunderlined;
		}
		else {
			flag &= ~kunderlined;
		}

		if (overlined) {
			flag |= koverlined;
		}
		else {
			flag &= ~koverlined;
		}

		if (underlined == 0 && overlined == 0) {
			delete m_pUnder_OverPoints;
			m_pUnder_OverPoints = 0;
		}
		else {

			if (!m_pUnder_OverPoints)  m_pUnder_OverPoints = new McGePoint3d[4];

			m_pUnder_OverPoints[0] = underPoints[0];
			m_pUnder_OverPoints[1] = underPoints[1];

			m_pUnder_OverPoints[2] = overPoints[0];
			m_pUnder_OverPoints[3] = overPoints[1];
		}
	}

	inline void getBoolVar(
		mxint8& stackTop,
		mxint8& stackBottom,
		mxint8&   underlined,
		mxint8&    overlined,
		mxbool&     bold,
		mxbool&     italic) const
	{

		stackTop = flag & kstackTop ? 1 : 0;
		stackBottom = flag & kstackBottom ? 1 : 0;

		underlined = flag & kunderlined ? 1 : 0;
		overlined = flag & koverlined ? 1 : 0;

		bold = flag & kbold;
		italic = flag & kitalic;
	}

	inline void setBoolVar(
		mxint8 stackTop,
		mxint8 stackBottom,
		mxint8   underlined,
		mxint8    overlined,
		mxbool     bold,
		mxbool     italic) {
		flag = 0;
		if (stackTop) flag |= kstackTop;
		if (stackBottom) flag |= kstackBottom;
		if (underlined) flag |= kunderlined;
		if (overlined) flag |= koverlined;
		if (bold) flag |= kbold;
		if (italic) flag |= kitalic;
	}
};


class McDbMTextImp;

// -------------------------------------------------------------------------
// Summary:
// 		多行文本实体类型
// Remarks:
// 		例如:多行文字类，绘制多行文字函数代码如下：
// 		<code>
// 			McDbMText* Mx::AddMText(IN McDbBlockTableRecord* pBlkRec,
// 									IN LPCMSTR pszContents,
// 									IN McGePoint3d  pos,
// 									IN mxreal width,
// 									IN mxreal textHeight,
// 
// 									IN mxreal rotation								/*= 0.0*/,		
// 									IN McGeVector3d direction						/*= McGeVector3d::kXAxis*/,
// 									IN int  attachment		/*=  McDbMText::kTopLeft*/,
// 									IN int    flowDirection	/*= McDbMText::kLtoR*/,
// 									IN mxreal dFactor								/*= 1.0*/,
// 									IN McDb::LineSpacingStyle style				/*	= McDb::kAtLeast*/
// 									)
// 			{
// 				McDbObjectId retId;
// 				McDbMText* pMText = new McDbMText;
// 				pMText->setContents(pszContents);
// 				pMText->setLocation(pos);
// 				pMText->setWidth(width);
// 				pMText->setTextHeight(textHeight);
// 				pMText->setRotation(rotation);
// 				pMText->setDirection(direction);
// 				pMText->setAttachment(McDbMText::AttachmentPoint(attachment) );
// 				pMText->setFlowDirection(McDbMText::FlowDirection(flowDirection) );
// 				pMText->setLineSpacingFactor(dFactor);
// 				pMText->setLineSpacingFactor(style);
// 				pBlkRec->appendAcDbEntity(retId,pMText);
// 				return pMText;
// 			}
// 		</code>
// -------------------------------------------------------------------------
class ARXDLL McDbMText  : public McDbEntity 
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McDbMText(void);

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

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

	// -------------------------------------------------------------------------
	// Summary:
	// 		多行文字的对齐方式
	// -------------------------------------------------------------------------
	enum AttachmentPoint {
		kTopLeft    = 1,
		kTopCenter  = 2,
		kTopRight   = 3,
		kMiddleLeft = 4,
		kMiddleCenter   = 5,
		kMiddleRight    = 6,
		kBottomLeft = 7,
		kBottomCenter   = 8,
		kBottomRight    = 9,
		kBaseLeft       = 10,   // Reserved for future use
		kBaseCenter     = 11,   // Reserved for future use
		kBaseRight      = 12,   // Reserved for future use
		kBaseAlign      = 13,   // Reserved for future use
		kBottomAlign    = 14,   // Reserved for future use
		kMiddleAlign    = 15,   // Reserved for future use
		kTopAlign       = 16,   // Reserved for future use
		kBaseFit        = 17,   // Reserved for future use
		kBottomFit      = 18,   // Reserved for future use
		kMiddleFit      = 19,   // Reserved for future use
		kTopFit         = 20,   // Reserved for future use
		kBaseMid        = 21,   // Reserved for future use
		kBottomMid      = 22,   // Reserved for future use
		kMiddleMid      = 23,   // Reserved for future use
		kTopMid         = 24,   // Reserved for future use
	};

	// -------------------------------------------------------------------------
	// Summary:
	// 		多行文字的显示方向
	// -------------------------------------------------------------------------
	enum FlowDirection {
		kLtoR       = 1,	//	从左到右
		kRtoL       = 2,    //  not currently supported
		kTtoB       = 3,	//	从上到下
		kBtoT       = 4,    //  not currently supported
		kByStyle    = 5		//  取文字样式
	};

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回文字位置
	// -------------------------------------------------------------------------
	McGePoint3d     location() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置文字位置
	// Parameters:
	// 		pt	-	文字位置 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setLocation(const McGePoint3d& pt);

	//:Ignore

	McGeVector3d    direction() const;
	Mcad::ErrorStatus   setDirection(const McGeVector3d&);
	//:End Ignore

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回多行文字的旋转角度
	// -------------------------------------------------------------------------
	mxreal      rotation() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置多行文字的旋转角度
	// Parameters:
	// 		dAng	-	文字的旋转角度 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setRotation(mxreal dAng);


	// -------------------------------------------------------------------------
	// Summary:
	// 		返回多行文字的宽度
	// -------------------------------------------------------------------------
	mxreal      width() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置多行文字的宽度
	// Parameters:
	// 		dWidth	-	多行文字的宽度
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setWidth(mxreal dWidth);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回多行文字的高度
	// -------------------------------------------------------------------------
	mxreal      textHeight() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置多行文字的高度
	// Parameters:
	// 		dHeight	-	多行文字的高度
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setTextHeight(mxreal dHeight);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回多行文字的对齐方式
	// -------------------------------------------------------------------------
	McDbMText::AttachmentPoint attachment() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置多行文字的对齐方式
	// Parameters:
	// 		attachment	-	多行文字的对齐方式
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus   setAttachment(McDbMText::AttachmentPoint attachment);


	// -------------------------------------------------------------------------
	// Summary:
	// 		返回多行文字的内容
	// -------------------------------------------------------------------------
	LPCMSTR        contents() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置多行文字的内容
	// Parameters:
	// 		pszContents	-	多行文字的内容
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	int         setContents(LPCMSTR pszContents);

	//:Ignore

	
	bool getAllText(std::vector<MxString>& vecText);

	virtual Mcad::ErrorStatus   explode(McDbVoidPtrArray& entitySet) const;

	Mcad::ErrorStatus   setLineSpacingFactor(mxreal dFactor);
	mxreal              lineSpacingFactor() const;

	Mcad::ErrorStatus   setLineSpacingStyle(McDb::LineSpacingStyle eStyle);
	McDb::LineSpacingStyle lineSpacingStyle() const;

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

	McDbMText::FlowDirection   flowDirection() const;
	Mcad::ErrorStatus   setFlowDirection(McDbMText::FlowDirection);

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

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

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


	virtual void objectClose    (const McDbObject* dbObj);

	virtual void modified(const McDbObject* dbObj);


	Mcad::ErrorStatus   InnerTransformBy(const McGeMatrix3d& xform);


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

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

	virtual McRxObject*        clone() const;

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



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

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


	Mcad::ErrorStatus reCompute();

	inline McDbMTextImp* getMcDbMTextImp() const {
		return (McDbMTextImp*)m_pImp;
	}
};

//:End Ignore