// TextBox.cpp
#include "TextBox.h"
#include "SxLog.h"

TextBox::TextBox(int x, int y, int width, int height, std::string text, StellarX::TextBoxmode mode, StellarX::ControlShape shape)
	:Control(x, y, width, height), text(text), mode(mode), shape(shape)
{
	this->id = "TextBox";
}

void TextBox::draw()
{
	if (dirty && show)
	{
		saveStyle();
		setfillcolor(textBoxBkClor);
		setlinecolor(textBoxBorderClor);
		if (textStyle.nHeight > height)
			textStyle.nHeight = height;
		if (textStyle.nWidth > width)
			textStyle.nWidth = width;
		settextstyle(textStyle.nHeight, textStyle.nWidth, textStyle.lpszFace,
			textStyle.nEscapement, textStyle.nOrientation, textStyle.nWeight,
			textStyle.bItalic, textStyle.bUnderline, textStyle.bStrikeOut);

		settextcolor(textStyle.color);
		setbkmode(TRANSPARENT);
		
		int text_width = 0;
		int text_height = 0;
		std::string pwdText;
		if (StellarX::TextBoxmode::PASSWORD_MODE == mode)
		{
			for (size_t i = 0; i < text.size(); ++i)
				pwdText += '*';
			text_width = textwidth(LPCTSTR(pwdText.c_str()));
			text_height = textheight(LPCTSTR(pwdText.c_str()));
		}
		else
		{
			text_width = textwidth(LPCTSTR(text.c_str()));
			text_height = textheight(LPCTSTR(text.c_str()));
		}

		if ((saveBkX != this->x) || (saveBkY != this->y) || (!hasSnap) || (saveWidth != this->width) || (saveHeight != this->height) || !saveBkImage)
			saveBackground(this->x, this->y, this->width, this->height);
		// 恢复背景（清除旧内容）
		restBackground();
		//根据形状绘制
		switch (shape)
		{
		case StellarX::ControlShape::RECTANGLE:
			fillrectangle(x, y, x + width, y + height);//有边框填充矩形
			StellarX::TextBoxmode::PASSWORD_MODE == mode ? outtextxy(x + 10, (y + (height - text_height) / 2), LPCTSTR(pwdText.c_str()))
				: outtextxy(x + 10, (y + (height - text_height) / 2), LPCTSTR(text.c_str()));
			break;
		case StellarX::ControlShape::B_RECTANGLE:
			solidrectangle(x, y, x + width, y + height);//无边框填充矩形
			StellarX::TextBoxmode::PASSWORD_MODE == mode ? outtextxy(x + 10, (y + (height - text_height) / 2), LPCTSTR(pwdText.c_str()))
			: outtextxy(x + 10, (y + (height - text_height) / 2), LPCTSTR(text.c_str()));
			break;
		case StellarX::ControlShape::ROUND_RECTANGLE:
			fillroundrect(x, y, x + width, y + height, rouRectangleSize.ROUND_RECTANGLEwidth, rouRectangleSize.ROUND_RECTANGLEheight);//有边框填充圆角矩形
			StellarX::TextBoxmode::PASSWORD_MODE == mode ? outtextxy(x + 10, (y + (height - text_height) / 2), LPCTSTR(pwdText.c_str()))
			:outtextxy(x + 10, (y + (height - text_height) / 2), LPCTSTR(text.c_str()));
			break;
		case StellarX::ControlShape::B_ROUND_RECTANGLE:
			solidroundrect(x, y, x + width, y + height, rouRectangleSize.ROUND_RECTANGLEwidth, rouRectangleSize.ROUND_RECTANGLEheight);//无边框填充圆角矩形
			StellarX::TextBoxmode::PASSWORD_MODE == mode ? outtextxy(x + 10, (y + (height - text_height) / 2), LPCTSTR(pwdText.c_str()))
			:outtextxy(x + 10, (y + (height - text_height) / 2), LPCTSTR(text.c_str()));
			break;
		}
		restoreStyle();
		dirty = false;     //标记不需要重绘
	}
}

