#include "StdAfx.h"
#include "ScrCaptureWnd.h"
#include "Canvas.h"
#include "CanvasContainer.h"
#include "Util.h"

CScrCaptureWnd* CScrCaptureWnd::m_pInstance = NULL;

class CDialogBuilderCallbackEx : public IDialogBuilderCallback
{
public:
	CControlUI* CreateControl(LPCTSTR pstrClass) 
	{
		if( _tcscmp(pstrClass, DUI_CTR_CANVAS) == 0 ) return new CCanvasUI;
		else if( _tcscmp(pstrClass, DUI_CTR_CANVASCONTAINER) == 0 ) return new CCanvasContainerUI;
		return NULL;
	}
};

CScrCaptureWnd::CScrCaptureWnd() : m_hEditMenu(NULL), m_bClipChoiced(false)
{
	m_ptClipBasePoint.x = m_ptClipBasePoint.y = 0;
	::ZeroMemory(&m_rcWindow, sizeof(m_rcWindow));
	::ZeroMemory(&m_rcClipPadding, sizeof(m_rcClipPadding));
	::ZeroMemory(m_sClipDrawStringBuf, sizeof(m_sClipDrawStringBuf));
};

CScrCaptureWnd::~CScrCaptureWnd() 
{
	::DestroyMenu(m_hEditMenu);
}

CScrCaptureWnd* CScrCaptureWnd::Instance() 
{
	if (m_pInstance == NULL) m_pInstance = new CScrCaptureWnd;
	return m_pInstance;
}

LPCTSTR CScrCaptureWnd::GetWindowClassName() const
{
	return _T("UIScrCaptureFrame");
}

UINT CScrCaptureWnd::GetClassStyle() const 
{
	return UI_CLASSSTYLE_DIALOG | CS_DBLCLKS;
}

void CScrCaptureWnd::OnFinalMessage(HWND /*hWnd*/)
{
	delete this; 
};

void CScrCaptureWnd::Init() 
{
	m_hEditMenu = ::CreatePopupMenu();
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_ADDRECTANGE, _T("添加矩形"));
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_ADDELLIPSE, _T("添加椭圆"));
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_ADDARROW, _T("添加箭头"));
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_ADDBRUSH, _T("添加画刷工具"));
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_ADDTEXT, _T("添加文字"));
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_UNDO, _T("撤销编辑"));
	::AppendMenu(m_hEditMenu, MF_SEPARATOR, 0, NULL);
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_RECHOICE, _T("重新选择截图区域"));
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_SAVEANDQUIT, _T("复制并退出截图"));
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_SAVE, _T("保存"));
	::AppendMenu(m_hEditMenu, MF_SEPARATOR, 0, NULL);
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_HIDETOOLBAR, _T("隐藏编辑工具栏"));
	::AppendMenu(m_hEditMenu, MF_STRING, MENUCMD_QUIT, _T("退出截屏"));

	m_pDesktopImage = m_pm.FindControl(_T("desktopimage"));
	m_pDesktopMask = m_pm.FindControl(_T("desktopmask"));
	m_pDesktopMaskBorder = m_pm.FindControl(_T("desktopmaskborder"));
	m_pDesktopCanvasContainer = static_cast<CContainerUI*>(m_pm.FindControl(_T("desktopcanvascontainer")));
	if (m_pDesktopImage == NULL || m_pDesktopMask == NULL ||
		m_pDesktopMaskBorder == NULL || m_pDesktopCanvasContainer == NULL) ::PostQuitMessage(0L);

	::GetWindowRect(::GetDesktopWindow(), &m_rcWindow);
	::SetWindowPos(GetHWND(), NULL, m_rcWindow.left, m_rcWindow.top, m_rcWindow.right-m_rcWindow.left, m_rcWindow.bottom-m_rcWindow.top, SWP_NOZORDER);

	HBITMAP hDesktopBmp = CreateDesktopBitmap(GetHWND());
	m_pm.AddImage(_T("desktopimage"), hDesktopBmp, m_rcWindow.right-m_rcWindow.left, m_rcWindow.bottom-m_rcWindow.top, false);
	HBITMAP hDesktopBmpMask = CreateDesktopMaskBitmap(GetHWND());
	m_pm.AddImage(_T("desktopimagemask"), hDesktopBmpMask, m_rcWindow.right-m_rcWindow.left, m_rcWindow.bottom-m_rcWindow.top, true);

	m_pDesktopImage->SetBkImage(_T("desktopimage"));
	m_pDesktopMask->SetBkImage(_T("desktopimagemask"));
}

