#include "game.h"
#include <math.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_surface.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#include "scaller.h"
#include "scene.h"
#include "text.h"
#include "input.h"


#define GRAVITY 10000.f

static Mix_Music * music;
static Mix_Chunk * petMusic;
static Mix_Chunk * koMusic;


Scene_t gameScene;

static bool isSpaceKeypressed = false;
static float deltaAccu = 0;
static bool crashed = false;
static const float startPersonPositionX = CAMERA_WIDTH * 0.18f;
static const float startPersonPositionY = CAMERA_HEIGHT * 0.4f;
static float personPositionX = startPersonPositionX;
static float personPositionY = startPersonPositionY;

static const float startPersonVelocityX = 200;
static float personVelocityX = 200;
static float personVelocityY = 0;

float jetons = 0.f;

static RenderId_t personId;
RenderObject_t scoreText;
static RenderId_t scoreTextId = -1;
static int victimHeight;

static RenderId_t pressSpaceShadowId;
static RenderId_t pressSpaceTextId;

#define VICTIME_COUNT 4
#define VICTIME_SIZE 0.5f
RenderId_t victims[VICTIME_COUNT];

#define ADAME_KEYFRAMES 7
RenderId_t adame[ADAME_KEYFRAMES];
static float adame_accu = 0;
static int adame_id;
static bool kicked = false;
#define ADAME_SPEED 1.f/250
#define ADAME_SIZE 2.5f
#define ADAME_Y round(CAMERA_HEIGHT * 0.30f)
#define ADAME_X round(CAMERA_WIDTH * 0.01f)

static RenderObject_t strengthBar;
static RenderId_t strengthBarId;
static float strength = 0.f;
static bool increaseStrength = true;

static float adameStrength = 2.f; // this value is not const as it will be possible to improve the strenght of Adame.

static RenderObject_t strengthBarSlider;
static float strengthBarSliderDistance = 0.f;
static RenderId_t strengthBarSliderId;
static bool increaseStrengthBarSlider = true;

#define STEROIDS_POSITION CAMERA_WIDTH * 0.4f
#define SLIDER_SPEED ((adameStrength *0.5f)/5000)

void game_handleFKeyInput(void);

static RenderId_t backgrounds[2];
static int currentBackground = 0;
static int backgroundOffset = 0;
static int backgroundStep;

RenderId_t steroidText;


static void playMusic(){
	music = Mix_LoadMUS("./assets/music/game.wav");
	if(music == NULL) {
		fprintf(stderr, "Game audio not found!\n");
		exit(1);
	}

	petMusic = Mix_LoadWAV("./assets/music/pet.mp3");
	if(petMusic == NULL){
		fprintf(stderr, "Pet audio not found!\n");
		exit(1);
	}

	koMusic = Mix_LoadWAV("./assets/music/ko-effect-gain.mp3");
	if(koMusic == NULL){
		fprintf(stderr, "ko effect audio not found!\n");
		exit(1);
	}

	if(Mix_PlayMusic(music, 0) != 0){
		printf("Music sound could not be played!\n"
			"SDL_Error: %s\n", Mix_GetError());
		Mix_FreeMusic(music);
		running = false;
	}
}

