#include "CPxaEditorDraw.h"
#include "resource.h"
#include "CPxaEditor.h"

IMPLEMENT_DYNAMIC(CPxaEditorDraw, CDialog)

BEGIN_MESSAGE_MAP(CPxaEditorDraw, CDialog)
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_MOUSEWHEEL()
	ON_WM_MOUSEMOVE()
	ON_WM_VSCROLL()
	ON_WM_HSCROLL()
END_MESSAGE_MAP()

CPxaEditorDraw::CPxaEditorDraw(CWnd* pParent)
	: CDialog(IDD_CPXAEDITOR_DRAW, pParent)
{
}

CPxaEditorDraw::~CPxaEditorDraw()
{
	if (tas.pSRV)
		tas.pSRV->Release();
	if (tas.pTexture)
		tas.pTexture->Release();
	if (tas_pxatype.pSRV)
		tas_pxatype.pSRV->Release();
	if (tas_pxatype.pTexture)
		tas_pxatype.pTexture->Release();
}

MyView* CPxaEditorDraw::GetMyView()
{
	return &view;
}

void CPxaEditorDraw::Draw()
{
	auto parentEditor = (CPxaEditor*)pParentEditor;
	pRenderer.RenderClear();
	if (parentEditor->showBk)
		view.DrawTransparentBk();
	if (tas.pSRV)
	{
		MyRect src, dst;
		pRenderer.GetRenderCopyDefaultRect(tas.pSRV, &src, nullptr);
		dst.Set1(-floorf(view.offX * view.scale),
			-floorf(view.offY * view.scale),
			src.GetWidth() * view.scale,
			src.GetHeight() * view.scale);
		pRenderer.SetTPenDraw(tas.pSRV);
		pRenderer.AddRenderCopy(nullptr, &dst);
		pRenderer.DrawRenderCopy();
	}
	DrawPxa();
	if (parentEditor->showGrid)
		view.DrawGrid();
	view.DrawBorderLine();
	view.DrawCursor();
	pRenderer.RenderPresent();
}

void CPxaEditorDraw::Load(CString filename)
{
	//载入贴图
	if (tas.pSRV)
		tas.pSRV->Release();
	if (tas.pTexture)
		tas.pTexture->Release();
	std::vector<char> utf8_buff;
	UTF16ToUTF8(filename.GetString(), &utf8_buff);
	pRenderer.MyLoadTexture(&tas.pTexture, utf8_buff.data());
	pRenderer.MyCreateShaderResourceView(&tas.pSRV, tas.pTexture);
	UpdateGrid();
}

void CPxaEditorDraw::ResetContext()
{
	view.Reset();
	if (tas.pSRV)
	{
		tas.pSRV->Release();
		tas.pSRV = nullptr;
	}
	if (tas.pTexture)
	{
		tas.pTexture->Release();
		tas.pTexture = nullptr;
	}
	Draw();
	view.Reset();
}

int CPxaEditorDraw::GetCopyPxa()
{
	auto parentEditor = (CPxaEditor*)pParentEditor;
	if (!parentEditor->IsLoaded())
		return 0;
	auto& step = *parentEditor->GetStep();
	if (step.find(MAKELONG(view.cursorX, view.cursorY)) == step.end())
		return 0;
	return step.at(MAKELONG(view.cursorX, view.cursorY));
}

void CPxaEditorDraw::SetCopyPxa(int pxa)
{
	auto parentEditor = (CPxaEditor*)pParentEditor;
	if (!parentEditor->IsLoaded())
		return;
	auto& step = *parentEditor->GetStep();
	step[MAKELONG(view.cursorX, view.cursorY)] = pxa;
}

void CPxaEditorDraw::UpdateGrid()
{
	if (!tas.pSRV)
		return;
	MyRect rc;
	pRenderer.GetRenderCopyDefaultRect(tas.pSRV, &rc, nullptr);
	float w = rc.GetWidth(), h = rc.GetHeight();
	view.count_w = (int)((int)w % (int)view.grid_w ? w / view.grid_w + 1 : w / view.grid_w);
	int count_h = (int)((int)h % (int)view.grid_h ? h / view.grid_h + 1 : h / view.grid_h);
	view.count_max = view.count_w * count_h;
	Draw();
}

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

