#include <clip.h>

#define APPNAME		"pngwin"
#define SIZE_MAX	2048

//	#define FNAME	"ct0d01p.png"
//	#define FNAME	"ct0d02p.png"
//	#define FNAME	"ct0d04p.png"
//	#define FNAME	"ct0d08p.png"
//	#define FNAME	"ct0d16p.png"
//	#define FNAME	"ct2d08p.png"
//	#define FNAME	"ct2d16p.png"
//	#define FNAME	"ct3d01p.png"
//	#define FNAME	"ct3d02p.png"
//	#define FNAME	"ct3d04p.png"
//	#define FNAME	"ct3d08p.png"
//	#define FNAME	"ct4d08p.png"
//	#define FNAME	"ct4d16p.png"
	#define FNAME	"ct6d08p.png"
//	#define FNAME	"ct6d16p.png"

//	#define FNAME	"ct0d01i.png"
//	#define FNAME	"ct0d02i.png"
//	#define FNAME	"ct0d04i.png"
//	#define FNAME	"ct0d08i.png"
//	#define FNAME	"ct0d16i.png"
//	#define FNAME	"ct2d08i.png"
//	#define FNAME	"ct2d16i.png"
//	#define FNAME	"ct3d01i.png"
//	#define FNAME	"ct3d02i.png"
//	#define FNAME	"ct3d04i.png"
//	#define FNAME	"ct3d08i.png"
//	#define FNAME	"ct4d08i.png"
//	#define FNAME	"ct4d16i.png"
//	#define FNAME	"ct6d08i.png"
//	#define FNAME	"ct6d16i.png"

int win_scale;
int file_size;
unsigned char* file_data;

int img_w;
int img_h;
unsigned char img[SIZE_MAX][SIZE_MAX][4];

BITMAPINFOHEADER bi;
unsigned char* dib;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

static void my_size_proc(int w, int h, void* user_data) {
	img_w = w;
	img_h = h;
}

static void my_draw_proc(int x, int y, int r, int g, int b, int a, void* user_data) {
	int ar, ag, ab;
	if(x < 0 || x > img_w - 1 || y < 0 || y > img_h - 1) {
		DIE();
	}
	if(r & ~255 || g & ~255 || b & ~255 || a & ~255) {
		DIE();
	}
	if(((x / 16) ^ (y / 16)) & 1) {
		ar = ag = ab = 85;
	} else {
		ar = ag = ab = 170;
	}
	img[y][x][0] = (b * a + ab * (255 - a)) / 255;
	img[y][x][1] = (g * a + ag * (255 - a)) / 255;
	img[y][x][2] = (r * a + ar * (255 - a)) / 255;
	img[y][x][3] = a;
}

int main(int argc, char* argv[]) {
	const char* fname;
	FILE* fp;
	int pitch;
	int i;
	int x;
	int y;
	HINSTANCE hInst;
	HWND hWnd;
	MSG msg;
	WNDCLASS wc;
	RECT rcWin;
	RECT rcCli;
	int ncW;
	int ncH;

	DEBUG_INIT();

	fname = (argc >= 1 + 1) ? argv[1] : FNAME;
	win_scale = (argc >= 1 + 2) ? atoi(argv[2]) : 4;
	if(win_scale < 1) win_scale = 1;

	fp = fopen(fname, "rb");
	if(!fp) {
		DIE();
	}
	fseek(fp, 0, SEEK_END);
	file_size = ftell(fp);
	rewind(fp);
	file_data = malloc(file_size);
	if(!file_data) {
		DIE();
	}
	fread(file_data, 1, file_size, fp);
	fclose(fp);
	png_decode(file_data, my_size_proc, my_draw_proc, NULL);
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = img_w;
	bi.biHeight = img_h;
	bi.biPlanes = 1;
	bi.biBitCount = 24;
	pitch = ((img_w * 3) + 3) & ~3;
	dib = malloc(pitch * img_h);
	if(!dib) {
		DIE();
	}
	for(y = 0; y < img_h; y++) {
		for(x = 0; x < img_w; x++) {
			for(i = 0; i < 3; i++) {
				dib[y * pitch + x * 3 + i] = img[img_h - 1 - y][x][i];
			}
		}
	}

	hInst = GetModuleHandle(NULL);
	memset(&wc, 0, sizeof wc);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;
	wc.hInstance = hInst;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszClassName = APPNAME;
	RegisterClass(&wc);
	hWnd = CreateWindow(APPNAME, APPNAME,
		WS_OVERLAPPED | WS_SYSMENU,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInst, NULL);
	GetWindowRect(hWnd, &rcWin);
	GetClientRect(hWnd, &rcCli);
	ncW = (rcWin.right - rcWin.left) - (rcCli.right - rcCli.left);
	ncH = (rcWin.bottom - rcWin.top) - (rcCli.bottom - rcCli.top);
	MoveWindow(hWnd, 0, 0, ncW + img_w * win_scale, ncH + img_h * win_scale, FALSE);
	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);

	while(GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	free(file_data);
	free(dib);

	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	HDC hDC;
	PAINTSTRUCT ps;

	switch(msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_KEYDOWN:
		if(wParam == VK_ESCAPE) {
			SendMessage(hWnd, WM_CLOSE, 0, 0);
			return 0;
		}
		return 0;
	case WM_PAINT:
		hDC = BeginPaint(hWnd, &ps);
		StretchDIBits(hDC,
			0, 0, bi.biWidth * win_scale, bi.biHeight * win_scale,
			0, 0, bi.biWidth, bi.biHeight,
			dib, (BITMAPINFO*)&bi, DIB_RGB_COLORS, SRCCOPY);
		EndPaint(hWnd, &ps);
		return 0;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

