// Copyright (c) 2022 Yevhen Babiichuk (DustDFG), <dfgdust@gmail.com>.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "Game.h"

#include "Screen.h"
#include "Sprite.h"
#include <vector>

#include <SDL.h>
#include <SDL_rect.h>
#include <SDL_events.h>

#include "Board.h"

Game::Game()
{
	SDL_Init(SDL_INIT_VIDEO);

	this->window = SDL_CreateWindow(
		"sdl-template",
		SDL_WINDOWPOS_UNDEFINED,
		SDL_WINDOWPOS_UNDEFINED,
		540,
		960,
		SDL_WINDOW_INPUT_GRABBED
	);

	this->screen = new Screen(this->window);

	this->sprites.push_back(new Board(this->screen));
}

Game::~Game()
{
	this->screen->~Screen();
	SDL_DestroyWindow(this->window);
	SDL_Quit();
}

void Game::start()
{
	//Timer related
	const uint8_t fps_max = 30;

	uint64_t last_frame_time = 0;
	uint64_t current_time = 0;

	while(true)
	{
		//Limit frame rate
		current_time = SDL_GetTicks64();

		if((current_time - last_frame_time) < (1000 / fps_max))
		{
			SDL_Delay(1000 / fps_max);
			continue;
		}

		last_frame_time = current_time;

		this->processEvents();
		this->draw();
	}
}

void Game::processEvents()
{
	SDL_Event event;

	while(SDL_PollEvent(&event))
	{
		if(event.type == SDL_QUIT) //User quits
		{
			this->~Game();
		}
		else if(event.type == SDL_MOUSEBUTTONUP) //User clicks
		{
			//Global coords
			SDL_FPoint coords = { (float)event.button.x, (float)event.button.y};

			for(auto &sprite : this->sprites)
			{
				if(SDL_PointInFRect(&coords, &sprite->bounds))
				{
					sprite->onBoundsClick(event.button);
				}
			}
		}
	}
}

void Game::draw()
{
	this->screen->clear();
	for(auto &sprite : this->sprites)
	{
		sprite->draw();
	}
	this->screen->update();
}
