/////////////////////////////////////////////////
//
//  filename: MenuWindow.cpp
//  author:Chafumi Touji
//  date: 2020/06/03 ver1.00
//
/////////////////////////////////////////////////

#include "StdAfx.h"
#include "Main.h"
#include "Config.h"
#include "MenuWindow.h"
#include "MainWindow.h"
#include "DispWindow.h"
#include "DialogFileSelect.h"
#include "CustomButton.h"

CMenuWindow::CMenuWindow(){

	HDC screen = GetDC(0);
	dpiX = (float)GetDeviceCaps(screen, LOGPIXELSX);
	dpiY = (float)GetDeviceCaps(screen, LOGPIXELSY);
	ReleaseDC(0, screen);

	ScaleX = (dpiX / 96.0f);
	ScaleY = (dpiY / 96.0f);

	DisplayWidth = ::GetSystemMetrics(SM_CXSCREEN);
	DisplayHeight = ::GetSystemMetrics(SM_CYSCREEN);
	FrameEdgeX = 8;
	FrameEdgeY = 8;

	TransparentR = COLOR_TRANSPARENT_R;
	TransparentG = COLOR_TRANSPARENT_G;
	TransparentB = COLOR_TRANSPARENT_B;

	CRect	rectDesktop;
	::SystemParametersInfo(SPI_GETWORKAREA, 0, &rectDesktop, 0);

	Width = (int)((double)DisplayWidth / 1.5);
	Height = (int)((double)DisplayHeight / 1.5);
	TitleBarHeight = (int)((double)DisplayHeight / 30.0);
	TaskBarHeight = DisplayHeight - rectDesktop.bottom;

	BKColorA = 255;
	BKColorR = 180;
	BKColorG = 150;
	BKColorB = 150;
	TextColorA = 255;
	TextColorR = 240;
	TextColorG = 240;
	TextColorB = 240;

	PosX = 30;
	PosY = TitleBarHeight + 30;

	LButtonDown = false;
	DownPoint = CPoint(0, 0);
}

CMenuWindow::~CMenuWindow(){

}

bool CMenuWindow::SetParam(CConfig *config){

	wcscpy_s(Path, SIZE_CHAR_MAX, config->Path);
	BKColorR = config->MenuBKColorR;
	BKColorG = config->MenuBKColorG;
	BKColorB = config->MenuBKColorB;
	BKColorA = config->MenuBKColorA;
	TextColorR = config->MenuTextColorR;
	TextColorG = config->MenuTextColorG;
	TextColorB = config->MenuTextColorB;
	TextColorA = config->MenuTextColorA;

	return true;
}

bool CMenuWindow::GetParam(CConfig *config){

	return true;
}


