#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#include <math.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>

#include "vector.h"
#include "asteroids.h"
#include "starfield.h"

#ifndef __nullptr__
#define Nullptr(type) (type *)0
#endif // __nullptr__

void DrawFrame();
void INITIALIZE();
void QUIT();
void GAMELOOP();
void mousePress(SDL_MouseButtonEvent b);

const int width = 1600; // TODO: Fullscreen
const int height = 900;
const int totalAsteroidCount = 6;
const int totalEnemyCount = 6;

Uint8 * keystate; // TODO: export all this into scenery and enemy waves
SDL_Window * window;
SDL_Renderer * renderer;
SDL_Event event;
bool running = true;
SDL_Color messageColor;
TTF_Font * Sans;
SDL_Surface * messageSurface;
SDL_Rect messageRect;
SDL_Texture * messageTexture;
Asteroid * asteroids;
Ship ship;
Enemy * enemies;
Starfield starfield;
int asteroidCount = 0, enemyCount = 0;

int main(int argc, char * args[]){
    INITIALIZE();
    while (running) {
        GAMELOOP();
        DrawFrame();
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    running = false;
                    break;
                case SDL_KEYDOWN:
                    if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) running = false;
                    break;
                case SDL_MOUSEBUTTONDOWN:
                    mousePress(event.button);
                    break;
            }
        }
    }
    QUIT();
    return 0;
} /* main */

void GAMELOOP() {
    keystate = SDL_GetKeyboardState(NULL);     // Get key changes
    SHIP_Update(&ship, keystate, asteroids, &asteroidCount, enemies, &enemyCount);
    int i;
    for (i = 0; i < enemyCount; i++) {
        ENEMY_Update(&(enemies[i]), &ship, 1);
    }
    STARFIELD_Update(&starfield);
    if (!(ship.IsDead)) {
        for (i = 0; i < asteroidCount; i++) {
            ASTEROID_Update(&(asteroids[i]));
        }
    }
} /* GAMELOOP */

void mousePress(SDL_MouseButtonEvent b){
    if (b.button == SDL_BUTTON_LEFT) {
        printf("Left mouse pressed...\n");
    } else if (b.button == SDL_BUTTON_RIGHT) {
        printf("Right mouse pressed...\n");
    } else {
        printf("Unknown mouse button pressed: %d\n", b.button);
    }
}

void DrawFrame(){
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);
    STARFIELD_Draw(&starfield, renderer); // Z-Layer Background
    int i;
    for (i = 0; i < asteroidCount; i++) { // Z-Layer Bottom
        ASTEROID_Draw(&(asteroids[i]), renderer);
    }
    for (i = 0; i < enemyCount; i++) { // Z-Layer Mid
        ENEMY_Draw(&(enemies[i]), renderer);
    }
    SHIP_Draw(&ship, renderer); // Z-Layer Top
    // SDL_RenderCopy(renderer, messageTexture, NULL, &messageRect);
    SDL_RenderPresent(renderer);
}

void INITIALIZE() {
    srand(time(NULL));
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0) printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
    else printf("SDL was successfully initialized!\n");
    if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) printf("IMG could not initialize! IMG_Error: %s\n", IMG_GetError());
    else printf("IMG was successfully initialized!\n");
    TTF_Init();

    Sans = TTF_OpenFont("assets/fonts/bulky.ttf", 12);
    if (!Sans) printf("Font cannot be initialized!\n");
    else printf("Font was successfully initialized!\n");
    messageColor = (SDL_Color) {.r = 125, .g = 255, .b = 125, .a = 255 };
    messageSurface = TTF_RenderText_Solid(Sans, "A", messageColor);
    if (!messageSurface) printf("Text surface is null!\n");
    else printf("Text surface was created!\n");
    messageTexture = SDL_CreateTextureFromSurface(renderer, messageSurface);
    if (!messageTexture) printf("Text texture is null!\n");
    else printf("Text texture was created!\n");
    messageRect = (SDL_Rect) {.x = 100, .y = 100, .w = (messageSurface->w), .h = (messageSurface->h) };

    window = SDL_CreateWindow("Asteroids Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
    printf("Window was created!\n");
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    printf("Renderer was created!\n");

    STARFIELD_Initialize(renderer, width, height);
    ASTEROIDS_InitializeGame(renderer, width, height);

    starfield = STARFIELD_GetDefault(100);
    ship = SHIP_CreateDefault();
    enemies = calloc(20, sizeof(Enemy));
    int i;
    enemies[enemyCount++] = ENEMY_GetDefault();
    asteroids = calloc(200, sizeof(Asteroid));
    for (i = 0; i < totalAsteroidCount; i++) {
        asteroids[asteroidCount++] = ASTEROID_CreateRandom();
    }
} /* INITIALIZE */

void QUIT(){
    printf("De-initializing started...\n");
    free(keystate);
    SDL_FreeSurface(messageSurface);
    SDL_DestroyTexture(messageTexture);
    SHIP_DestroyObject(&ship);
    int i;
    for (i = 0; i < enemyCount; i++) {
        ENEMY_DestroyObject(&(enemies[i]));
    }
    free(enemies);
    STARFIELD_DestroyObject(&starfield);
    STARFIELD_Deinitialize();
    ASTEROIDS_DeinitializeGame();
    TTF_CloseFont(Sans);
    TTF_Quit();
    free(asteroids);
    IMG_Quit();
    printf("Quitting SDL_IMG finished!\n");
    SDL_DestroyRenderer(renderer);
    printf("De-initializing renderer finished!\n");
    SDL_DestroyWindow(window);
    printf("De-initializing window finished!\n");
    SDL_Quit();
    printf("Quitting SDL finished!\n");
    printf("De-initializing finished!\n");
} /* QUIT */
