#include "../commonheaders.h"

extern HINSTANCE g_hInst;
HANDLE hStatusBarShowToolTipEvent,hStatusBarHideToolTipEvent;
boolean canloadstatusbar = FALSE;
HWND helperhwnd = 0;
HANDLE hFrameHelperStatusBar;

void CluiProtocolStatusChanged(int parStatus, const char* szProto);

INT_PTR GetConnectingIconService (WPARAM wParam,LPARAM lParam);

int RecreateStatusBar(HWND);
int UseOwnerDrawStatusBar;

#define TM_STATUSBAR 23435234
#define TM_STATUSBARHIDE 23435235
boolean tooltipshoing;
WNDPROC OldWindowProc = NULL;


POINT lastpnt;
RECT OldRc = {0};
static	HBITMAP hBmpBackground;
static int backgroundBmpUse;
static COLORREF bkColour;
extern BYTE showOpts;
int extraspace;

int OnStatusBarBackgroundChange()
{
	{	
		DBVARIANT dbv;
		showOpts = DBGetContactSettingByte(NULL,"CLUI","SBarShow",1);		
		bkColour = DBGetContactSettingDword(NULL,"StatusBar","BkColour",CLCDEFAULT_BKCOLOUR);
		if (hBmpBackground) {DeleteObject(hBmpBackground); hBmpBackground = NULL;}
		if (DBGetContactSettingByte(NULL,"StatusBar","UseBitmap",CLCDEFAULT_USEBITMAP)) {
			if (!DBGetContactSettingString(NULL,"StatusBar","BkBitmap",&dbv)) {
				hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
				mir_free(dbv.pszVal);
			}
		}
		backgroundBmpUse = DBGetContactSettingWord(NULL,"StatusBar","BkBmpUse",CLCDEFAULT_BKBMPUSE);
		extraspace = DBGetContactSettingDword(NULL,"StatusBar","BkExtraSpace",0);
	}

	RecreateStatusBar(pcli->hwndContactList);
	if (pcli->hwndStatus) InvalidateRect(pcli->hwndStatus,NULL,TRUE);
	return 0;
}