bool CMenuWindow::CreateWnd( HWND ParentWnd, int x, int y, int w, int h ){

	SetParam(theApp->MainWindow->Config);

	WNDCLASSEX wcx;
	memset(&wcx, 0, sizeof(WNDCLASSEX));
	wcx.style = CS_HREDRAW | CS_VREDRAW;
	wcx.cbSize = sizeof(WNDCLASSEX);
	wcx.hInstance = NULL;
	wcx.hIcon = NULL;
	wcx.lpszMenuName = NULL;
	wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcx.lpfnWndProc = &CMenuWindow::WindowProc;
	wcx.lpszClassName = L"CLASS_MENUWINDOW";
	RegisterClassEx(&wcx);

	Width = w;
	Height = h;
	m_hWnd = CreateWindowEx(WS_EX_LEFT, L"CLASS_MENUWINDOW", _T("MenuWindow"), WS_CHILD | WS_CLIPCHILDREN, x, y, w, h, ParentWnd, NULL, NULL, NULL);
	::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (UINT_PTR) this);

	BitmapWidth = DisplayWidth;
	BitmapHeight = DisplayHeight;

	BITMAPINFO  bmi = { 0 };
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = BitmapWidth;
	bmi.bmiHeader.biHeight = BitmapHeight;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;

	MemBMP = CreateDIBSection(0, &bmi, DIB_RGB_COLORS, (void **)&AlphaBMP, 0, 0);
	::DeleteDC(MemDC);

	HDC hdc = ::GetDC(m_hWnd);
	MemDC = CreateCompatibleDC(hdc);
	::SelectObject(MemDC, MemBMP);
	DeleteDC(hdc);

	::ShowWindow(m_hWnd, SW_SHOW);

	int button_height = (int)((double)TitleBarHeight * 1.5f);
	int button_width = (int)(Width * 0.95f);
	x = (int)((double)( Width - button_width ) / 2.0f );
	y = (int)((double)TitleBarHeight * 0.5f);
	ButtonModelOpen = new CButtonModelOpen();
	ButtonModelOpen->CreateWnd(x, y, button_width, button_height, m_hWnd);
	ButtonModelOpen->SetImage(L"./pict/ButtonModelOpen.png", L"./pict/ButtonModelOpenDown.png");
	ButtonModelOpen->SetColor(BKColorA, BKColorR, BKColorG, BKColorB);

	y += button_height;
	ButtonModelWrite = new CButtonModelWrite();
	ButtonModelWrite->CreateWnd(x, y, button_width, button_height, m_hWnd);
	ButtonModelWrite->SetImage(L"./pict/ButtonModelWrite.png", L"./pict/ButtonModelWriteDown.png");
	ButtonModelWrite->SetColor(BKColorA, BKColorR, BKColorG, BKColorB);

	y += button_height;
	ButtonAnimOpen = new CButtonAnimOpen();
	ButtonAnimOpen->CreateWnd(x, y, button_width, button_height, m_hWnd);
	ButtonAnimOpen->SetImage(L"./pict/ButtonAnimOpen.png", L"./pict/ButtonAnimOpenDown.png");
	ButtonAnimOpen->SetColor(BKColorA, BKColorR, BKColorG, BKColorB);

	y += button_height;
	ButtonAnimWrite = new CButtonAnimWrite();
	ButtonAnimWrite->CreateWnd(x, y, button_width, button_height, m_hWnd);
	ButtonAnimWrite->SetImage(L"./pict/ButtonAnimWrite.png", L"./pict/ButtonAnimWriteDown.png");
	ButtonAnimWrite->SetColor(BKColorA, BKColorR, BKColorG, BKColorB);

	y += (int)(button_height * 1.5f);
	int box_height = (int)(Height - y - Height * 0.04f);
	AnimationListWnd = new CAnimationListWindow();
	AnimationListWnd->CreateWnd(m_hWnd, x, y, button_width, box_height, MemDC, MemBMP);


	return true;
}

LRESULT CMenuWindow::WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){

	CMenuWindow *menu_wnd = (CMenuWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
	if (menu_wnd != NULL)
		menu_wnd->MenuWindowProc(hwnd, message, wParam, lParam);

	return DefWindowProc(hwnd, message, wParam, lParam);
}

LRESULT CMenuWindow::MenuWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){

	int width = 0;
	int height = 0;
	int x = 0;
	int y = 0;
	int delta = 0;
	int key = 0;

	switch (message){
	case WM_PAINT:
		OnPaint();
		break;
	case WM_SIZE:
		width = GET_X_LPARAM(lParam);
		height = GET_Y_LPARAM(lParam);
		OnSize((UINT)wParam, width, height);
		break;
	case WM_LBUTTONDOWN:
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		OnLButtonDown((UINT)wParam, CPoint(x, y));
		break;
	case WM_LBUTTONUP:
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		OnLButtonUp((UINT)wParam, CPoint(x, y));
		break;
	case WM_RBUTTONDOWN:
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		OnRButtonDown((UINT)wParam, CPoint(x, y));
		break;
	case WM_RBUTTONUP:
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		OnRButtonUp((UINT)wParam, CPoint(x, y));
		break;
	case WM_MOUSEMOVE:
		::SetFocus(m_hWnd);
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		OnMouseMove((UINT)wParam, CPoint(x, y));
		break;
	case WM_MOUSEWHEEL:
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		key = GET_KEYSTATE_WPARAM(wParam);
		delta = GET_WHEEL_DELTA_WPARAM(wParam);
		OnMouseWheel(key, delta, CPoint(x, y));
		break;
	case WM_KEYDOWN:
		OnKeyDown((UINT)wParam);
		break;
	default:
		break;
	}

	return 0;
}

void CMenuWindow::OnKeyDown(UINT nChar){

	if (nChar == 32 /* enter */){
	}
}

