#include "sysconfig.h"

#include <windows.h>
#include <commctrl.h>

#include "sysdeps.h"

#include "options.h"
#include "uae.h"
#include "win32.h"
#include "picasso96_win.h"
#include "win32gfx.h"
#include "registry.h"
#include "win32gui.h"
#include "statusline.h"
#include "gui.h"
#include "xwin.h"

static HDC statusline_hdc;
static HBITMAP statusline_bitmap;
static void *statusline_bm;
static int statusline_width;
static int statusline_height = TD_TOTAL_HEIGHT;
static HFONT statusline_font;
static HPALETTE statusline_palette;
static char *td_new_numbers;
static int statusline_fontsize, statusline_fontstyle, statusline_fontweight;
static bool statusline_customfont;
static TCHAR statusline_fontname[256];

void deletestatusline(int monid)
{
	if (monid)
		return;
	struct AmigaMonitor *mon = &AMonitors[monid];
	if (!statusline_hdc)
		return;
	if (statusline_bitmap)
		DeleteObject(statusline_bitmap);
	if (statusline_hdc)
		ReleaseDC(NULL, statusline_hdc);
	if (statusline_font)
		DeleteObject(statusline_font);
	if (statusline_palette)
		DeleteObject(statusline_palette);
	statusline_bitmap = NULL;
	statusline_hdc = NULL;
	statusline_font = NULL;
	statusline_palette = NULL;
}

static void create_led_font(HWND parent, int monid)
{
	HDC hdc;
	LPLOGPALETTE lp;
	HPALETTE hpal;
	BITMAPINFO *bi;
	BITMAPINFOHEADER *bih;
	HBITMAP bitmap = NULL;
	int width = 128;
	int height = 128;
	void *bm;

	statusline_set_font(NULL, 0, 0);

	xfree(td_new_numbers);

	statusline_fontsize = 8;
	_tcscpy(statusline_fontname, _T("Lucida Console"));
	statusline_fontweight = FW_NORMAL;
	statusline_customfont = regqueryfont(NULL, NULL, _T("OSDFont"), statusline_fontname, &statusline_fontsize, &statusline_fontstyle, &statusline_fontweight);

	hdc = CreateCompatibleDC(NULL);
	if (hdc) {
		int y = getdpiforwindow(parent);
		statusline_fontsize = -MulDiv(statusline_fontsize, y, 72);
		statusline_fontsize = statusline_fontsize * statusline_get_multiplier(monid) / 100;
		lp = (LOGPALETTE *)xcalloc(uae_u8, sizeof(LOGPALETTE) + 3 * sizeof(PALETTEENTRY));
		if (lp) {
			lp->palNumEntries = 4;
			lp->palVersion = 0x300;
			lp->palPalEntry[1].peBlue = lp->palPalEntry[1].peGreen = lp->palPalEntry[0].peRed = 0x10;
			lp->palPalEntry[2].peBlue = lp->palPalEntry[2].peGreen = lp->palPalEntry[2].peRed = 0xff;
			lp->palPalEntry[3].peBlue = lp->palPalEntry[3].peGreen = lp->palPalEntry[3].peRed = 0x7f;
			hpal = CreatePalette(lp);
			if (hpal) {
				SelectPalette(hdc, hpal, FALSE);
				bi = (BITMAPINFO*)xcalloc(uae_u8, sizeof(BITMAPINFOHEADER) + 4 * sizeof(RGBQUAD));
				if (bi) {
					bih = &bi->bmiHeader;
					bih->biSize = sizeof(BITMAPINFOHEADER);
					bih->biWidth = width;
					bih->biHeight = -height;
					bih->biPlanes = 1;
					bih->biBitCount = 8;
					bih->biCompression = BI_RGB;
					bih->biClrUsed = 4;
					bih->biClrImportant = 4;
					bi->bmiColors[1].rgbBlue = bi->bmiColors[1].rgbGreen = bi->bmiColors[1].rgbRed = 0x10;
					bi->bmiColors[2].rgbBlue = bi->bmiColors[2].rgbGreen = bi->bmiColors[2].rgbRed = 0xff;
					bi->bmiColors[3].rgbBlue = bi->bmiColors[3].rgbGreen = bi->bmiColors[3].rgbRed = 0x7f;
					bitmap = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bm, NULL, 0);
					if (bitmap) {
						SelectObject(hdc, bitmap);
						RealizePalette(hdc);
						HFONT font = CreateFont(statusline_fontsize, 0,
							0, 0,
							statusline_fontweight,
							(statusline_fontstyle & ITALIC_FONTTYPE) != 0,
							FALSE,
							FALSE,
							DEFAULT_CHARSET,
							OUT_TT_PRECIS,
							CLIP_DEFAULT_PRECIS,
							PROOF_QUALITY,
							FIXED_PITCH | FF_DONTCARE,
							statusline_fontname);
						if (font) {
							SelectObject(hdc, font);
							SetTextColor(hdc, PALETTEINDEX(2));
							SetBkColor(hdc, PALETTEINDEX(1));
							TEXTMETRIC tm;
							GetTextMetrics(hdc, &tm);
							int w = 0;
							int h = tm.tmAscent + 2;
							for (int i = 0; i < td_characters[i]; i++) {
								SIZE sz;
								if (GetTextExtentPoint32(hdc, &td_characters[i], 1, &sz)) {
									if (sz.cx > w)
										w = sz.cx;
								}
							}
							int offsetx = 10;
							int offsety = 10 - 1;
							w += 1;
							td_new_numbers = xcalloc(char, w * h * NUMBERS_NUM);
							if (td_new_numbers) {
								for (int i = 0; i < td_characters[i]; i++) {
									SetBkMode(hdc, OPAQUE);
									BitBlt(hdc, 0, 0, width, height, NULL, 0, 0, BLACKNESS);
									TextOut(hdc, 10, 10, &td_characters[i], 1);
									for (int y = 0; y < h; y++) {
										uae_u8 *src = (uae_u8 *)bm + (y + offsety) * width + offsetx;
										char *dst = td_new_numbers + i * w + y * w * NUMBERS_NUM;
										for (int x = 0; x < w; x++) {
											uae_u8 b = *src++;
											if (b == 2) {
												*dst = 'x';
											} else {
												*dst = '-';
											}
											dst++;
										}
									}

									BitBlt(hdc, 0, 0, width, height, NULL, 0, 0, BLACKNESS);
									SetBkMode(hdc, TRANSPARENT);
									TextOut(hdc, 9, 9, &td_characters[i], 1);
									TextOut(hdc, 11, 9, &td_characters[i], 1);
									TextOut(hdc, 11, 11, &td_characters[i], 1);
									TextOut(hdc, 9, 11, &td_characters[i], 1);
									for (int y = 0; y < h; y++) {
										uae_u8 *src = (uae_u8 *)bm + (y + offsety) * width + offsetx;
										char *dst = td_new_numbers + i * w + y * w * NUMBERS_NUM;
										for (int x = 0; x < w; x++) {
											uae_u8 b = *src++;
											if (b == 2 && dst[0] == '-') {
												*dst = '+';
											}
											dst++;
										}
									}

								}
							}
							statusline_set_font(td_new_numbers, w, h);
							DeleteObject(font);
						}
						DeleteObject(bitmap);
					}
					xfree(bi);
				}
				DeleteObject(hpal);
			}
			xfree(lp);
		}
		ReleaseDC(NULL, hdc);
	}
}