BOOL CPxaEditorDraw::OnInitDialog()
{
	CDialog::OnInitDialog();
	//初始化渲染器
	pRenderer.Init(m_hWnd);
	view.Init(this, &pRenderer);
	//载入资源
	LoadResourceTexture(&pRenderer, IDR_PXATYPE, &tas_pxatype.pTexture, &tas_pxatype.pSRV);
	return 0;
}

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

	if (!view.pRenderer)
		return;
	view.window_w = (float)cx;
	view.window_h = (float)cy;
	pRenderer.OnSize(cx, cy, nType == SIZE_MINIMIZED);
}

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

void CPxaEditorDraw::OnLButtonDown(UINT nFlags, CPoint point)
{
	view.BeginSelect(point);
	Draw();
	CDialog::OnLButtonDown(nFlags, point);
}

void CPxaEditorDraw::OnLButtonUp(UINT nFlags, CPoint point)
{
	CDialog::OnLButtonUp(nFlags, point);
	auto parentEditor = (CPxaEditor*)pParentEditor;
	view.EndSelect();
	if (!parentEditor->IsLoaded())
		return;
	auto& viewBrush = *parentEditor->GetBrushView();
	auto& undoRedo = *parentEditor->GetMyUndoRedo();
	undoRedo.BeginStep(CPXAEDITOR_DATATYPE_PXA_STR);
	auto& step = *parentEditor->GetStep();
	for (int y = 0; y < view.cursorH_selected; y++)
		for (int x = 0; x < view.cursorW_selected; x++)
			step[MAKELONG(view.cursorX_selected + x, view.cursorY_selected + y)] =
			(viewBrush.cursorY_selected + y % viewBrush.cursorH_selected) * viewBrush.count_w +
			viewBrush.cursorX_selected + x % viewBrush.cursorW_selected;
	undoRedo.EndStep();
	parentEditor->Draw();
	parentEditor->UpdateWindowTitle();
	parentEditor->UpdateMenuState();
}

void CPxaEditorDraw::OnRButtonDown(UINT nFlags, CPoint point)
{
	view.WindowBind_OnRButtonDown(point);
	CDialog::OnRButtonDown(nFlags, point);
}


void CPxaEditorDraw::OnRButtonUp(UINT nFlags, CPoint point)
{
	view.WindowBind_OnRButtonUp();
	CDialog::OnRButtonUp(nFlags, point);
}

BOOL CPxaEditorDraw::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	if (view.WindowBind_OnMouseWheel(zDelta, pt))
		Draw();
	return CDialog::OnMouseWheel(nFlags, zDelta, pt);
}

void CPxaEditorDraw::OnMouseMove(UINT nFlags, CPoint point)
{
	view.Select(point);
	if (view.WindowBind_OnMouseMove(point))
		Draw();
	CDialog::OnMouseMove(nFlags, point);
}

void CPxaEditorDraw::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	
	if (view.WindowBind_OnVScroll(nSBCode, nPos))
		Draw();
	CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CPxaEditorDraw::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	
	if (view.WindowBind_OnHScroll(nSBCode, nPos))
		Draw();
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CPxaEditorDraw::DrawPxa()
{
	if (!tas_pxatype.pSRV)
		return;
	auto parentEditor = (CPxaEditor*)pParentEditor;
	auto& step = *parentEditor->GetStep();
	auto& viewBrush = *parentEditor->GetBrushView();
	MyViewDrawFor vFor;
	MyRect src, dst;
	vFor.Init(&view);
	int* pX = nullptr;
	int* pY = nullptr;
	pRenderer.SetTPenDraw(tas_pxatype.pSRV);
	for (vFor.DrawForYBegin(&pY); vFor.DrawForY(); vFor.DrawForYInc())
	{
		for (vFor.DrawForXBegin(&pX); vFor.DrawForX(&dst); vFor.DrawForXInc())
		{
			int& x = *pX;
			int& y = *pY;
			if (step.find(MAKELONG(x, y)) == step.end())
				continue;
			int pxa = step.at(MAKELONG(x, y));
			src.Set1((pxa % viewBrush.count_w) * viewBrush.grid_w,
				((float)(pxa / viewBrush.count_w) * viewBrush.grid_h),
				viewBrush.grid_w,
				viewBrush.grid_h);
			pRenderer.AddRenderCopy(&src, &dst, RGBA(0xff, 0xff, 0xff, 0x80));
		}
	}
	pRenderer.DrawRenderCopy();
}

