#include "CMyDXList.h"
#include "resource.h"
#include "CMainEditor.h"

IMPLEMENT_DYNAMIC(CMyDXList, CDialog)

BEGIN_MESSAGE_MAP(CMyDXList, CDialog)
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_VSCROLL()
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_MOUSEWHEEL()
END_MESSAGE_MAP()

CMyDXList::CMyDXList(CWnd* pParent)
	: CDialog(IDD_CMYDXLIST, pParent)
{
}

CMyDXList::~CMyDXList()
{
	if (pFont_sourcesun14)
		TTF_CloseFont(pFont_sourcesun14);
	for (auto& p : pFontMap70)
	{
		if (p.second.pTexture)
			p.second.pTexture->Release();
		if (p.second.pSRV)
			p.second.pSRV->Release();
	}
	for (auto& p : loadedTexture)
	{
		if (p.second.pSRV)
		{
			p.second.pSRV->Release();
			p.second.pSRV = nullptr;
		}
		if (p.second.pTexture)
		{
			p.second.pTexture->Release();
			p.second.pTexture = nullptr;
		}
	}
	loadedTexture.clear();
}

void CMyDXList::Draw()
{
	if (view.window_h == 0 || view.window_w == 0)
		return;
	//绘制窗口背景色
	pRenderer.RenderClear(1.0f, 1.0f, 1.0f);
	//绘制列表
	int y = (int)(view.offY / view.lineHeight);//从第y个列表开始绘制
	int len = (int)(view.window_h / view.lineHeight + 1);//绘制count_h个
	float dy = y * view.lineHeight - view.offY;
	float nextX = 0;
	float nextY = 0;
	MyRect dst;
	for (int i = 0; i < len; i++)
	{
		//限制绘制数量
		if (y + i >= (int)itemList.size())
			break;
		auto& p = itemList.at(y + i);
		//绘制头像
		dst.Set1(0, dy, view.icon_w, view.icon_h);
		pRenderer.SetTPenDraw(GetTexture(p.png));
		pRenderer.AddRenderCopy(nullptr, &dst);
		pRenderer.DrawRenderCopy();
		//绘制名字
		nextX = view.icon_w;
		nextY = dy + view.lineHeight / 2;
		pRenderer.DrawText_Unicode(&pFontMap70, pFont_sourcesun14, p.name.GetString(), 0, &nextX, &nextY, RGBA(0, 0, 0, 0xff));

		dy += view.lineHeight;
	}
	//绘制光标
	if (view.selected >= 0)
	{
		dst.Set1(0, view.selected * view.lineHeight - view.offY, view.window_w, view.lineHeight);
		pRenderer.SetPenDraw();
		pRenderer.AddFillRect(&dst, RGBA(0, 0x80, 0xff, 0x40));
		pRenderer.DrawFillRect();
	}
	//呈现
	pRenderer.RenderPresent();
}

void CMyDXList::Init(float lineHeight, float icon_w, float icon_h)
{
	view.lineHeight = lineHeight;
	view.icon_w = icon_w;
	view.icon_h = icon_h;
	CRect rc;
	GetClientRect(&rc);
	view.window_w = (float)rc.Width();
	view.window_h = (float)rc.Height();
}

void CMyDXList::SetCurSel(int index)
{
	int sel_prep = view.selected;
	if (itemList.size() == 0 || index < 0)
	{
		view.selected = -1;
		SendSelChangeMsg();
	}
	if (index >= 0 && index < itemList.size())
		view.selected = index;
	else
	{
		view.selected = -1;
		SendSelChangeMsg();
	}
	if (view.selected != sel_prep)
		SendSelChangeMsg();
	Draw();
}

int CMyDXList::GetCurSel()
{
	return view.selected;
}

void CMyDXList::AddItem(CString text, CString pngName)
{
	CMyDXListDrawItem item;
	item.name = text;
	item.png = pngName;
	itemList.push_back(item);
	SetVScrollBar();
	Draw();
}

void CMyDXList::SetMenu(int selectedMenu, int notSelectedMenu)
{
	this->selectedMenu = selectedMenu;
	this->notSelectedMenu = notSelectedMenu;
}

