/*
 * Game.cpp
 *
 *  Created on: Feb 9, 2020
 *      Author: ayoungblood
 *      Special Thanks to: Carl Birch of Let's Make Games
 *      				   Nic Allen
 *      				   Brian Lhota
 */

#include "Game.hpp"
#include "../assetmgr/TextureManager.h"
#include "../assetmgr/Map.h"
#include "../ecs/Components.h"
#include "Collision.h"
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include "../assetmgr/AssetManager.h"
#include "../ui/UIText.h"
#include "../ui/UINineSlice.h"
#include "../cjson/cJSON.h"

Map* map;
Manager manager;
UIText* text;
UINineSlice* my9Slice;
UIText* scoreboardText;
UINineSlice* scoreboard9Slice;

SDL_Renderer* Game::renderer = nullptr;
SDL_Event Game::event;

SDL_Rect Game::camera;

AssetManager* Game::assets = new AssetManager(&manager);

bool Game::isRunning = false;

auto& player(manager.addEntity());

// auto& enemy(manager.addEntity());
auto& puppy(manager.addEntity());

// auto& scoreboard(manager.addEntity());
auto& uiInfo(manager.addEntity());

bool Game::debugCollisionBoxes = false;

bool Game::gravityOnPlayer = true;

bool Game::playerIsGrounded = false;

int gScale = 0;

int last_time;
int current_time;
int diff_time;

Game::Game() {
	// TODO Auto-generated constructor stub

}

Game::~Game() {
	// TODO Auto-generated destructor stub
}

void Game::init(const char *title, int width, int height, bool fullscreen, int globalScale)
{
    camera = { 0, 0, width, height };
    int flags = 0;
    gScale = globalScale;
    if(fullscreen)
    {
        flags = SDL_WINDOW_FULLSCREEN;
    }

    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags);
        if(!window)
        {
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,"Couldn't create window: %s", SDL_GetError());
        }
        renderer = SDL_CreateRenderer(window, -1, 0);
        if(!renderer)
        {
        	SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s", SDL_GetError());
        	isRunning = false;
        }
        else
        {
        	SDL_SetRenderDrawColor(renderer, 255,255,255,255);
        	isRunning = true;
        }
        //Initialize SDL_mixer
        if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048)<0)
        {
        	SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Couldn't initialize SDL audio mixer!, Error: %s", SDL_GetError());
        }

//         current_time = SDL_GetTicks();
        
        assets->AddTexture("terrain", "assets/textures/tiles/br-tiles.png");
        assets->AddTexture("player", "assets/textures/actors/firefighter.png");
        assets->AddTexture("font", "assets/textures/ui/ui-font-cloud-sans.png");
        assets->AddTexture("textBox", "assets/textures/ui/ui-element-cloud.png");
        assets->AddTexture("puppy","assets/textures/actors/beaglepuppy.png");
        
        assets->AddMusicTrack("simonZ","assets/audio/music/sillypuppy.ogg");
        assets->AddMusicTrack("simonZ","assets/audio/music/victory.ogg");
        
        assets->AddSoundClip("bwoop","assets/audio/sfx/bwoop.wav");
        assets->AddSoundClip("bark1","assets/audio/sfx/Bark1.wav");        
        assets->AddSoundClip("bark2","assets/audio/sfx/Bark2.wav");
        
        map = new Map("terrain",globalScale,16);

        const char* myText = "Find lost puppies!";
        text = new UIText(myText, "font", 0, 0, 8, 12, globalScale);
        text->ParseString(myText, 12, 22, globalScale);
        SDL_Rect myDestRect = SDL_Rect();
        myDestRect.x = 12;
        myDestRect.y = 8;
        myDestRect.w = 160;
        myDestRect.h = 40;
        my9Slice = new UINineSlice("textBox");
        my9Slice->MakeSlices("textBox",32,32,14,16,14,16,myDestRect,globalScale);
        
        //ecs implementation

        map->LoadMap("assets/maps/br-map-color.txt",70,45, globalScale);

        player.addComponent<TransformComponent>(860*globalScale,630*globalScale,22,42,globalScale);
//         player.addComponent<TransformComponent>(150*globalScale,80*globalScale,40,40,globalScale);
        player.addComponent<SpriteComponent>("player", SpriteComponent::spriteAnimation, "assets/textures/actors/firefighter.json");
        player.addComponent<KeyboardController>();
        player.addComponent<ColliderComponent>("player");
        player.addGroup(groupPlayers);
        
        puppy.addComponent<TransformComponent>(1024*globalScale,210*globalScale,36,30,globalScale);
        puppy.addComponent<SpriteComponent>("puppy", SpriteComponent::spriteObject);
        puppy.addGroup(groupObjects);
        
