#include <iostream>
#include <SDL2/SDL.h>
#include <box2d/box2d.h>
#include "texturer.h"
#include "Input.h"

using namespace std;

int main() {
    // Start
    cout << "SDL2 app is loading..." << endl;

    // Useful data
    const int SCREEN_WIDTH = 1200;
    const int SCREEN_HEIGHT = 700;

    // Init video
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        logSDLError(cout, "SDL_Init(SDL_INIT_VIDEO)");
        return 1;
    }

    // Opening window
    SDL_Window *win = SDL_CreateWindow("Hello Box2D!",
                                       SDL_WINDOWPOS_UNDEFINED,
                                       SDL_WINDOWPOS_UNDEFINED,
                                       SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    if (win == nullptr) {
        logSDLError(cout, "SDL_CreateWindow");
        SDL_Quit();
        return 1;
    }

    // Create a renderer
    SDL_Renderer *ren = SDL_CreateRenderer(win, -1,
                                           SDL_RENDERER_ACCELERATED |
                                           SDL_RENDERER_PRESENTVSYNC);
    if (ren == nullptr) {
        SDL_DestroyWindow(win);
        logSDLError(cout, "SDL_CreateRenderer");
        SDL_Quit();
        return 1;
    }

    // Events
    Input myInput;

    // Time
    Uint32 frameRate(60);
    Uint32 prevTime(0);
    Uint32 waitTime(1000 / frameRate);
    float timeStep(1.0f / frameRate);

    int32 velocityIterations = 6;
    int32 positionIterations = 2;

    /// Physic
    // World
    b2Vec2 gravity(0.0f, 10.0f);
    b2World world(gravity);
    float zoom = 50.0f;

    // Defs
    b2BodyDef myBodyDef;
    b2PolygonShape myBox;

    // Ground body
    myBodyDef.position.Set(10.0f, 17.0f);
    b2Body* groundBody(world.CreateBody(&myBodyDef));

    myBox.SetAsBox(50.0f, 5.0f);

    groundBody->CreateFixture(&myBox, 0.0f); // Warning : simple function (no fixture)

    // Crate body
    myBodyDef.type = b2_dynamicBody;
    myBodyDef.position.Set(10.0f, -4.0f);
    b2Body* crateBody(world.CreateBody(&myBodyDef));

    myBox.SetAsBox(1.0f, 1.0f);

    b2FixtureDef myFixtureDef;
    myFixtureDef.shape = &myBox;
    myFixtureDef.density = 1.0f;
    myFixtureDef.friction = 0.3f;
    myFixtureDef.restitution = 0.3f;

    crateBody->CreateFixture(&myFixtureDef);

    while (!myInput.isFinished()) {
        // Update events
        myInput.updateEvents();

        // Update physic
        world.Step(timeStep, velocityIterations, positionIterations);

        // Reset renderer
        SDL_SetRenderDrawColor(ren, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(ren);

        // Foreground
        b2Vec2 pos(crateBody->GetPosition());
        float angle(crateBody->GetAngle());

        SDL_Rect fillRect = {(int)(pos.x * zoom), (int)(pos.y * zoom), 100, 100};
        SDL_SetRenderDrawColor(ren, 0xFF, 0x00, 0x00, 0xFF);
        SDL_RenderFillRect(ren, &fillRect);

        // Render
        SDL_RenderPresent(ren);

        // Pause
        if (SDL_GetTicks() < prevTime + waitTime)
            SDL_Delay(waitTime + prevTime - SDL_GetTicks());
        prevTime = SDL_GetTicks();
    }

    // End
    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(win);
    SDL_Quit();
    return 0;
}