bool TextBox::handleEvent(const ExMessage& msg)
{
	if (!show) return false;

	bool hover = false;
	bool oldClick = click;
	bool consume = false;

	switch (shape)
	{
	case StellarX::ControlShape::RECTANGLE:
	case StellarX::ControlShape::B_RECTANGLE:
	case StellarX::ControlShape::ROUND_RECTANGLE:
	case StellarX::ControlShape::B_ROUND_RECTANGLE:
		hover = (msg.x > x && msg.x < (x + width) && msg.y > y && msg.y < (y + height));
		break;
	default:
		break;
	}

	if (hover && msg.message == WM_LBUTTONUP)
	{
		click = true;

		const size_t oldLen = text.size();
		SX_LOGI("TextBox") << SX_T("激活：id=","activate: id=") << id << " mode=" << (int)mode << " oldLen=" << oldLen;

		if (StellarX::TextBoxmode::INPUT_MODE == mode)
		{
			char* temp = new char[maxCharLen + 1];
			dirty = InputBox(temp, (int)maxCharLen + 1, "输入框", NULL, text.c_str(), NULL, NULL, false);
			if (dirty) text = temp;
			delete[] temp;
			consume = true;
		}
		else if (StellarX::TextBoxmode::READONLY_MODE == mode)
		{
			dirty = false;
			InputBox(NULL, (int)maxCharLen, "输出框（输入无效！）", NULL, text.c_str(), NULL, NULL, false);
			consume = true;
		}
		else if (StellarX::TextBoxmode::PASSWORD_MODE == mode)
		{
			char* temp = new char[maxCharLen + 1];
			// 不记录明文，只记录长度变化
			dirty = InputBox(temp, (int)maxCharLen + 1, "输入框\n不可见输入，覆盖即可", NULL, NULL, NULL, NULL, false);
			if (dirty) text = temp;
			delete[] temp;
			consume = true;
		}

		if (dirty)
		{
			SX_LOGI("TextBox") << SX_T("文本已更改: id=","text changed: id=") << id
				<< " oldLen=" << oldLen << " newLen=" << text.size();
		}
		else
		{
			SX_LOGD("TextBox") << SX_T("文本无变化：id=","no change: id=") << id;
		}

		flushmessage(EX_MOUSE | EX_KEY);
	}

	if (dirty)
		requestRepaint(parent);

	if (click)
		click = false;

	return consume;
}


void TextBox::setMode(StellarX::TextBoxmode mode)
{
	this->mode = mode;
	this->dirty = true;
}

void TextBox::setMaxCharLen(size_t len)
{
	if (len > 0)
		maxCharLen = len;
	this->dirty = true;
}

void TextBox::setTextBoxshape(StellarX::ControlShape shape)
{
	switch (shape)
	{
	case StellarX::ControlShape::RECTANGLE:
	case StellarX::ControlShape::B_RECTANGLE:
	case StellarX::ControlShape::ROUND_RECTANGLE:
	case StellarX::ControlShape::B_ROUND_RECTANGLE:
		this->shape = shape;
		this->dirty = true;
		break;
	case StellarX::ControlShape::CIRCLE:
	case StellarX::ControlShape::B_CIRCLE:
	case StellarX::ControlShape::ELLIPSE:
	case StellarX::ControlShape::B_ELLIPSE:
		this->shape = StellarX::ControlShape::RECTANGLE;
		this->dirty = true;
		break;
	}
}

void TextBox::setTextBoxBorder(COLORREF color)
{
	textBoxBorderClor = color;
	this->dirty = true;
}

void TextBox::setTextBoxBk(COLORREF color)
{
	textBoxBkClor = color;
	this->dirty = true;
}

void TextBox::setText(std::string text)
{
	if (text.size() > maxCharLen)
		text = text.substr(0, maxCharLen);
	this->text = text;
	this->dirty = true;
}

std::string TextBox::getText() const
{
	return this->text;
}