//         enemy.addComponent<TransformComponent>(180*globalScale,180*globalScale,32,32,globalScale);
//         enemy.addComponent<SpriteComponent>("robber", SpriteComponent::spriteAnimation, "assets/textures/actors/robberrodent.json");
//         enemy.addGroup(groupEnemies);
        
    } else {
    		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't Initialize SDL: %s", SDL_GetError());
            isRunning = false;
    }
}

//camera.x = camera.x*globalScale;

auto& tiles(manager.getGroup(Game::groupMap));
auto& players(manager.getGroup(Game::groupPlayers));
auto& colliders(manager.getGroup(Game::groupColliders));
auto& objects(manager.getGroup(Game::groupObjects));
// auto& enemies(manager.getGroup(Game::groupEnemies));
// auto& projectiles(manager.getGroup(Game::groupProjectiles));
auto& gui(manager.getGroup(Game::groupUI_Layer0));
auto& uiText(manager.getGroup(Game::groupUI_Layer1));


void Game::handleEvents()
{
    SDL_PollEvent(&event);
    switch (event.type)
    {
    case SDL_QUIT:
    	isRunning = false;
    	break;
    default:
    	break;
    }

}

void Game::update()
{
	SDL_Rect playerCol = player.getComponent<ColliderComponent>().collider;
	Vector2D playerPos = player.getComponent<TransformComponent>().position;
    
	if (Mix_PlayingMusic() == 0)
	{
//		std::cout << "Play Music Now" << std::endl;
		Mix_PlayMusic(assets->GetMusicTrack("simonZ"), -1);
	}
	
    if (Mix_PlayChannel(-1, Game::assets->GetSoundClip("bark1"),0) == 0)
    {
        Mix_PlayChannel(-1, Game::assets->GetSoundClip("bark1"),0);
    }

	manager.refresh();
	manager.update();

	for (auto& c : colliders)
	{
		SDL_Rect cCol = c->getComponent<ColliderComponent>().collider;
		if(Collision::AABB(cCol, playerCol))
		{
//             printf("Collision detected!\nplayerIsGrounded:%d if 0: idle plays\n",playerIsGrounded);
            if(!playerIsGrounded){
                player.getComponent<SpriteComponent>().Play("Idle");                
            }
            gravityOnPlayer = false;
            playerIsGrounded = true;


		}

	}
	
// 	Gravity
    if (gravityOnPlayer){
    player.getComponent<TransformComponent>().position.y += 10;
    }
// 	for(auto& p: projectiles)
// 	{
// 		if(Collision::AABB(player.getComponent<ColliderComponent>().collider, p->getComponent<ColliderComponent>().collider))
// 		{
// 			std::cout << "Projectile hit player" << std::endl;
// 			p->destroy();
// 		}
// 	}

	camera.x = player.getComponent<TransformComponent>().position.x - camera.w/2;
	camera.y = player.getComponent<TransformComponent>().position.y - camera.h/2;
    
	if(camera.x < 0)
		camera.x = 0;
	if (camera.y < 0)
		camera.y = 0;
	if (camera.x > map->width-camera.w)
		camera.x = map->width-camera.w;
	if (camera.y > map->height-camera.h)
		camera.y = map->height-camera.h;
}


void Game::render()
{
	SDL_RenderClear(renderer);

    for (auto& t : tiles)
	{
		t->draw();
	}
	if (Game::debugCollisionBoxes)
	{
		for (auto& c : colliders)
		{
			c->draw();
		}
	}
	
    for (auto& o : objects)
    {
        o->draw();
    }	
//     
// 	for (auto& e : enemies)
// 	{
// 		e->draw();
// 	}

	for (auto& p : players)
	{
		p->draw();
	}

	for (auto& guiElement : gui)
	{
		guiElement->draw();
	}
	for (auto& letter : uiText)
	{
		letter->draw();
	}
// 	Vector2D origPt;
//     Vector2D destPt;
//     origPt.Zero();
//     destPt.x = 320.0*gScale;
//     destPt.y = 240.0*gScale;
// 	drawLine(origPt,destPt,255,0,0);
	SDL_RenderPresent(renderer);
}

void Game::clean()
{
	SDL_DestroyWindow(window);
	SDL_DestroyRenderer(renderer);
	IMG_Quit();
	Mix_Quit();
	SDL_Quit();
	printf("Game Cleaned\n");
}

void Game::printDebug(char* debugInfo)
{
    printf("%s",debugInfo);
    printf("\n");
}

// void Game::drawLine(Vector2D srcpt, Vector2D destpt, int red, int green, int blue)
// {
//     SDL_SetRenderDrawColor(renderer, red, green, blue, 255);
//     SDL_RenderDrawLine(renderer, srcpt.x, srcpt.y, destpt.x, destpt.y);
// }