void CMenuWindow::OnSize(UINT nType, int cx, int cy){

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

void CMenuWindow::OnPaint(){

	PAINTSTRUCT ps;
	HDC hdc = ::BeginPaint(m_hWnd, &ps);
	OnDraw(hdc);
	::EndPaint(m_hWnd, &ps);
}

bool CMenuWindow::OnDraw(HDC hdc){

	HBITMAP OldBmp = (HBITMAP)::SelectObject(MemDC, MemBMP);

	int width = Width;
	int height = Height;

	Gdiplus::Graphics *gfc = new Gdiplus::Graphics(MemDC);
	gfc->Clear(Gdiplus::Color(255, BKColorR, BKColorG, BKColorB));

	Gdiplus::SolidBrush *brush1 = new Gdiplus::SolidBrush(Gdiplus::Color(BKColorA, BKColorR, BKColorG, BKColorB));
	gfc->FillRectangle(brush1, 0, 0, width, TitleBarHeight);
	delete brush1;

	Gdiplus::Pen *pen1 = new Gdiplus::Pen(Gdiplus::Color(BKColorA, BKColorR, BKColorG, BKColorB), 8);
	gfc->DrawLine(pen1, 0, 0, Width, 0);
	gfc->DrawLine(pen1, width, 0, width, height);
	gfc->DrawLine(pen1, width, height, 0, height);
	gfc->DrawLine(pen1, 0, height, 0, 0);
	delete pen1;

	gfc->SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
	Gdiplus::Font *font = new Gdiplus::Font(L"メイリオ", (REAL)((double)TitleBarHeight * 0.5f / ScaleX));

	ButtonModelOpen->OnDraw(MemDC, ButtonModelOpen->PosX, ButtonModelOpen->PosY, ButtonModelOpen->Width, ButtonModelOpen->Height);
	ButtonModelWrite->OnDraw(MemDC, ButtonModelWrite->PosX, ButtonModelWrite->PosY, ButtonModelWrite->Width, ButtonModelWrite->Height);
	ButtonAnimOpen->OnDraw(MemDC, ButtonAnimOpen->PosX, ButtonAnimOpen->PosY, ButtonAnimOpen->Width, ButtonAnimOpen->Height);
	ButtonAnimWrite->OnDraw(MemDC, ButtonAnimWrite->PosX, ButtonAnimWrite->PosY, ButtonAnimWrite->Width, ButtonAnimWrite->Height);

	::BitBlt(hdc, 0, 0, width, height, MemDC, 0, 0, SRCCOPY);

	delete font;
	delete gfc;

	return true;
}

void CMenuWindow::OnLButtonDown(UINT nFlag, CPoint point){

	LButtonDown = true;

	::ClientToScreen(m_hWnd, &point);
	DownPoint = point;
	LButtonDown = true;
	::SetCapture(m_hWnd);

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

void CMenuWindow::OnRButtonDown(UINT nFlag, CPoint point){

	RButtonDown = true;

	::ClientToScreen(m_hWnd, &point);
	DownPoint = point;
	RButtonDown = true;
	::SetCapture(m_hWnd);

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

void CMenuWindow::OnLButtonUp(UINT nFlag, CPoint point){

	::ReleaseCapture();
	LButtonDown = false;

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

void CMenuWindow::OnRButtonUp(UINT nFlag, CPoint point){

	::ReleaseCapture();
	RButtonDown = false;

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

void CMenuWindow::OnMouseMove(UINT nFlag, CPoint point){

	::ClientToScreen(m_hWnd, &point);

	if (RButtonDown == true){
		int move_x = point.x - DownPoint.x;
		int move_y = point.y - DownPoint.y;
	}
	else if (LButtonDown == true){
		int move_x = point.x - DownPoint.x;
		int move_y = point.y - DownPoint.y;
	}

	DownPoint = point;

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

void CMenuWindow::OnMouseWheel(UINT nFlag, int zDelta, CPoint point){

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

///////////////////////////////////////////////////////////////////////////

CAnimationListWindow::CAnimationListWindow(){

	HDC screen = GetDC(0);
	dpiX = (float)GetDeviceCaps(screen, LOGPIXELSX);
	dpiY = (float)GetDeviceCaps(screen, LOGPIXELSY);
	ReleaseDC(0, screen);

	ScaleX = (dpiX / 96.0f);
	ScaleY = (dpiY / 96.0f);

	DisplayWidth = ::GetSystemMetrics(SM_CXSCREEN);
	DisplayHeight = ::GetSystemMetrics(SM_CYSCREEN);


	LButtonDown = false;
	DownPoint = CPoint(0, 0);
	ItemCount = 0;
	SelectedNum = -1;
}

CAnimationListWindow::~CAnimationListWindow(){
}

bool CAnimationListWindow::SetParam(CConfig *config){

	BKColorA = config->BKColorA;
	BKColorR = config->BKColorR;
	BKColorG = config->BKColorG;
	BKColorB = config->BKColorB;
	TextColorA = config->TextColorA;
	TextColorR = config->TextColorR;
	TextColorG = config->TextColorG;
	TextColorB = config->TextColorB;

	return true;
}

bool CAnimationListWindow::CreateWnd(HWND ParentWnd, int x, int y, int w, int h, HDC memDC, HBITMAP bitmap){

	SetParam(theApp->MainWindow->Config);

	WNDCLASSEX wcx;
	memset(&wcx, 0, sizeof(WNDCLASSEX));
	wcx.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
	wcx.cbSize = sizeof(WNDCLASSEX);
	wcx.hInstance = NULL;
	wcx.hIcon = NULL;
	wcx.lpszMenuName = NULL;
	wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcx.lpfnWndProc = &CAnimationListWindow::WindowProc;
	wcx.lpszClassName = L"CLASS_ANIMATIONLISTWINDOW";
	RegisterClassEx(&wcx);

	PosX = x;
	PosY = y;
	Width = w;
	Height = h;
	m_hWnd = CreateWindowEx(WS_EX_COMPOSITED, L"CLASS_ANIMATIONLISTWINDOW", _T("animation list"), WS_CHILD | WS_CLIPCHILDREN, PosX, PosY, Width, Height, ParentWnd, NULL, NULL, NULL);
	::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (UINT_PTR) this);

	int scroll_width = (int)(Width * 0.05f);
	int scroll_height = Height;
	int scroll_pos_x = Width - scroll_width;
	int scroll_pos_y = 0;
	ItemHeight = (int)((float)Height / (float)ANIMATION_LIST_DISP_NUM);
	ItemCountMax = SELECT_LIST_ITEM_DISP_NUM;
	ItemBegin = 0;
	IconSize = (int)(ItemHeight / ScaleX);

	ScrollV = new CScrollBar();
	ScrollV->CreateWnd(m_hWnd, scroll_pos_x, scroll_pos_y, scroll_width, scroll_height, memDC, bitmap);

	MemDC = memDC;
	MemBMP = bitmap;

	::ShowWindow(m_hWnd, SW_SHOW);

	return true;
}

LRESULT CAnimationListWindow::WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){

	CAnimationListWindow *select_list = (CAnimationListWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
	if (select_list != NULL)
		select_list->AnimationListWindowProc(hwnd, message, wParam, lParam);

	return DefWindowProc(hwnd, message, wParam, lParam);
}

LRESULT CAnimationListWindow::AnimationListWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){

	int width = 0;
	int height = 0;
	int x = 0;
	int y = 0;
	int delta = 0;
	int key = 0;

	switch (message){
	case WM_PAINT:
		OnPaint();
		break;
	case WM_SIZE:
		width = GET_X_LPARAM(lParam);
		height = GET_Y_LPARAM(lParam);
		OnSize((UINT)wParam, width, height);
		break;
	case WM_LBUTTONDOWN:
		SetFocus(m_hWnd);
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		OnLButtonDown((UINT)wParam, CPoint(x, y));
		break;
	case WM_LBUTTONUP:
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		OnLButtonUp((UINT)wParam, CPoint(x, y));
		break;
	case WM_MOUSEMOVE:
		SetFocus(m_hWnd);
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		OnMouseMove((UINT)wParam, CPoint(x, y));
		break;
	case WM_MOUSEWHEEL:
		SetFocus(m_hWnd);
		x = GET_X_LPARAM(lParam);
		y = GET_Y_LPARAM(lParam);
		key = GET_KEYSTATE_WPARAM(wParam);
		delta = GET_WHEEL_DELTA_WPARAM(wParam);
		OnMouseWheel(key, delta, CPoint(x, y));
		break;
	default:
		break;
	}

	return 0;
}

void CAnimationListWindow::OnSize(UINT nType, int cx, int cy){

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

void CAnimationListWindow::OnPaint(){

	PAINTSTRUCT ps;
	HDC hdc = ::BeginPaint(m_hWnd, &ps);
	OnDraw(hdc);
	::EndPaint(m_hWnd, &ps);
}

bool CAnimationListWindow::OnDraw(HDC hdc){

	HBITMAP OldBmp = (HBITMAP)::SelectObject(MemDC, MemBMP);

	Gdiplus::Graphics *gfc = new Gdiplus::Graphics(MemDC);
	gfc->Clear(Gdiplus::Color(BKColorA, BKColorR - 20, BKColorG - 20, BKColorB - 20));

	DrawItem(gfc);

	::BitBlt(hdc, 0, 0, Width, Height, MemDC, 0, 0, SRCCOPY);

	delete gfc;

	return true;
}

bool CAnimationListWindow::DrawItem(Gdiplus::Graphics *gfc){

	Gdiplus::SolidBrush *brush = new Gdiplus::SolidBrush(Gdiplus::Color(TextColorA, TextColorR, TextColorG, TextColorB));
	Gdiplus::SolidBrush *brush1 = new Gdiplus::SolidBrush(Gdiplus::Color(BKColorA, BKColorR, BKColorG, BKColorB));
	Gdiplus::SolidBrush *brush2 = new Gdiplus::SolidBrush(Gdiplus::Color(BKColorA, BKColorR-20, BKColorG-20, BKColorB-20));

	Gdiplus::Font *font = new Gdiplus::Font(L"メイリオ", (REAL)((double)ItemHeight * 0.6f / ScaleX));
	Gdiplus::StringFormat *format = new Gdiplus::StringFormat(StringFormatFlagsNoWrap);

	gfc->FillRectangle(brush1, 0, 0, Width, Height );

	int item_count = (int) theApp->MainWindow->DispWindow->ChaResourceObject->AnimationList->PushPos;
	for (int i = 0; i <= item_count - 1; i++){

		wchar_t name[SIZE_CHAR_MAX];
		wmemset(name, 0, SIZE_CHAR_MAX);
		CAnimation *anim = *(CAnimation **) theApp->MainWindow->DispWindow->ChaResourceObject->AnimationList->GetData(i);
		wcscpy_s(name, SIZE_CHAR_MAX, anim->AnimatonID);

		int pos_x = ItemHeight;
		int pos_y = ItemHeight * i;

		if (i == SelectedNum)
			gfc->FillRectangle(brush2, 0, pos_y, Width, ItemHeight);

		gfc->DrawString(name, -1, font, RectF((REAL)pos_x, (REAL)pos_y, (REAL)Width, (REAL)ItemHeight ), format, brush);
	}

	ScrollV->BarHeight = (int)(Height * (float)SELECT_LIST_ITEM_DISP_NUM / (float)item_count);

	if (item_count > SELECT_LIST_ITEM_DISP_NUM)
		::ShowWindow(ScrollV->m_hWnd, SW_SHOW);
	else
		::ShowWindow(ScrollV->m_hWnd, SW_HIDE);

	delete brush;
	delete brush1;
	delete brush2;
	delete font;
	delete format;

	return true;
}

void CAnimationListWindow::OnLButtonDown(UINT nFlag, CPoint point){

	LButtonDown = true;

	int pos_x = point.x;
	int pos_y = point.y;

	/////////////////////////////////////////////////////////

	SelectedNum = SelectItem(point);
	theApp->MainWindow->DispWindow->ChaResourceObject->SetCurrentAnimation(SelectedNum, 15, 1, true);

	::ClientToScreen(m_hWnd, &point);
	DownPoint = point;
	LButtonDown = true;

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

int CAnimationListWindow::SelectItem(CPoint point){

	int selected_count = ItemBegin + point.y / ItemHeight;

	return selected_count;
}

void CAnimationListWindow::OnLButtonUp(UINT nFlag, CPoint point){

	LButtonDown = false;

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}

void CAnimationListWindow::OnMouseMove(UINT nFlag, CPoint point){

	if (LButtonDown == true){
		::ClientToScreen(m_hWnd, &point);
		int pos_x = point.x - DownPoint.x;
		int pos_y = point.y - DownPoint.y;
		DownPoint = point;

		::InvalidateRect(m_hWnd, NULL, false);
		::UpdateWindow(m_hWnd);
	}
}

void CAnimationListWindow::OnMouseWheel(UINT nFlag, int zDelta, CPoint point){

	if (ScrollV->BarHeight < ScrollV->Height){

		ScrollV->BarPosY -= (int)(zDelta * 0.1f);
		if (ScrollV->BarPosY < 0)
			ScrollV->BarPosY = 0;
		if (ScrollV->BarPosY > ScrollV->Height - ScrollV->BarHeight)
			ScrollV->BarPosY = ScrollV->Height - ScrollV->BarHeight;

		ScrollV->UpdateScrollBar();
	}

	::InvalidateRect(m_hWnd, NULL, false);
	::UpdateWindow(m_hWnd);
}