void CScrCaptureWnd::OnPrepare() 
{
}

void CScrCaptureWnd::Notify(TNotifyUI& msg)
{
	if( msg.sType == _T("windowinit") ) {
		OnPrepare();
	}
	else if( msg.sType == _T("click") ) {
	}
}

RECT CScrCaptureWnd::GetWindowRect() const
{
	return m_rcWindow;
}

RECT CScrCaptureWnd::GetClipPadding() const
{
	return m_rcClipPadding;
}

void CScrCaptureWnd::SetClipPadding(RECT rc) {
	m_rcClipPadding = rc;
	_stprintf_s(m_sClipDrawStringBuf, MAX_PATH - 1, _T("file='desktopimagemask' scale9='%d,%d,%d,%d' hole='true'"),
		m_rcClipPadding.left, m_rcClipPadding.top, m_rcClipPadding.right, m_rcClipPadding.bottom);
	m_pDesktopMask->SetBkImage(m_sClipDrawStringBuf);
	m_pDesktopMaskBorder->SetPos(GetClipRect());
	m_pDesktopCanvasContainer->SetPos(GetCanvasContainerRect());
}

RECT CScrCaptureWnd::GetClipRect() const
{
	RECT rc = m_rcClipPadding;
	rc.left = rc.left+m_rcWindow.left;
	rc.top = rc.top+m_rcWindow.top;
	rc.right = m_rcWindow.right-rc.right;
	rc.bottom = m_rcWindow.bottom-rc.bottom;
	return rc;
}

RECT CScrCaptureWnd::GetCanvasContainerRect() const
{
	RECT rcInset = m_pDesktopCanvasContainer->GetInset();
	RECT rc = m_rcClipPadding;
	rc.left = rc.left+m_rcWindow.left-rcInset.left;
	rc.top = rc.top+m_rcWindow.top-rcInset.left;
	rc.right = m_rcWindow.right-rc.right+rcInset.left;
	rc.bottom = m_rcWindow.bottom-rc.bottom+rcInset.left;
	return rc;
}

LRESULT CScrCaptureWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
	if( uMsg == WM_KEYDOWN ) {
		if( wParam == VK_ESCAPE ) {
			PostQuitMessage(0);
			return true;
		}

	}
	return false;
}