void CMyDXList::Clear()
{
	view.selected = -1;
	for (auto& p : loadedTexture)
	{
		if (p.second.pSRV)
		{
			p.second.pSRV->Release();
			p.second.pSRV = nullptr;
		}
		if (p.second.pTexture)
		{
			p.second.pTexture->Release();
			p.second.pTexture = nullptr;
		}
	}
	loadedTexture.clear();
	itemList.clear();
}

bool CMyDXList::Empty()
{
	return itemList.empty();
}

void CMyDXList::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BOOL CMyDXList::OnInitDialog()
{
	CDialog::OnInitDialog();
	pRenderer.Init(m_hWnd);
	//初始化字体
	pFont_sourcesun14 = pRenderer.MyLoadFont("SourceHanSansSC-Normal", 14);
	return 0;
}

void CMyDXList::OnSize(UINT nType, int cx, int cy)
{
	CDialog::OnSize(nType, cx, cy);

	
	pRenderer.OnSize(cx, cy, nType == SIZE_MINIMIZED);
	CRect rc;
	GetClientRect(&rc);
	view.window_w = (float)rc.Width();
	view.window_h = (float)rc.Height();
	SetVScrollBar();
}

void CMyDXList::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	
	// 不为绘图消息调用 CDialog::OnPaint()
	Draw();
}

void CMyDXList::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	
	//内容还没到足以翻页时，限制滚动
	if (itemList.size() * view.lineHeight - view.window_h < 0)
	{
		view.offY = 0;
		SetScrollPos(SB_VERT, 0);
		Draw();
		CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
	}

	switch (nSBCode)
	{
	case SB_LINEUP:
		if ((int)view.offY % (int)view.lineHeight)
			view.offY = floorf(view.offY / view.lineHeight) * view.lineHeight;
		else
			view.offY -= view.lineHeight;
		nPos = (int)max(view.offY, 0);
		view.offY = (float)nPos;
		SetScrollPos(SB_VERT, nPos);
		Draw();
		break;
	case SB_LINEDOWN:
		if ((int)view.offY % (int)view.lineHeight)
			view.offY = ceilf(view.offY / view.lineHeight) * view.lineHeight;
		else
			view.offY += view.lineHeight;
		nPos = (int)min(view.offY, itemList.size() * view.lineHeight - view.window_h);
		view.offY = (float)nPos;
		SetScrollPos(SB_VERT, nPos);
		Draw();
		break;
	case SB_PAGEUP:
		view.offY -= view.window_h;
		nPos = (int)max(view.offY, 0);
		view.offY = (float)nPos;
		SetScrollPos(SB_VERT, nPos);
		Draw();
		break;
	case SB_PAGEDOWN:
		view.offY += view.window_h;
		nPos = (int)min(view.offY, itemList.size() * view.lineHeight - view.window_h);
		view.offY = (float)nPos;
		SetScrollPos(SB_VERT, nPos);
		Draw();
		break;
	case SB_THUMBTRACK:
		view.offY = (float)nPos;
		SetScrollPos(SB_VERT, nPos);
		Draw();
		break;
	}
	CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CMyDXList::OnLButtonDown(UINT nFlags, CPoint point)
{
	
	UpdateSel(point);
	Draw();
	CDialog::OnLButtonDown(nFlags, point);
}

void CMyDXList::OnRButtonDown(UINT nFlags, CPoint point)
{
	
	UpdateSel(point);
	Draw();
	if (view.selected >= 0)
	{
		// 加载弹出菜单
		CMenu m, * pm;
		m.LoadMenu(selectedMenu);
		pm = m.GetSubMenu(0);
		ClientToScreen(&point);
		pm->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
			point.x, point.y, GetParent());
		goto CMyDXList_OnRButtonDown;
	}
	if (notSelectedMenu)// 加载弹出菜单
	{
		CMenu m, * pm;
		m.LoadMenu(notSelectedMenu);
		pm = m.GetSubMenu(0);
		ClientToScreen(&point);
		pm->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
			point.x, point.y, GetParent());
	}
