#include "game.h"

#include <chrono>
#include <format>
#include <iostream>
#include <SDL3/SDL.h>
#include <Windows.h>
#include "image.h"
#include "settings.h"


LRESULT WINAPI wnd_proc(HWND window, UINT msg, WPARAM w, LPARAM l) {
	switch(msg) {
	case WM_DESTROY:
		::PostQuitMessage(0);
		return 0;
	}
	return ::DefWindowProc(window, msg, w, l);
}

void game::run() {
	settings settings;
	init(settings);
	auto title = std::wstring(settings.title.begin(), settings.title.end());

	auto instance = GetModuleHandle(0);
	auto wc = WNDCLASS{
		.lpfnWndProc = wnd_proc,
		.hInstance = instance,
		.lpszClassName = title.c_str(),
	};

	auto atom = RegisterClass(&wc);
	auto window = CreateWindow(
		wc.lpszClassName,
		title.c_str(),
		WS_POPUP,
		0,
		0,
		settings.size.x * settings.scale,
		settings.size.y * settings.scale,
		0,
		0,
		instance,
		0
	);

	ShowWindow(window, SW_SHOWNORMAL);
	ShowCursor(FALSE);

	auto window_image = image(settings.size * settings.scale);
	auto screen = image(settings.size);
	screen.clear(0xffdddd);

	
	auto last_second = std::chrono::steady_clock::now();
	auto frames_since_last_second = 0;

	std::chrono::duration<int32_t, std::nano> second(1000000000ll);
	auto frame_duration = second / settings.target_fps;
	auto last_frame = last_second;

	auto running = true;
	while(running) {
		MSG msg;
		while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			switch(msg.message) {
			case WM_QUIT:
				running = false;
				break;
			case WM_MOUSEMOVE:
				_mouse_pos.x = LOWORD(msg.lParam) / settings.scale;
				_mouse_pos.y = HIWORD(msg.lParam) / settings.scale;
				break;
			}
		}

		auto now = std::chrono::steady_clock::now();
		if(now - last_second >= std::chrono::seconds(1)) {
			std::cout << std::format("FPS: {:5} | mspf: {}", frames_since_last_second, 1000.0 / frames_since_last_second) << std::endl;
			frames_since_last_second = 0;
			last_second += std::chrono::seconds(1);
		}

		if(now - last_frame >= frame_duration) {
			update();
			render(screen);
			window_image.draw_upscaled(screen);

			BITMAPINFOHEADER bi{ sizeof(bi) };
			bi.biWidth = window_image.size().x;
			bi.biHeight = -window_image.size().y;
			bi.biPlanes = 1;
			bi.biBitCount = 32;
			bi.biCompression = BI_RGB;

			auto dc = GetDC(window);
			SetDIBitsToDevice(
				dc,
				0,
				0, 
				window_image.size().x,
				window_image.size().y,
				0,
				0,
				0,
				window_image.size().y,
				window_image.raw_pointer(),
				(BITMAPINFO*)&bi, 
				DIB_RGB_COLORS
			);
			ReleaseDC(window, dc);
			++frames_since_last_second;
			last_frame += frame_duration;
		}
	}


}

/*
void game::run() {
	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);

	settings settings;

	init(settings);

	SDL_PropertiesID props = SDL_CreateProperties();
	SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, "title");
	SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED);
	SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_CENTERED);
	SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, settings.size.x * settings.scale);
	SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, settings.size.y * settings.scale);
	auto window = SDL_CreateWindowWithProperties(props);
	auto screen = image(settings.size);
	auto renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED);
	auto window_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, settings.size.x * settings.scale, settings.size.y * settings.scale);

	auto last_second = std::chrono::steady_clock::now();
	auto frames_since_last_second = 0;

	auto running = true;
	while(running) {
		auto event = SDL_Event{};
		while(SDL_PollEvent(&event)) {
			switch(event.type) {
			case SDL_EVENT_QUIT:
				running = false;
				break;
			}
		}

		auto now = std::chrono::steady_clock::now();
		if(now - last_second >= std::chrono::seconds(1)) {
			std::cout << std::format("FPS: {:5} | mspf: {}", frames_since_last_second, 1000.0/frames_since_last_second) << std::endl;
			frames_since_last_second = 0;
			last_second += std::chrono::seconds(1);
		}

		update();
		render(screen);
		++frames_since_last_second;
		int pitch;
		void* pixels = 0;
		SDL_LockTexture(window_texture, 0, &pixels, &pitch);
		auto window_image = image(settings.size * settings.scale, static_cast<color*>(pixels));
		window_image.draw_upscaled(screen);
		SDL_UnlockTexture(window_texture);
		SDL_RenderTexture(renderer, window_texture, 0, 0);
		SDL_RenderPresent(renderer);
	}

	SDL_Quit();
}
*/

void game::init(settings& settings) {

}

void game::render(image& target) {
	
}

void game::update() {

}

vec2i const& game::mouse_pos() const {
	return _mouse_pos;
}