LRESULT CScrCaptureWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if( uMsg == WM_CREATE ) {
		m_pm.Init(m_hWnd);
		m_pm.AddPreMessageFilter(this);
		CDialogBuilder builder;
		CDialogBuilderCallbackEx cb;
		CControlUI* pRoot = builder.Create(_T("ScrCapture.xml"), (UINT)0, &cb, &m_pm);
		ASSERT(pRoot && "Failed to parse XML");
		m_pm.AttachDialog(pRoot);
		m_pm.AddNotifier(this);
		Init();
		return 0;
	}
	else if( uMsg == WM_DESTROY ) {
		::PostQuitMessage(0L);
	}
	else if(uMsg == WM_LBUTTONDOWN) {
		if (!m_bClipChoiced) {
			m_pDesktopCanvasContainer->SetEnabled(false);
			m_ptClipBasePoint.x = GET_X_LPARAM(lParam);
			m_ptClipBasePoint.y = GET_Y_LPARAM(lParam);
			return 0;
		}
	}
	else if(uMsg == WM_LBUTTONUP) {
		if (!m_bClipChoiced) {
			m_bClipChoiced = true;
			m_pDesktopMaskBorder->SetVisible(false);
			m_pDesktopCanvasContainer->SetVisible(true);
			m_pDesktopCanvasContainer->SetEnabled(true);
			SetClipPadding(m_rcClipPadding);
			return 0;
		}
		else {

		}
	}
	else if(uMsg == WM_LBUTTONDBLCLK) {
		// todo:完成截图，保存到剪贴板
		m_bClipChoiced = true;
		::PostQuitMessage(0L);
		return 0;
	}
	else if(uMsg == WM_RBUTTONUP) {
		if (m_bClipChoiced) {
			POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
			RECT rcClipRect = GetClipRect();
			if (::PtInRect(&rcClipRect, pt)) {
				::ClientToScreen(m_hWnd, &pt);
				::TrackPopupMenu(m_hEditMenu, TPM_TOPALIGN, pt.x, pt.y, 0, m_hWnd, NULL);
				::PostMessage(m_hWnd, WM_NULL, 0, 0);
			}
			else {
				m_bClipChoiced = false;
				m_pDesktopCanvasContainer->SetEnabled(false);
				::SendMessage(m_hWnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt.x, pt.y));
			}
		}
		else {
			// 退出截图
			::PostQuitMessage(0L);
		}
		return 0;
	}
	else if(uMsg == WM_MOUSEMOVE) {
		if (!m_bClipChoiced) {
			if( ::GetKeyState(VK_LBUTTON) < 0 ) { // 左键按下状态
				if (m_ptClipBasePoint.x != GET_X_LPARAM(lParam) || m_ptClipBasePoint.y != GET_Y_LPARAM(lParam)) {
					m_rcClipPadding.left = min(GET_X_LPARAM(lParam), m_ptClipBasePoint.x)-m_rcWindow.left; if (m_rcClipPadding.left < 0) m_rcClipPadding.left = 0;
					m_rcClipPadding.top = min(GET_Y_LPARAM(lParam), m_ptClipBasePoint.y)-m_rcWindow.top; if (m_rcClipPadding.top < 0) m_rcClipPadding.top = 0;
					m_rcClipPadding.right = m_rcWindow.right-max(GET_X_LPARAM(lParam), m_ptClipBasePoint.x); if (m_rcClipPadding.right < 0) m_rcClipPadding.right = 0;
					m_rcClipPadding.bottom = m_rcWindow.bottom-max(GET_Y_LPARAM(lParam), m_ptClipBasePoint.y); if (m_rcClipPadding.bottom < 0) m_rcClipPadding.bottom = 0;
					m_pDesktopMaskBorder->SetVisible(false);
					m_pDesktopCanvasContainer->SetVisible(true);
					SetClipPadding(m_rcClipPadding);
				}
			}
			else {
				RECT rc;
				HWND hWnd;
				::EnableWindow(m_hWnd, FALSE);
				hWnd = SmallestWindowFromCursor(rc);
				::EnableWindow(m_hWnd, TRUE);
				::SetFocus(m_hWnd);
				rc.left = rc.left-m_rcWindow.left; if (rc.left < 0) rc.left = 0;
				rc.top = rc.top-m_rcWindow.top; if (rc.top < 0) rc.top = 0;
				rc.right = m_rcWindow.right-rc.right; if (rc.right < 0) rc.right = 0;
				rc.bottom = m_rcWindow.bottom-rc.bottom; if (rc.bottom < 0) rc.bottom = 0;
				if (rc.left != m_rcClipPadding.left || rc.right != m_rcClipPadding.right || rc.top != m_rcClipPadding.top || rc.bottom != m_rcClipPadding.bottom) {
					SetClipPadding(rc);
					m_pDesktopMaskBorder->SetVisible(true);
					m_pDesktopCanvasContainer->SetVisible(false);
				}
			}
		}
		else {

		}
	}
	else if(uMsg == WM_COMMAND) {
		switch (LOWORD(wParam)) 
		{ 
		case MENUCMD_ADDRECTANGE:
			return 0;
		case MENUCMD_ADDELLIPSE:
			return 0;
		case MENUCMD_ADDARROW:
			return 0;
		case MENUCMD_ADDBRUSH:
			return 0;
		case MENUCMD_ADDTEXT:
			return 0;
		case MENUCMD_UNDO:
			return 0;
		case MENUCMD_RECHOICE:
			{
				m_bClipChoiced = false;
				m_pDesktopCanvasContainer->SetEnabled(false);
				POINT pt;
				::GetCursorPos(&pt);
				::SendMessage(m_hWnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt.x, pt.y));
			}
			return 0;
		case MENUCMD_SAVEANDQUIT:
			{
				// todo:
				PostQuitMessage(0L);
			}
			return 0;
		case MENUCMD_SAVE:
			{
				// todo:弹出保存对话框
			}
			return 0;
		case MENUCMD_HIDETOOLBAR:
			return 0;
		case MENUCMD_QUIT:
			PostQuitMessage(0L);
			return 0;
		}
	}
	LRESULT lRes = 0;
	if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes;
	return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
}
