#include <iostream>
#include <SDL.h>
#include <cmath>
#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 SDL!",
                                       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;
    }

    // Loading
    const string file0("cruiser_on.png");
    const string file1("cruiser.png");
    const string file2("cruiser_ftl.png");
    const string file3("base.jpg");
    const string file4("pierres.bmp");
    SDL_Texture *cruiser_on(loadTexture(file0, ren));
    SDL_Texture *cruiser_off(loadTexture(file1, ren));
    SDL_Texture *cruiser_ftl(loadTexture(file2, ren));
    SDL_Texture *background1(loadTexture(file3, ren));
    SDL_Texture *background2(loadTexture(file4, ren));
    if (cruiser_on == nullptr || cruiser_off == nullptr || cruiser_ftl == nullptr ||
        background1 == nullptr || background2 == nullptr) {

        SDL_DestroyTexture(cruiser_on);
        SDL_DestroyTexture(cruiser_off);
        SDL_DestroyTexture(cruiser_ftl);
        SDL_DestroyTexture(background1);
        SDL_DestroyTexture(background2);
        SDL_DestroyRenderer(ren);
        SDL_DestroyWindow(win);
        SDL_Quit();
        return 1;
    }

    //Set standard alpha blending
    SDL_SetTextureBlendMode(background1, SDL_BLENDMODE_BLEND);
    SDL_SetTextureBlendMode(background2, SDL_BLENDMODE_BLEND);

    // Events
    Input myInput;

    // Time
    Uint32 prevTime(0);
    Uint32 waitTime(1000 / 60);

    // Drawing
    SDL_Texture *cruiser(cruiser_off);
    SDL_Texture *background(background1);

    int backW, backH;
    SDL_QueryTexture(background, NULL, NULL, &backW, &backH);
    double angle(0.0);
    float bx(0), by(0);
    float speed(0.0f);
    Uint8 ftlLevel(0);
    bool ftlTriggered(false);

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

        // Movement
        if (myInput.getMouseKey(1)) {
            cruiser = cruiser_on;
            speed += 0.05f;

            if (ftlLevel > 0)
                ftlLevel--;
        } else if (myInput.getMouseKey(3)) {
            if (ftlLevel < 255) {
                ftlLevel++;
            } else if (!ftlTriggered) {
                ftlTriggered = true;
                if (background == background1)
                    background = background2;
                else
                    background = background1;
                SDL_QueryTexture(background, NULL, NULL, &backW, &backH);
            }
            cruiser = cruiser_ftl;
        } else {
            cruiser = cruiser_off;
            speed *= 0.99f;

            if (ftlLevel > 0)
                ftlLevel--;
            else
                ftlTriggered = false;
        }

        by += speed * sin(-angle * M_PI_2 / 90.0);
        bx -= speed * cos(-angle * M_PI_2 / 90.0);

        if (by < -backH)
            by += backH;

        if (by > 0)
            by -= backH;

        if (bx < -backW)
            bx += backW;

        if (bx > 0)
            bx -= backW;

        // Reset renderer
        SDL_RenderClear(ren);

        // Background
        SDL_SetTextureAlphaMod(background, (Uint8) 255 - ftlLevel);

        for (int x((int) bx); x < SCREEN_WIDTH; x += backW) {
            for (int y((int) by); y < SCREEN_HEIGHT; y += backH) {
                renderTexture(background, ren, x, y);
            }
        }

        // Foreground
        SDL_SetTextureColorMod(cruiser, (Uint8) 255 - ftlLevel, (Uint8) 255 - ftlLevel, 255);
        angle = myInput.getX() * 360.0 / SCREEN_WIDTH + 90.0;
        renderTexture(cruiser, ren, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, angle, true);

        // Render
        SDL_RenderPresent(ren);

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

    // End
    SDL_DestroyTexture(background1);
    SDL_DestroyTexture(background2);
    SDL_DestroyTexture(cruiser_on);
    SDL_DestroyTexture(cruiser_off);
    SDL_DestroyTexture(cruiser_ftl);
    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(win);
    SDL_Quit();
    return 0;
}