bool createstatusline(HWND parentHwnd, int monid)
{
	struct AmigaMonitor *mon = &AMonitors[monid];
	BITMAPINFO *bi;
	BITMAPINFOHEADER *bih;
	LOGPALETTE *lp;

	if (monid)
		return false;

	deletestatusline(mon->monitor_id);
	statusline_hdc = CreateCompatibleDC(NULL);
	if (!statusline_hdc)
		return false;

	create_led_font(parentHwnd, monid);

	lp = (LOGPALETTE*)xcalloc(uae_u8, sizeof(LOGPALETTE) + 3 * sizeof(PALETTEENTRY));
	if (!lp)
		return false;
	lp->palNumEntries = 4;
	lp->palVersion = 0x300;
	lp->palPalEntry[1].peBlue = lp->palPalEntry[1].peGreen = lp->palPalEntry[0].peRed = 0x10;
	lp->palPalEntry[2].peBlue = lp->palPalEntry[2].peGreen = lp->palPalEntry[2].peRed = 0xff;
	lp->palPalEntry[3].peBlue = lp->palPalEntry[3].peGreen = lp->palPalEntry[3].peRed = 0x7f;
	statusline_palette = CreatePalette(lp);
	xfree(lp);
	SelectPalette(statusline_hdc, statusline_palette, FALSE);
	statusline_width = (WIN32GFX_GetWidth(mon) + 31) & ~31;
	statusline_height = -statusline_fontsize;
	bi = (BITMAPINFO*)xcalloc(uae_u8, sizeof(BITMAPINFOHEADER) + 4 * sizeof(RGBQUAD));
	if (bi) {
		bih = &bi->bmiHeader;
		bih->biSize = sizeof(BITMAPINFOHEADER);
		bih->biWidth = statusline_width;
		bih->biHeight = -statusline_height;
		bih->biPlanes = 1;
		bih->biBitCount = 8;
		bih->biCompression = BI_RGB;
		bih->biClrUsed = 4;
		bih->biClrImportant = 4;
		bi->bmiColors[1].rgbBlue = bi->bmiColors[1].rgbGreen = bi->bmiColors[1].rgbRed = 0x10;
		bi->bmiColors[2].rgbBlue = bi->bmiColors[2].rgbGreen = bi->bmiColors[2].rgbRed = 0xff;
		bi->bmiColors[3].rgbBlue = bi->bmiColors[3].rgbGreen = bi->bmiColors[3].rgbRed = 0x7f;
		statusline_bitmap = CreateDIBSection(statusline_hdc, bi, DIB_RGB_COLORS, &statusline_bm, NULL, 0);
		xfree(bi);
	}
	if (!statusline_bitmap) {
		deletestatusline(mon->monitor_id);
		return false;
	}
	SelectObject(statusline_hdc, statusline_bitmap);
	RealizePalette(statusline_hdc);

	statusline_font = CreateFont(statusline_fontsize, 0,
		0, 0,
		statusline_fontweight,
		(statusline_fontstyle & ITALIC_FONTTYPE) != 0,
		FALSE,
		FALSE,
		DEFAULT_CHARSET,
		OUT_TT_PRECIS,
		CLIP_DEFAULT_PRECIS,
		PROOF_QUALITY,
		VARIABLE_PITCH | FF_DONTCARE,
		statusline_fontname);
	SelectObject(statusline_hdc, statusline_font);
	SetTextColor(statusline_hdc, PALETTEINDEX(2));
	SetBkColor(statusline_hdc, PALETTEINDEX(1));
	SetBkMode(statusline_hdc, OPAQUE);

	return true;
}

