#include <SDL2/SDL.h>
#include <iostream>

const int ScreenWidth = 1280;
const int ScreenHeight = 720;

void logSDLError(std::ostream &os, const std::string &msg){
        os << msg << " error: " << SDL_GetError() << std::endl;
}

void ApplySurface(int x, int y, SDL_Texture *tex, SDL_Renderer *rend){
   SDL_Rect pos;
   pos.x = x;
   pos.y = y;
   SDL_QueryTexture(tex, NULL, NULL, &pos.w, &pos.h);
   SDL_RenderCopy(rend, tex, NULL, &pos);
}

void renderLoop(SDL_Texture *texture, SDL_Texture *background, SDL_Renderer *renderer, int x, int y) {
//    ApplySurface(0,0,background,renderer);
    SDL_RenderCopy(renderer, background, NULL, NULL);
    ApplySurface(x,y,texture,renderer);
}

void kbdHandler(bool &quit, int &x, int &y, SDL_Event event)
{
    switch (event.key.keysym.sym) {
    case SDLK_UP:
        y-=2;
        break;
    case SDLK_DOWN:
        y+=2;
        break;
    case SDLK_LEFT:
        x-=2;
        break;
    case SDLK_RIGHT:
        x+=2;
        break;
    case SDLK_ESCAPE:
        quit = true;
        break;
    }
}
void physLoop(int &x, int &y, int &dx, int &dy)
{
    x += dx;
    y += dy;
}
void loop(SDL_Renderer *renderer, SDL_Texture *cat, SDL_Texture *background){
    SDL_Event e;
    bool quit = false;
    int x = 0, y = 0;
    while (!quit){
        int dx = 0, dy = 0;
        while (SDL_PollEvent(&e)){
                if (e.type == SDL_QUIT){
                        quit = true;
                }
                if (e.type == SDL_KEYDOWN){
                    kbdHandler(quit,x,y,e);
                }
                if (e.type == SDL_MOUSEBUTTONDOWN){
                        quit = true;
                }
        }

        physLoop(x,y,dx,dy);
        //Render the scene
        SDL_RenderClear(renderer);
        renderLoop(cat, background, renderer, x, y);
        SDL_RenderPresent(renderer);
//        SDL_Delay(1000);
    }
}

SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren){
        //Initialize to nullptr to avoid dangling pointer issues
        SDL_Texture *texture = nullptr;
        //Load the image
        SDL_Surface *loadedImage = SDL_LoadBMP(file.c_str());
        //If the loading went ok, convert to texture and return the texture
        if (loadedImage != nullptr){
                texture = SDL_CreateTextureFromSurface(ren, loadedImage);
                SDL_FreeSurface(loadedImage);
                //Make sure converting went ok too
                if (texture == nullptr){
                        logSDLError(std::cout, "CreateTextureFromSurface");
                }
        }
        else {
                logSDLError(std::cout, "LoadBMP");
        }
        return texture;
}

int main()
{
	//sdl init
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
		std::cout << "err" << SDL_GetError() << std::endl;
	//window init
        SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, ScreenWidth, ScreenHeight, SDL_WINDOW_SHOWN);
	//renderer init
        SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

//        //load texture to ram
//        SDL_Surface *bmp = SDL_LoadBMP("test.bmp");
//        //load to gpu
//        SDL_Texture *cat = SDL_CreateTextureFromSurface(ren, bmp);
//        //remove texture from ram
//        SDL_FreeSurface(bmp);
//        //load texture to ram
//        *bmp = SDL_LoadBMP("bg.bmp");
//        //load to gpu
//        SDL_Texture *bg = SDL_CreateTextureFromSurface(ren, bmp);
//        //remove texture from ram
//        SDL_FreeSurface(bmp);
        SDL_Texture *cat = loadTexture("text.bmp", ren);
        SDL_Texture *bg = loadTexture("bg.bmp",ren);
        //loop
        loop(ren,cat,bg);

	//deinit
        SDL_DestroyTexture(cat);
        SDL_DestroyTexture(bg);
	SDL_DestroyRenderer(ren);
	SDL_DestroyWindow(win);
	SDL_Quit();

	return 0;
}
