#include <stdio.h>
#include <windows.h>
#include <sys\timeb.h>
#include <sys\stat.h>

#include "Screenshots.h"

static volatile Uint8 _screenshot_scheduled = 0;

#define PATH_COMPONENT_MAX_SIZE (256)
#define FILENAME_AND_EXTENSION_MAX_SIZE (PATH_COMPONENT_MAX_SIZE*3+1)
static char _filenameAndExtensionBuffer[FILENAME_AND_EXTENSION_MAX_SIZE];
static char _screenshotFilenameBuffer[FILENAME_AND_EXTENSION_MAX_SIZE];

static char _driveBuffer[PATH_COMPONENT_MAX_SIZE];
static char _directoryBuffer[PATH_COMPONENT_MAX_SIZE];
static char _filenameBuffer[PATH_COMPONENT_MAX_SIZE];
static char _extensionBuffer[PATH_COMPONENT_MAX_SIZE];

#define ABSOLUTE_PATH_MAX_SIZE (4*FILENAME_AND_EXTENSION_MAX_SIZE)
#define _DEBUG_BUFFER_SIZE (ABSOLUTE_PATH_MAX_SIZE+256)
static char _debugBuffer[_DEBUG_BUFFER_SIZE];

static char _absolutePathBuffer[ABSOLUTE_PATH_MAX_SIZE];

static Uint8 _screenshotsInitialized = 0;

void screenshots_keyup(SDL_Keysym key) {
	if (!_screenshotsInitialized) {
		return;
	}

	if (key.sym == SDLK_PRINTSCREEN) {
		// schedule a screenshot
		_screenshot_scheduled = 1;
	}
}

Uint8 screenshots_is_scheduled() {
	return _screenshot_scheduled;
}

void screenshots_snap_and_save(SDL_Surface* surface, int height) {
	if (!_screenshotsInitialized) {
		return;
	}

	SYSTEMTIME time;
	GetSystemTime(&time);

	sprintf_s(_screenshotFilenameBuffer, FILENAME_AND_EXTENSION_MAX_SIZE - 5, "%s\\%s_%04d-%02d-%02d_%02d-%02d-%02d.%03d.png",
		_filenameAndExtensionBuffer,
		_filenameBuffer,
		time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds);

	// create a clone of the main surface, cutting off any UI elements at the bottom
	SDL_Surface* surfaceForScreenshot = SDL_CreateRGBSurface(
		0, surface->w, height, surface->format->BytesPerPixel * 8,
		surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);

	if (surfaceForScreenshot == NULL) {
		log_write("Error: unable to create temporary surface for screenshot");
	}
	else {
		// clone pixels
		SDL_memcpy4(surfaceForScreenshot->pixels, surface->pixels, surfaceForScreenshot->w * surfaceForScreenshot->h);

		// write to file
		IMG_SavePNG(surfaceForScreenshot, _screenshotFilenameBuffer);

		sprintf_s(_debugBuffer, _DEBUG_BUFFER_SIZE - 10, "Saved screenshot: %s", _screenshotFilenameBuffer);
		log_write(_debugBuffer);

		// cleanup temporary surface
		SDL_FreeSurface(surfaceForScreenshot);
	}

	_screenshot_scheduled = 0;
}

void screenshots_start(char* path) {
	// does not need to be freed, because it returns input buffer on success
	char* resultPtr = _fullpath(
		_absolutePathBuffer,
		path,
		ABSOLUTE_PATH_MAX_SIZE
	);
	if (!resultPtr) {
		sprintf_s(_debugBuffer, _DEBUG_BUFFER_SIZE - 10, "Warning: screenshots unavailable: could not resolve absolute path of %s", path);
		log_write(_debugBuffer);
		return;
	}

	errno_t result = _splitpath_s(
		_absolutePathBuffer,
		_driveBuffer,
		PATH_COMPONENT_MAX_SIZE - 5,
		_directoryBuffer,
		PATH_COMPONENT_MAX_SIZE - 5,
		_filenameBuffer,
		PATH_COMPONENT_MAX_SIZE - 5,
		_extensionBuffer,
		PATH_COMPONENT_MAX_SIZE - 5);
	if (result) {
		sprintf_s(_debugBuffer, _DEBUG_BUFFER_SIZE - 10, "Warning: screenshots unavailable: could not parse path %s", _absolutePathBuffer);
		log_write(_debugBuffer);
		return;
	}

	CreateDirectoryA("screenshots", NULL);

	sprintf_s(_filenameAndExtensionBuffer, FILENAME_AND_EXTENSION_MAX_SIZE - 5, "screenshots\\%s%s", _filenameBuffer, _extensionBuffer);
	sprintf_s(_debugBuffer, _DEBUG_BUFFER_SIZE - 10, "Screenshots root directory: %s", _filenameAndExtensionBuffer);
	log_write(_debugBuffer);

	CreateDirectoryA(_filenameAndExtensionBuffer, NULL);
	_screenshotsInitialized = 1;
}

void screenshots_destroy() {
	if (!_screenshotsInitialized) {
		return;
	}

	_screenshot_scheduled = 0;
}
