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

#include "breakout.h"
#include "vector.h"
#include "startmenu.h"
#include "gamestate.h"
#include "highscores.h"
#include "settings.h"
#include "background.h"

#include "main.h"

// Default Render Size (Upscaled for bigger monitors)
const int width = 1920;
const int height = 1080;
float XScale = 1.0f, YScale = 1.0f;
// End render properties

int numKeys;
const Uint8 * keystate; // TODO: export all this into scenery and enemy waves
SDL_Window * window;
SDL_Renderer * renderer;
SDL_Event event;
bool running = true, fullscreen = false;
GameState gameState = MainMenu;
Scenery scenery;

int main(int argc, char * args[]){
    // printf("Spielbereiche\n\t- 1: Hauptmen"ue "\n\t- 2: Spiel\n\t- 3: Level Select\n\t- 4: Settings\n\t- 5: Highscores\n");
    // GAME_ChangeState(readIntFromIO("W"ae "hle einen Spielbereich aus, den du testen m"oe "chtest:", "Fehlerhafte Eingabe!\n", "%d ist kein g"ue "ltiger Spielbereich!\n", 1, 5));
    INITIALIZE();
    while (running) { // Gameloop
        HandleSDLEvents();
        DrawBackground(renderer);
        switch (gameState) {
            case Game:
                BREAKOUT_Update(&scenery, keystate);
                BACKGROUND_Draw(renderer, 0);
                BREAKOUT_Draw(&scenery, renderer);
                break;
            case MainMenu:
                // Startmenu_Update(keystate);
                Startmenu_Draw(renderer);
                break;
            case Highscores:
                HIGHSCORES_Draw(renderer);
                break;
            case Settings:
                Settings_Draw(renderer);
                break;
            default:
                printf("Unknow state was updated: %d\n", gameState);
                break;
        }
        SDL_RenderPresent(renderer);
    }
    QUIT();
    return 0;
} /* main */

void GAME_Escape(){
    running = false;
    printf("GAME_Escape was called!\n");
}

void GAME_ChangeState(GameState state){
    if (gameState == state) {
        printf("State wasn't changed!\n");
        return;
    }
    gameState = state;
    switch (gameState) {
        case Highscores:
            HIGHSCORES_ReloadList();
            HIGHSCORES_GenerateTexture(renderer);
            printf("State was changed to Highscores!\n");
            break;
        default:
            printf("State was changed to %d!\n", gameState);
            break;
    }
}

void HandleSDLEvents(){
    while (SDL_PollEvent(&event)) {
        switch (event.type) {
            case SDL_QUIT:
                printf("NOTICE: User manually quit window!\n");
                running = false;
                break;
            case SDL_KEYDOWN:
                // if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) running = false;
                // else
                keyPress(event.key);
                break;
            case SDL_MOUSEBUTTONDOWN:
                mousePress(event.button);
                button_clicked(event.button, gameState);
                break;
            case SDL_WINDOWEVENT:
                windowChanged(event.window);
                break;
        }
    }
} /* HandleSDLEvents */

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

void keyPress(SDL_KeyboardEvent b){ // Debug prop
    printf("Key pressed: ID is %d\n", b.keysym.scancode);
    if (b.keysym.scancode == SDL_SCANCODE_F11 || b.keysym.scancode == SDL_SCANCODE_5) {
        toggleFullscreen();
    }
}

void toggleFullscreen(){
    if (fullscreen) {
        SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
    } else {
        SDL_SetWindowFullscreen(window, 0);
    }
    fullscreen = !fullscreen;
}

void windowChanged(SDL_WindowEvent b){ // Debug prop
    switch (b.event) {
        case SDL_WINDOWEVENT_SIZE_CHANGED:
            printf("Window was resized to (%d|%d)!\n", event.window.data1, event.window.data2);
            // BREAKOUT_ChangeSize(event.window.data1, event.window.data2);
            XScale = ((double)(event.window.data1) / (double)width);
            YScale = ((double)(event.window.data2) / (double)height);
            SDL_RenderSetScale(renderer, XScale, YScale);
            break;
    }
}

void DrawBackground(SDL_Renderer * renderer){
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);
} /* DrawFrame */

void INITIALIZE() {
    printf("Initializing started...\n");
    srand(time(NULL));
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0) printf("SDL could not initialize! Error: %s\n", SDL_GetError());
    else printf("SDL was successfully initialized!\n");
    keystate = SDL_GetKeyboardState(&numKeys);
    if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) printf("IMG could not initialize! Error: %s\n", IMG_GetError());
    else printf("IMG was successfully initialized!\n");
    if (TTF_Init() == -1) printf("TTF could not initialize! Error: %s\n", TTF_GetError());
    else printf("TTF was successfully initialized!\n");

    window = SDL_CreateWindow("BreakING", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
    SDL_SetWindowResizable(window, true);
    printf("Window was created!\n");
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    printf("Renderer was created!\n");
    BREAKOUT_INITIALIZE(renderer, width, height);
    scenery = BREAKOUT_CreateDefault();
    Load_Textures(renderer);
    HIGHSCORES_Initialize();
    BACKGROUND_Initialize(renderer, width, height);
    Settings_Initialize(renderer);
    printf("Initializing finished!\n");
} /* INITIALIZE */

void QUIT(){
    printf("De-initializing started...\n");
    BACKGROUND_Deinitialize();
    Settings_Deinitialize();
    HIGHSCORES_Deinitialize();
    BREAKOUT_DestroyObject(&scenery);
    BREAKOUT_DEINITIALIZE();
    TTF_Quit();
    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 */

int readIntFromIO(char * m1, char * m2, char * m3, int min, int max){
    int nitems, num;

    while (1) {
        while (1) {
            printf(m1);
            nitems = scanf("%d", &num);
            if (nitems == 0) {
                printf(m2);
                fflush(stdin);
                continue;
            } else {
                break;
            }
        }
        if ((num < min) || (num > max)) {
            printf(m3, num);
        } else {
            break;
        }
    }
    fflush(stdin);
    return(num);
} /* readIntFromIO */