int game_staticRender(void){
	input_listenKeyDown(SDL_SCANCODE_F, game_handleFKeyInput);
	playMusic();
	srand(time(NULL));

	MonitorSize_t size = renderer_getMonitorSize();
	float aspectRatio = (float)size.width / size.height;

	SDL_Surface* gameBackgroundSurface = IMG_Load("./assets/img/game_bg.png");
	if(gameBackgroundSurface == NULL){
		printf("cannot load background");
		return -1;
	}


	RenderObject_t gameBackground = EMPTY_RENDER_OBJECT;
	strcpy(gameBackground.name, "gameBackground");
	gameBackground.z = 0;
	gameBackground.surface = gameBackgroundSurface;
	scaller(gameBackground.surface, 1, &gameBackground.width, &gameBackground.height);
	gameBackground.height = 1;
	backgrounds[0] = scene_addRenderObject(&gameScene, gameBackground, 0, 0);
	backgrounds[1] = scene_addRenderObject(&gameScene, gameBackground, gameBackground.width * CAMERA_WIDTH, 0);
	backgroundStep = gameBackground.width * CAMERA_WIDTH;

	SDL_Surface* buildingSurface = IMG_Load("./assets/img/building.png");
	RenderObject_t building = EMPTY_RENDER_OBJECT;
	strcpy(building.name, "building");
	building.z = 9;
	building.surface = buildingSurface;
	building.width = 0.25;
	building.height = 1;
	scene_addRenderObject(&gameScene, building, 0, 0);


	SDL_Surface* victim1 = IMG_Load("./assets/img/victim_1.png");
	RenderObject_t person1 = EMPTY_RENDER_OBJECT;
	strcpy(person1.name, "person1");
	person1.z = 9;
	person1.surface = victim1;
	person1.width = 0.25f;
	scaller(person1.surface, 0.5f, &person1.width, &person1.height);
	victims[0] = scene_addRenderObject(&gameScene, person1, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* victim2 = IMG_Load("./assets/img/victim_2.png");
	RenderObject_t person2 = EMPTY_RENDER_OBJECT;
	strcpy(person2.name, "person2");
	person2.z = 9;
	person2.surface = victim2;
	person2.width = 0.25f;
	scaller(person2.surface, 0.5f, &person2.width, &person2.height);
	victims[1] = scene_addRenderObject(&gameScene, person2, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* victim3 = IMG_Load("./assets/img/victim_3.png");
	RenderObject_t person3 = EMPTY_RENDER_OBJECT;
	strcpy(person3.name, "person3");
	person3.z = 9;
	person3.surface = victim3;
	person3.width = 0.25f;
	scaller(person3.surface, 0.5f, &person3.width, &person3.height);
	victims[2] = scene_addRenderObject(&gameScene, person3, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* victim4 = IMG_Load("./assets/img/victim_4.png");
	RenderObject_t person4 = EMPTY_RENDER_OBJECT;
	strcpy(person4.name, "person4");
	person4.z = 9;
	person4.surface = victim4;
	person4.width = 0.25f;
	scaller(person4.surface, 0.5f, &person4.width, &person4.height);
	victims[3] = scene_addRenderObject(&gameScene, person4, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* adame1 = IMG_Load("./assets/img/adame_1.png");
	RenderObject_t adameObject1 = EMPTY_RENDER_OBJECT;
	strcpy(adameObject1.name, "adameObject1");
	adameObject1.z = 9;
	adameObject1.surface = adame1;
	adameObject1.width = 0.25f;
	scaller(adameObject1.surface, ADAME_SIZE, &adameObject1.width, &adameObject1.height);
	adame[0] = scene_addRenderObject(&gameScene, adameObject1, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* adame2 = IMG_Load("./assets/img/adame_2.png");
	RenderObject_t adameObject2 = EMPTY_RENDER_OBJECT;
	strcpy(adameObject2.name, "adameObject2");
	adameObject2.z = 9;
	adameObject2.surface = adame2;
	adameObject2.width = 0.25f;
	scaller(adameObject2.surface, ADAME_SIZE, &adameObject2.width, &adameObject2.height);
	adame[1] = scene_addRenderObject(&gameScene, adameObject2, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* adame3 = IMG_Load("./assets/img/adame_3.png");
	RenderObject_t adameObject3 = EMPTY_RENDER_OBJECT;
	strcpy(adameObject3.name, "adameObject3");
	adameObject3.z = 9;
	adameObject3.surface = adame3;
	adameObject3.width = 0.25f;
	scaller(adameObject3.surface, ADAME_SIZE, &adameObject3.width, &adameObject3.height);
	adame[2] = scene_addRenderObject(&gameScene, adameObject3, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* adame4 = IMG_Load("./assets/img/adame_4.png");
	RenderObject_t adameObject4 = EMPTY_RENDER_OBJECT;
	strcpy(adameObject4.name, "adameObject4");
	adameObject4.z = 9;
	adameObject4.surface = adame4;
	adameObject4.width = 0.25f;
	scaller(adameObject4.surface, ADAME_SIZE, &adameObject4.width, &adameObject4.height);
	adame[3] = scene_addRenderObject(&gameScene, adameObject4, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* adame5 = IMG_Load("./assets/img/adame_5.png");
	RenderObject_t adameObject5 = EMPTY_RENDER_OBJECT;
	strcpy(adameObject5.name, "adameObject5");
	adameObject5.z = 9;
	adameObject5.surface = adame5;
	adameObject5.width = 0.25f;
	scaller(adameObject5.surface, ADAME_SIZE, &adameObject5.width, &adameObject5.height);
	adame[4] = scene_addRenderObject(&gameScene, adameObject5, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* adame6 = IMG_Load("./assets/img/adame_6.png");
	RenderObject_t adameObject6 = EMPTY_RENDER_OBJECT;
	strcpy(adameObject6.name, "adameObject6");
	adameObject6.z = 9;
	adameObject6.surface = adame6;
	adameObject6.width = 0.25f;
	scaller(adameObject6.surface, ADAME_SIZE, &adameObject6.width, &adameObject6.height);
	adame[5] = scene_addRenderObject(&gameScene, adameObject6, 0, CAMERA_HEIGHT * 2);

	SDL_Surface* adame7 = IMG_Load("./assets/img/adame_7.png");
	RenderObject_t person7 = EMPTY_RENDER_OBJECT;
	strcpy(person7.name, "person7");
	person7.z = 9;
	person7.surface = adame7;
	person7.width = 0.25f;
	scaller(person7.surface, ADAME_SIZE, &person7.width, &person7.height);
	adame[6] = scene_addRenderObject(&gameScene, person7, 0, CAMERA_HEIGHT * 2);


	adame_id = 0;
	victimHeight = person1.height;
	personId = victims[rand() % 4];
	scene_moveRenderObject(&gameScene, adame[0], ADAME_X, ADAME_Y);

	scoreText = EMPTY_RENDER_OBJECT;
	strcpy(scoreText.name, "scoreText");
	SDL_Color black = {0, 0, 0, 255};
	text_renderText(&scoreText, 50, 0.5f, black, "./assets/fonts/Quinquefive.ttf", 40, "jetons: %lu", (unsigned long)jetons);
	scoreTextId = scene_addRenderObject(&gameScene, scoreText, gameScene.x + 2, 0);


	SDL_Surface* strengthBarSurface = IMG_Load("./assets/img/strengthBar.png");
	strcpy(strengthBar.name, "strengthBar");
	strengthBar.z = 100;
	strengthBar.surface = strengthBarSurface;
	strengthBar.width = 0.50f;
	strengthBar.height = 0.025f;
	strengthBarId = scene_addRenderObject(&gameScene, strengthBar, 0.30f * CAMERA_WIDTH, 0.9f * CAMERA_HEIGHT);


	SDL_Surface* strengthBarSliderSurface = IMG_Load("./assets/img/building.png");
	strcpy(strengthBarSlider.name, "strengthBarSlider");
	strengthBarSlider.z = 101;
	strengthBarSlider.surface = strengthBarSliderSurface;
	strengthBarSlider.width = 0.005f;
	strengthBarSlider.height = 0.05f;
	strengthBarSliderId = scene_addRenderObject(&gameScene, strengthBarSlider, 0.30f * CAMERA_WIDTH, 0.89f * CAMERA_HEIGHT);

	text_renderText(&scoreText, 50, 1.f, black, "./assets/fonts/Quinquefive.ttf", 20, "Press F to buy steroids for 200J");
	steroidText = scene_addRenderObject(&gameScene, scoreText, STEROIDS_POSITION, 0);

	RenderObject_t pressSpaceShadow = EMPTY_RENDER_OBJECT;
	strcpy(pressSpaceShadow.name, "pressSpaceShadow");
	text_renderText(&pressSpaceShadow, 50, 1, black, "./assets/fonts/Quinquefive.ttf", 20, "Press space to teach respect");
	pressSpaceShadowId = scene_addRenderObject(&gameScene, pressSpaceShadow, 0.30f * CAMERA_WIDTH, 0.8f * CAMERA_HEIGHT);


	RenderObject_t pressSpaceText = EMPTY_RENDER_OBJECT;
	strcpy(pressSpaceText.name, "pressSpaceText");
	SDL_Color white = {255, 255, 255, 255};
	text_renderText(&pressSpaceText, 50, 1, white, "./assets/fonts/Quinquefive.ttf", 20, "Press space to teach respect");
	pressSpaceTextId = scene_addRenderObject(&gameScene, pressSpaceText, 0.295f * CAMERA_WIDTH, 0.82f * CAMERA_HEIGHT);

	return 0;
}

int game_render(float delta){
	deltaAccu += delta;

	if(personPositionX - backgroundOffset > backgroundOffset * 0.1f) {
		currentBackground = 1 - currentBackground;
		backgroundOffset += backgroundStep;
		scene_moveRenderObject(&gameScene, backgrounds[currentBackground], backgroundOffset, 0);
	}

	if(!isSpaceKeypressed && !crashed && deltaAccu >= SLIDER_SPEED){
		if(increaseStrengthBarSlider && strengthBarSliderDistance >= 0.50f)
			increaseStrengthBarSlider = false;
		else if(increaseStrengthBarSlider){
			strengthBarSliderDistance += 0.005f;
			scene_moveRenderObject(&gameScene, strengthBarSliderId, 0.30f * CAMERA_WIDTH + strengthBarSliderDistance * CAMERA_WIDTH, 0.89f * CAMERA_HEIGHT);
		}
		else if(!increaseStrengthBarSlider && strengthBarSliderDistance <= 0.0001f)
			increaseStrengthBarSlider = true;
		else{
			strengthBarSliderDistance -= 0.005f;
			scene_moveRenderObject(&gameScene, strengthBarSliderId, 0.30f * CAMERA_WIDTH + strengthBarSliderDistance * CAMERA_WIDTH, 0.89f * CAMERA_HEIGHT);
		}

		deltaAccu = 0;
	}

	if(strength != 0 && !kicked && isSpaceKeypressed) {
		adame_accu += delta;
		printf("%f\n", adame_accu);
		if(adame_accu >= ADAME_SPEED / strength) {
			scene_moveRenderObject(&gameScene, adame[adame_id], 0, CAMERA_HEIGHT * 2);
			if(adame_id == 6) {
				scene_moveRenderObject(&gameScene, adame[0], ADAME_X, ADAME_Y);
				adame_id = 0;
				kicked = true;
				if(strength > 1.5){
					if(Mix_PlayChannel(-1, koMusic, 0) != 0){
						printf("Music sound could not be played!\n"
							"SDL_Error: %s\n", Mix_GetError());
						Mix_FreeChunk(koMusic);
					}
				}
				else{
					if(Mix_PlayChannel(-1, petMusic, 0) != 0){
						printf("Music sound could not be played!\n"
							"SDL_Error: %s\n", Mix_GetError());
						Mix_FreeChunk(petMusic);
					}
				}
			} else {
				adame_id++;
				scene_moveRenderObject(&gameScene, adame[adame_id], ADAME_X, ADAME_Y);
				adame_accu = 0;
			}
		}
	}

	// if(!crashed && deltaAccu >= SPEED && isSpaceKeypressed){
	if(!crashed && kicked){
		const float distance = personVelocityX * delta;
		personPositionX += distance;
		gameScene.x = personPositionX - startPersonPositionX;

		personVelocityY += GRAVITY * delta;

		personPositionY += personVelocityY * delta;
		jetons += distance;
		if(jetons > (float)ULONG_MAX)
			jetons = (float)ULONG_MAX;
		scene_moveRenderObject(&gameScene, scoreTextId, gameScene.x + 2, 0);

		if(personPositionY + CAMERA_HEIGHT * victimHeight >= CAMERA_HEIGHT - 18){
			crashed = true;
			scene_removeRenderObject(&gameScene, scoreTextId);
			SDL_Color black = {0, 0, 0, 255};
			text_renderText(&scoreText, 50, 0.5f, black, "./assets/fonts/Quinquefive.ttf", 40, "jetons: %lu", (unsigned long)jetons);
			scoreTextId = scene_addRenderObject(&gameScene, scoreText, gameScene.x + 2, 0);
		}
	}

	scene_moveRenderObject(&gameScene, steroidText, STEROIDS_POSITION + gameScene.x, 0);
	scene_moveRenderObject(&gameScene, personId, personPositionX, personPositionY);

	return 0;
}

void game_remove(void){
	scene_free(&gameScene);
	Mix_FreeMusic(music);
}

void game_handleFKeyInput(void) {
	printf("coucou %f\n", jetons);
	if(jetons > 200) {
		jetons -= 200;
		adameStrength += 0.5f;
		scene_removeRenderObject(&gameScene, scoreTextId);
		SDL_Color black = {0, 0, 0, 255};
		text_renderText(&scoreText, 50, 0.5f, black, "./assets/fonts/Quinquefive.ttf", 40, "jetons: %lu", (unsigned long)jetons);
		scoreTextId = scene_addRenderObject(&gameScene, scoreText, gameScene.x + 2, 0);
	}
}

void game_handleSpaceKeyInput(void){
	#ifdef DEBUG
	if(isSpaceKeypressed == true && !crashed)return;
	#endif
	if(crashed){
		crashed = false;
		personPositionX = startPersonPositionX;
		personPositionY = startPersonPositionY;
		personVelocityX = startPersonVelocityX;
		personVelocityY = 0;
		isSpaceKeypressed = false;
		gameScene.x = 0;
		gameScene.y = 0;
		strengthBarSliderDistance = 0.f;
		scene_moveRenderObject(&gameScene, scoreTextId, gameScene.x + 2, 0);
		scene_moveRenderObject(&gameScene, strengthBarId, 0.30f * CAMERA_WIDTH, 0.9 * CAMERA_HEIGHT);
		scene_moveRenderObject(&gameScene, personId, 0, CAMERA_HEIGHT * 2);
		personId = victims[rand() % 4];
		kicked=false;

		backgroundOffset = 0;
		currentBackground = 0;
		scene_moveRenderObject(&gameScene, backgrounds[0], 0, 0);
		scene_moveRenderObject(&gameScene, backgrounds[1], backgroundStep, 0);
	} else{
		isSpaceKeypressed = true;
		strength = - 32 * powf(fabs(strengthBarSliderDistance - 0.5f/2), 2) + 2;
		personVelocityX *= strength * adameStrength;
		scene_moveRenderObject(&gameScene, strengthBarId, 0, CAMERA_HEIGHT * 2);
		scene_moveRenderObject(&gameScene, strengthBarSliderId, 0, CAMERA_HEIGHT * 2);
		scene_removeRenderObject(&gameScene, pressSpaceShadowId);
		scene_removeRenderObject(&gameScene, pressSpaceTextId);
	}
}


// press space to teach respect