void DrawDataForStatusBar(LPDRAWITEMSTRUCT dis)
{
	//LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
	ProtocolData *PD = (ProtocolData *)dis->itemData;
	char *szProto = (char*)dis->itemData;
	int status,x;
	SIZE textSize;
	boolean NeedDestroy = FALSE;
	HICON hIcon;
	HRGN  hrgn;


	if (PD == NULL){return;}					
	if (dis->hDC == NULL) {return;}

	//clip it

	hrgn = CreateRectRgn(dis->rcItem.left, dis->rcItem.top, 
		dis->rcItem.right, dis->rcItem.bottom); 

	SelectClipRgn(dis->hDC, hrgn);

	szProto = PD->RealName;
#ifdef _DEBUG
	{
		//char buf[512];
		//sprintf(buf,"proto: %s draw at pos: %d\r\n",szProto,dis->rcItem.left);
		//OutputDebugStringA(buf);
	}
#endif

	status = CallProtoService(szProto,PS_GETSTATUS,0,0);
	SetBkMode(dis->hDC,TRANSPARENT);
	x = dis->rcItem.left+extraspace;

	if (showOpts&1) 
    {
		if ((DBGetContactSettingByte(NULL,"CLUI","UseConnectingIcon",1) == 1) && status < ID_STATUS_OFFLINE)
		{
			hIcon = (HICON)GetConnectingIconService((WPARAM)szProto,0);

			if (hIcon)
			{
				NeedDestroy = TRUE;
			}else
			{
				hIcon = LoadSkinnedProtoIcon(szProto,status);
			}

		}else					
		{				
			hIcon = LoadSkinnedProtoIcon(szProto,status);
		}
		DrawIconEx(dis->hDC,x,(dis->rcItem.top+dis->rcItem.bottom-GetSystemMetrics(SM_CYSMICON))>>1,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
		if (NeedDestroy) DestroyIcon(hIcon);
		x += GetSystemMetrics(SM_CXSMICON)+2;
	}
	else x += 2;
	if (showOpts&2) {
		TCHAR szName[64];

		PROTOACCOUNT* pa = ProtoGetAccount(szProto);
		mir_sntprintf(szName, SIZEOF(szName), _T("%s%s"), pa->tszAccountName, showOpts&4 ? _T(" ") : _T(""));
		GetTextExtentPoint32(dis->hDC, szName, (int)_tcslen(szName), &textSize);

		TextOut(dis->hDC,x,(dis->rcItem.top+dis->rcItem.bottom-textSize.cy)>>1,szName,lstrlen(szName));
		x += textSize.cx;
	}
	if (showOpts&4) {
		TCHAR *szStatus = pcli->pfnGetStatusModeDescription(status, 0);
		if (!szStatus)
			szStatus = _T("");
		GetTextExtentPoint32(dis->hDC,szStatus,lstrlen(szStatus),&textSize);
		TextOut(dis->hDC,x,(dis->rcItem.top+dis->rcItem.bottom-textSize.cy)>>1,szStatus,lstrlen(szStatus));
	}
	SelectClipRgn(dis->hDC, NULL);
	DeleteObject(hrgn);
}

void DrawBackGround(HWND hwnd,HDC mhdc)
{
	HDC hdcMem,hdc;
	RECT clRect,*rcPaint;

	int yScroll = 0;
	int y;
	PAINTSTRUCT paintst = {0};
	HBITMAP hBmpOsb,holdbmp;
	DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
	int grey = 0;
	HFONT oFont;
	HBRUSH hBrushAlternateGrey = NULL;

	HFONT hFont;

	//InvalidateRect(hwnd,0,FALSE);

	hFont = (HFONT)SendMessage(hwnd,WM_GETFONT,0,0);

	if (mhdc)
	{
		hdc = mhdc;
		rcPaint = NULL;
	}else
	{
		hdc = BeginPaint(hwnd,&paintst);
		rcPaint = &(paintst.rcPaint);
	}

	GetClientRect(hwnd,&clRect);
	if (rcPaint == NULL) rcPaint = &clRect;
	if (rcPaint->right-rcPaint->left == 0||rcPaint->top-rcPaint->bottom == 0) rcPaint = &clRect;
	y = -yScroll;
	hdcMem = CreateCompatibleDC(hdc);
	hBmpOsb = CreateBitmap(clRect.right,clRect.bottom,1,GetDeviceCaps(hdc,BITSPIXEL),NULL);
	holdbmp = (HBITMAP)SelectObject(hdcMem,hBmpOsb);
	oFont = (HFONT)SelectObject(hdcMem,hFont);
	SetBkMode(hdcMem,TRANSPARENT);
	{	HBRUSH hBrush,hoBrush;

	hBrush = CreateSolidBrush(bkColour);
	hoBrush = (HBRUSH)SelectObject(hdcMem,hBrush);
	FillRect(hdcMem,rcPaint,hBrush);
	SelectObject(hdcMem,hoBrush);
	DeleteObject(hBrush);
	if (hBmpBackground) {
		BITMAP bmp;
		int x,y;
		int maxx,maxy;
		int destw,desth;

		GetObject(hBmpBackground,sizeof(bmp),&bmp);
		HDC hdcBmp = CreateCompatibleDC(hdcMem);
		HDC holdbackbmp = (HDC)SelectObject(hdcBmp,hBmpBackground);
		y = backgroundBmpUse&CLBF_SCROLL?-yScroll:0;
		maxx = backgroundBmpUse&CLBF_TILEH?clRect.right:1;
		maxy = backgroundBmpUse&CLBF_TILEV?maxy = rcPaint->bottom:y+1;
		switch(backgroundBmpUse&CLBM_TYPE) {
		case CLB_STRETCH:
			if (backgroundBmpUse&CLBF_PROPORTIONAL) {
				if (clRect.right*bmp.bmHeight<clRect.bottom*bmp.bmWidth) {
					desth = clRect.bottom;
					destw = desth*bmp.bmWidth/bmp.bmHeight;
				}
				else {
					destw = clRect.right;
					desth = destw*bmp.bmHeight/bmp.bmWidth;
				}
			}
			else {
				destw = clRect.right;
				desth = clRect.bottom;
			}
			break;
		case CLB_STRETCHH:
			if (backgroundBmpUse&CLBF_PROPORTIONAL) {
				destw = clRect.right;
				desth = destw*bmp.bmHeight/bmp.bmWidth;
			}
			else {
				destw = clRect.right;
				desth = bmp.bmHeight;
			}
			break;
		case CLB_STRETCHV:
			if (backgroundBmpUse&CLBF_PROPORTIONAL) {
				desth = clRect.bottom;
				destw = desth*bmp.bmWidth/bmp.bmHeight;
			}
			else {
				destw = bmp.bmWidth;
				desth = clRect.bottom;
			}
			break;
		default:    //clb_topleft
			destw = bmp.bmWidth;
			desth = bmp.bmHeight;
			break;
		}
		desth = clRect.bottom -clRect.top;
		for (;y<maxy;y += desth) {
			if (y<rcPaint->top-desth) continue;
			for (x = 0;x<maxx;x += destw)
				StretchBlt(hdcMem,x,y,destw,desth,hdcBmp,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
		}
		SelectObject(hdcBmp,holdbackbmp);
		DeleteDC(hdcBmp);
	}
	}

	//call to draw icons
	{
		DRAWITEMSTRUCT ds;
		int nParts,nPanel;
		ProtocolData *PD;
		RECT rc,clrc;
		int startoffset,sectwidth;

		memset(&ds,0,sizeof(ds));
		ds.hwndItem = hwnd;
		ds.hDC = hdcMem;


		startoffset = DBGetContactSettingDword(NULL,"StatusBar","FirstIconOffset",0);
		extraspace = DBGetContactSettingDword(NULL,"StatusBar","BkExtraSpace",0);

		nParts = SendMessage(hwnd,SB_GETPARTS,0,0);
		memset(&rc,0,sizeof(RECT));
		GetClientRect(hwnd,&clrc);
		clrc.right -= clrc.left;
		clrc.right -= startoffset;
		sectwidth = clrc.right/nParts;

		for (nPanel = 0;nPanel<nParts;nPanel++)
		{
			PD = (ProtocolData *)SendMessage(pcli->hwndStatus,SB_GETTEXT,(WPARAM)nPanel,(LPARAM)0);
			if (PD == NULL){
				continue;
			}
			SendMessage(hwnd,SB_GETRECT,(WPARAM)nPanel,(LPARAM)&rc);
			//rc.left += startoffset;
			//if (rc.left>=rc.right) rc.left = rc.right-1;
			rc.top = 0;
			rc.left = nPanel*sectwidth+startoffset;
			rc.right = rc.left+sectwidth-1;
			ds.rcItem = rc;
			ds.itemData = (ULONG_PTR)PD;
			ds.itemID = nPanel;

			DrawDataForStatusBar(&ds);
	}	}

	BitBlt(hdc,rcPaint->left,rcPaint->top,rcPaint->right-rcPaint->left,rcPaint->bottom-rcPaint->top,hdcMem,rcPaint->left,rcPaint->top,SRCCOPY);

	SelectObject(hdcMem,holdbmp);
	SelectObject(hdcMem,oFont);
	DeleteObject(hBmpOsb);
	DeleteDC(hdcMem);
	paintst.fErase = FALSE;
	//DeleteObject(hFont);
	if (!mhdc)
		EndPaint(hwnd,&paintst);	
}

LRESULT CALLBACK StatusBarOwnerDrawProc(          HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
)
{
if (UseOwnerDrawStatusBar)
{
	switch(uMsg)
	{
	case WM_ERASEBKGND:
		{

			//DrawBackGround(hwnd);
			return 0;
		}
	case WM_PRINT:
		{
			DrawBackGround(hwnd,(HDC)wParam);
			return 0;
		}
	case WM_PAINT:
		{
			DrawBackGround(hwnd,0);
			return 0;
		}
	}

}
return (CallWindowProc(OldWindowProc,hwnd,uMsg,wParam,lParam)
		);
}

LRESULT CALLBACK StatusHelperProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_CREATE:
		{
			{
				tooltipshoing = FALSE;
				//HWND label;
				//label = CreateWindow("static","Top window",WS_VISIBLE|WS_CHILD	,2,2,120,60,hwnd,NULL,g_hInst,0);
				//SendMessage(label,WM_SETFONT,(WPARAM)TitleBarFont,0);
			}
			return(FALSE);

		}
	case WM_GETMINMAXINFO:{
			RECT rct;
			if (pcli->hwndStatus == 0){break;}
			GetWindowRect(pcli->hwndStatus,&rct);
			memset((LPMINMAXINFO)lParam,0,sizeof(MINMAXINFO));
			((LPMINMAXINFO)lParam)->ptMinTrackSize.x = 5;
			((LPMINMAXINFO)lParam)->ptMinTrackSize.y = rct.bottom-rct.top;
			((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = 1600;
			((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = rct.bottom-rct.top;
			return 0;
	}

	case WM_NCHITTEST:
		{
	
		}
	case WM_SHOWWINDOW:
		{
			{
				int res;
				if (hFrameHelperStatusBar)
				{
					res = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS,hFrameHelperStatusBar),0);
					DBWriteContactSettingByte(0,"CLUI","ShowSBar",(BYTE)((res&F_VISIBLE)?1:0));
				}
			}
			

			if (tooltipshoing){
					NotifyEventHooks(hStatusBarHideToolTipEvent,0,0);
					tooltipshoing = FALSE;
				}
			return 0;
			//
		}
	case WM_TIMER:
		{
			if (wParam == TM_STATUSBARHIDE)
			{
				KillTimer(hwnd,TM_STATUSBARHIDE);
				
				if (tooltipshoing){
					NotifyEventHooks(hStatusBarHideToolTipEvent,0,0);
					tooltipshoing = FALSE;
				}
				

			}

			if (wParam == TM_STATUSBAR)
			{
				POINT pt;
				KillTimer(hwnd,TM_STATUSBAR);

				GetCursorPos(&pt);
				if (pt.x == lastpnt.x&&pt.y == lastpnt.y)
				{
					{
	 				int i,nParts;
					ProtocolData *PD;
					RECT rc;
						ScreenToClient(pcli->hwndStatus,&pt);
						nParts = SendMessage(pcli->hwndStatus,SB_GETPARTS,0,0);
						for (i = 0;i<nParts;i++) {
							SendMessage(pcli->hwndStatus,SB_GETRECT,i,(LPARAM)&rc);
							if (PtInRect(&rc,pt)) {							
								PD = (ProtocolData *)SendMessage(pcli->hwndStatus,SB_GETTEXT,i,(LPARAM)0);
								if (PD == NULL){return 0;}
								
								NotifyEventHooks(hStatusBarShowToolTipEvent,(WPARAM)PD->RealName,0);
								SetTimer(hwnd,TM_STATUSBARHIDE,DBGetContactSettingWord(NULL,"CLUIFrames","HideToolTipTime",5000),0);
								tooltipshoing = TRUE;

								break;
							}
						}

						
						
					}
					
					
					
				}
				
			}
		
		return 0;
		}
	
	case WM_SETCURSOR:
		{

				{		
					POINT pt;
					GetCursorPos(&pt);
					if (pt.x == lastpnt.x&&pt.y == lastpnt.y)
					{
						return 0;
					}
					lastpnt = pt;
					if (tooltipshoing){
							KillTimer(hwnd,TM_STATUSBARHIDE);				
							NotifyEventHooks(hStatusBarHideToolTipEvent,0,0);
							tooltipshoing = FALSE;		
						}
						KillTimer(hwnd,TM_STATUSBAR);
						SetTimer(hwnd,TM_STATUSBAR,DBGetContactSettingWord(NULL,"CLC","InfoTipHoverTime",750),0);
						return 0;
				}			

		}
	case WM_NOTIFY:
		{
			if (lParam == 0){return 0;}
			if (((LPNMHDR)lParam)->hwndFrom == pcli->hwndStatus)
			{

				if (((LPNMHDR)lParam)->code == WM_NCHITTEST)
				{
					LPNMMOUSE lpnmmouse = (LPNMMOUSE) lParam;
				} ;
			}
		}

	case WM_CONTEXTMENU:
		KillTimer(hwnd,TM_STATUSBARHIDE);

		if (tooltipshoing)
			NotifyEventHooks(hStatusBarHideToolTipEvent,0,0);

		tooltipshoing = FALSE;

	case WM_MEASUREITEM:
	case WM_DRAWITEM:
		//parent do all work for us
		return(SendMessage(pcli->hwndContactList,msg,wParam,lParam));

	case WM_MOVE:
		PostMessage(pcli->hwndStatus,WM_MOVE,wParam,lParam);

	case WM_SIZE:
		{
			RECT rc;
			int b;
			if (pcli->hwndStatus != 0) {
				GetClientRect(hwnd,&rc);

				b = LOWORD(lParam);
				if (b != 0&&(rc.right-rc.left) != (OldRc.right-OldRc.left)) {
					OldRc = rc;
					if (canloadstatusbar) 	
						if (DBGetContactSettingByte(NULL,"CLUI","UseOwnerDrawStatusBar",0)||DBGetContactSettingByte(NULL,"CLUI","EqualSections",1)) 
							CluiProtocolStatusChanged(0,0);
				}
				if (msg == WM_SIZE) PostMessage(pcli->hwndStatus,WM_SIZE,wParam,lParam);
				if (pcli->hwndStatus != 0) InvalidateRect(pcli->hwndStatus,NULL,TRUE);
				return 0;
			}
		}

	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);

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

HWND CreateStatusHelper(HWND parent)
{
	WNDCLASS wndclass = {0};
	TCHAR pluginname[] = _T("Statushelper");

	if (GetClassInfo(g_hInst,pluginname,&wndclass) == 0 ) {
		wndclass.style         = 0;
		wndclass.lpfnWndProc   = StatusHelperProc;
		wndclass.cbClsExtra    = 0;
		wndclass.cbWndExtra    = 0;
		wndclass.hInstance     = g_hInst;
		wndclass.hIcon         = NULL;
		wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
		wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
		wndclass.lpszMenuName  = NULL;
		wndclass.lpszClassName = pluginname;
		RegisterClass(&wndclass);
	}

	return(CreateWindow(pluginname,pluginname,
		/*WS_THICKFRAME|*/WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN,
		0,0,0,0,parent,NULL,g_hInst,NULL));
}

HANDLE CreateStatusBarFrame()
{
	CLISTFrame Frame;
	int h;
	RECT rc;

	memset(&Frame,0,sizeof(Frame));
	Frame.cbSize = sizeof(CLISTFrame);
	Frame.hWnd = helperhwnd;
	Frame.align = alBottom;
	Frame.hIcon = LoadSkinnedIcon (SKINICON_OTHER_MIRANDA);
	Frame.Flags = (DBGetContactSettingByte(NULL,"CLUI","ShowSBar",1)?F_VISIBLE:0)|F_LOCKED|F_NOBORDER|F_TCHAR;
	GetWindowRect(helperhwnd,&rc);
	h = rc.bottom-rc.top;
	Frame.height = (h == 0)?20:h;


	Frame.tname = _T("Status");
	Frame.TBtname = TranslateT("Status Bar");
	hFrameHelperStatusBar = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0);


	return hFrameHelperStatusBar;
}

int RecreateStatusBar(HWND parent)
{
	if (pcli->hwndStatus) {
		FreeProtocolData();
		DestroyWindow(pcli->hwndStatus);
	}
	pcli->hwndStatus = 0;
	if (hFrameHelperStatusBar) CallService(MS_CLIST_FRAMES_REMOVEFRAME,(WPARAM)hFrameHelperStatusBar,0);

	helperhwnd = CreateStatusHelper(parent);
	UseOwnerDrawStatusBar = DBGetContactSettingByte(NULL,"CLUI","UseOwnerDrawStatusBar",0);

	//create the status wnd
	pcli->hwndStatus = CreateStatusWindow(
		( DBGetContactSettingByte(0,"CLUI","SBarUseSizeGrip",TRUE) && (!UseOwnerDrawStatusBar)?SBARS_SIZEGRIP:0)|
		WS_CHILD | (DBGetContactSettingByte(NULL,"CLUI","ShowSBar",1)?WS_VISIBLE:0), _T(""), helperhwnd, 0);

	OldWindowProc = (WNDPROC)GetWindowLongPtr(pcli->hwndStatus,GWLP_WNDPROC);
	SetWindowLongPtr(pcli->hwndStatus,GWLP_WNDPROC,(LONG_PTR)&StatusBarOwnerDrawProc);
	CreateStatusBarFrame();
	{
		SetWindowPos(helperhwnd,NULL,1,1,1,1,SWP_NOZORDER);
		CluiProtocolStatusChanged(0,0);
		CallService(MS_CLIST_FRAMES_UPDATEFRAME,-1,0);
	}

	return 0;
}

HWND CreateStatusBarhWnd(HWND parent)
{	
	RecreateStatusBar(parent);
	OnStatusBarBackgroundChange();

	hStatusBarShowToolTipEvent = CreateHookableEvent(ME_CLIST_FRAMES_SB_SHOW_TOOLTIP);
	hStatusBarHideToolTipEvent = CreateHookableEvent(ME_CLIST_FRAMES_SB_HIDE_TOOLTIP);
	return pcli->hwndStatus;
}