void statusline_updated(int monid)
{
	if (monid)
		return;
	struct AmigaMonitor *mon = &AMonitors[monid];
	if (mon->hStatusWnd)
		PostMessage(mon->hStatusWnd, SB_SETTEXT, (WPARAM)((window_led_msg_start) | SBT_OWNERDRAW), (LPARAM)_T(""));
}

void statusline_render(int monid, uae_u8 *buf, int bpp, int pitch, int width, int height, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *alpha)
{
	struct AmigaMonitor *mon = &AMonitors[monid];
	uae_u32 white = rc[0xff] | gc[0xff] | bc[0xff] | (alpha ? alpha[0xff] : 0);
	uae_u32 back = rc[0x00] | gc[0x00] | bc[0x00] | (alpha ? alpha[0xa0] : 0);
	const TCHAR *text;
	int y = 0, x = 10, textwidth = 0;
	int bar_xstart;

	if (monid || !statusline_hdc) {
		return;
	}

	text = statusline_fetch();
	//text = _T("Testing string 123!");
	if (!text)
		return;

	BitBlt(statusline_hdc, 0, 0, statusline_width, statusline_height, NULL, 0, 0, BLACKNESS);
	SIZE size;
	if (GetTextExtentPoint32(statusline_hdc, text, uaetcslen(text), &size)) {
		textwidth = size.cx;
		if (isfullscreen()) {
			if (td_numbers_pos & TD_RIGHT) {
				bar_xstart = width - td_numbers_padx - VISIBLE_LEDS * td_width;
				x = bar_xstart - textwidth - td_led_width;
			} else {
				bar_xstart = td_numbers_padx;
				x = bar_xstart + textwidth + td_led_width;
			}
		}
	}
	if (x < 0)
		x = 0;
	TextOut(statusline_hdc, x, y, text, uaetcslen(text));

	for (int y = 0; y < height && y < statusline_height; y++) {
		uae_u8 *src = (uae_u8*)statusline_bm + y * statusline_width;
		uae_u32 *dst2 = (uae_u32*)(buf + pitch * y);
		for (int x = 0; x < width && x < statusline_width; x++) {
			uae_u8 b = *src++;
			if (b) {
				if (b == 2)
					*dst2 = white;
				else if (b == 1)
					*dst2 = back;
			}
			dst2++;
		}
	}
}