CMyDXList_OnRButtonDown:
	CDialog::OnRButtonDown(nFlags, point);
}

BOOL CMyDXList::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	
	//内容还没到足以翻页时，限制滚动
	if (itemList.size() * view.lineHeight - view.window_h < 0)
	{
		view.offY = 0;
		SetScrollPos(SB_VERT, 0);
		Draw();
		return CDialog::OnMouseWheel(nFlags, zDelta, pt);
	}

	int nPos;
	if (zDelta > 0)//往上翻
	{
		if ((int)view.offY % (int)view.lineHeight)
			view.offY = floorf(view.offY / view.lineHeight) * view.lineHeight;
		else
			view.offY -= view.lineHeight;
		nPos = (int)max(view.offY, 0);
	}
	else//往下翻
	{
		if ((int)view.offY % (int)view.lineHeight)
			view.offY = ceilf(view.offY / view.lineHeight) * view.lineHeight;
		else
			view.offY += view.lineHeight;
		nPos = (int)min(view.offY, itemList.size() * view.lineHeight - view.window_h);
	};
	view.offY = (float)nPos;
	SetScrollPos(SB_VERT, nPos);
	Draw();
	return CDialog::OnMouseWheel(nFlags, zDelta, pt);
}

void CMyDXList::UpdateSel(CPoint point)
{
	int sel_prep = view.selected;
	view.selected = -1;
	if (itemList.size() > 0)
	{
		int sel = (int)((point.y + view.offY) / view.lineHeight);
		if ((sel >= 0 && sel < itemList.size()))
			view.selected = sel;
	}
	if (view.selected != sel_prep)
		SendSelChangeMsg();
}

void CMyDXList::SetVScrollBar()
{
	SCROLLINFO info = {};
	info.cbSize = sizeof(SCROLLBARINFO);
	info.fMask = SIF_PAGE | SIF_RANGE;
	info.nMin = 0;
	info.nMax = (int)(itemList.size() * view.lineHeight);
	info.nPage = (UINT)view.window_h;
	SetScrollInfo(SB_VERT, &info);
}

void CMyDXList::SendSelChangeMsg()
{
	//往父窗口发送消息
	auto parent = GetParent();
	if (parent != nullptr)
		::SendMessageW(parent->m_hWnd, MYDXLIST_SELCHANGED, (WPARAM)view.selected, (LPARAM)0);
}

ID3D11ShaderResourceView* CMyDXList::GetTexture(CString pngName)
{
	if (loadedTexture.find(pngName.GetString()) == loadedTexture.end())
	{
		std::vector<char> gbk_buff;
		//测试pngName是路径全名还是单文件名
		if (pngName.ReverseFind('\\') == -1)
		{
			//单文件名
			CString wstr;
			wstr.Format(L"./data/png/%s", pngName.GetString());
			UTF16ToGBK(wstr.GetString(), &gbk_buff);

			//确认文件是否存在
			FILE* fp;
			fopen_s(&fp, gbk_buff.data(), "rb");
			if (fp)
				fclose(fp);
			else
			{
				wstr.Format(L"./data/png/%s", NULLFACE);
				UTF16ToGBK(wstr.GetString(), &gbk_buff);

			}
			MyTextureAndSRV tas;
			pRenderer.MyLoadTexture(&tas.pTexture, gbk_buff.data());
			pRenderer.MyCreateShaderResourceView(&tas.pSRV, tas.pTexture);

			loadedTexture.insert(std::make_pair(pngName.GetString(), tas));
			return tas.pSRV;
		}
		else
		{
			//全路径名
			UTF16ToGBK(pngName.GetString(), &gbk_buff);

			MyTextureAndSRV tas;
			pRenderer.MyLoadTexture(&tas.pTexture, gbk_buff.data());
			pRenderer.MyCreateShaderResourceView(&tas.pSRV, tas.pTexture);

			loadedTexture.insert(std::make_pair(pngName.GetString(), tas));
			return tas.pSRV;
		}
	}
	return loadedTexture.at(pngName.GetString()).pSRV;
}



