#include <cstdio>
#include <string>
#include <Windows.h>
#include <turbojpeg.h>
#include "mSock.h"

// 2-second timeout for all incoming HTTP requests
#define HTTP_GET_TIMEOUT (3000)

// ===========================
struct image_t {
	int width;
	int height;
	int bpp;
	unsigned char* data;
};

image_t getScreenshot() {
	// get the device context of the screen and a device context to put it in
	HDC hScreenDC = GetDC(0); // CreateDC(L"DISPLAY", NULL, NULL, NULL);     
	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);

	int width  = GetDeviceCaps(hScreenDC, HORZRES);
	int height = GetDeviceCaps(hScreenDC, VERTRES);

	// maybe worth checking these are positive values
	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);

	// get a new bitmap
	HANDLE hOldBitmap = SelectObject(hMemoryDC, hBitmap);

	BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY);
	hBitmap = (HBITMAP) SelectObject(hMemoryDC, hOldBitmap);
	// now your image is held in hBitmap. You can save it or do whatever with it

	// -----------------

	// Get bpp
	image_t ret = image_t();
	
	// Get image details 
	BITMAPINFO bi = {0};
	bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
	int rv = GetDIBits(hScreenDC, hBitmap, 0, 0, 0, &bi, DIB_RGB_COLORS);

	ret.data = new unsigned char[width * height * 32];	
	bi.bmiHeader.biBitCount = 32;
	bi.bmiHeader.biCompression = BI_RGB; // no compression here
	
	rv = GetDIBits(hScreenDC, hBitmap, 0, height, ret.data, &bi, DIB_RGB_COLORS);
	
	ret.width = width;
	ret.height = height;
	ret.bpp = bi.bmiHeader.biBitCount;	

	// clean up
	DeleteDC(hMemoryDC);
	DeleteDC(hScreenDC);

	return ret;
}

int main(int argc, char* argv[]) {
	puts("ndsview-mappy");
	tjhandle jpg = tjInitCompress();

	mSockServer ss = mSockServer(8081);
	puts("listening");

	while (ss.isValid()) {
		mSockClient msc = ss.newConn();
		if (msc != -1) {

			puts("request");

			mSock client = mSock(msc);
			unsigned long lastTime = GetTickCount();
			bool bGotRequestOK = false;
			std::string sInput = "";

			// See if the request is a valid HTTP request
			for (;;) {
				client.doEvents();
				sInput.append( client.get() );
				if (sInput.find("GET" /* screen.jpg HTTP/1"*/, 0) != sInput.npos) {
					bGotRequestOK = true;
					break;
				}
				if (lastTime + HTTP_GET_TIMEOUT < GetTickCount()) break;
				Sleep(1);
			}

			// Respond with the image
			if (bGotRequestOK) {
				puts("valid request");

				// Get screen
				image_t screen = getScreenshot();

				// Encode as jpg
				unsigned char *jpegbuffer = new unsigned char [TJBUFSIZE(screen.width, screen.height)];
				unsigned long jpeg_size = 0;
				int rv = tjCompress(
					jpg, screen.data, screen.width, 0, screen.height, 4, 
					jpegbuffer, &jpeg_size, TJ_420, 80, TJ_BGR | TJ_BOTTOMUP
				);

				

				char fmtBuff[256] = {0};

				client.put("HTTP/1.1 200 OK\n");
				client.put("Content-Type: image/jpeg\n"); // doublecheck
				sprintf_s(fmtBuff, "Content-Length: %d\n");
				client.put(fmtBuff);
				client.put("Access-Control-Allow-Origin: *\n\n");

				client.put((const char*)jpegbuffer, jpeg_size);
				client.close();

				puts("all sent");

				delete[] screen.data;
				delete[] jpegbuffer;

			} else {
				puts("invalid request");
				puts("=========================");
				puts(sInput.c_str());
				puts("=========================");
			}

		}	

		// Release timeslice to OS
		Sleep(1);
	}
	
	// Respond to network request

	// Tidy up

	return 0;
}