#include "jdraw.h"
#include <SDL2/SDL.h>
#include "gif.c"
#include "jfile.h"
#include <vector>

namespace draw
{
    // La idea de esta unitat es usar "superficies", que no son mes que arrays de bytes, per a anar pintant.
    // El resultat final s'ha de pintar en algun moment a la superficie "screen" (o siga, especificar nullptr en setDestination)
    // Aleshores, en "render" el contingut de screen se volca a la textura SDL que crearem,
    // i eixa textura se pintarà a pantalla com se sol fer amb SDL. Ho anirem veient en el codi.

    SDL_Window *sdl_window = nullptr;     // La finestra de SDL
    SDL_Renderer *sdl_renderer = nullptr; // El renderer de SDL
    SDL_Texture *sdl_texture = nullptr;   // La textura de SDL a la que pintarem la nostra superficie "screen" i que despres volcarem a pantalla

    SDL_Rect dest_rect = {0, 0, 320, 240};
    static int fullscreen_scale = 1;

    static int screen_zoom = 1;
    static bool screen_fullscreen = false;
    static int screen_width = 320;
    static int screen_height = 240;
    std::string screen_title = "";
    static int screen_mode = SCREEN_MODE_NORMAL;

    surface *screen = nullptr;      // La superficie screen, que representa la pantalla. Se crea i destrueix internament
    surface *destination = nullptr; // Punter a la actual superficie de destí
    surface *source = nullptr;      // Punter a la actual superficie d'oritge
    surface *pushedSource = nullptr;      // Punter a la superficie d'oritge que s'ha pushat

    uint32_t palette[256];          // La paleta de colors
    uint8_t color_indices[256];     // Indices dels colors per defecte
    uint8_t sel_color = 0;          // Color seleccionat per defecte
    uint8_t transparent = 0;        // El color transparent

    surface *textsurf = nullptr;    // Surface on guardar el gif amb la font
    surface *textsurf2 = nullptr;    // Surface on guardar el gif amb la font gran

    SDL_Rect viewport;

    surface* managed[50];
    int num_managed = 0;

    namespace stencil
    {
        static bool enabled = false;
        static uint8_t value = 0;
        static surface *stencil = nullptr;
        
        void init()
        {
            if (stencil) freeSurface(stencil);
            stencil = createSurface(screen->w, screen->h);
        }

        void enable() { enabled = true; }
        void disable() { enabled = false; }

        void clear(const uint8_t val)
        {
            if (!enabled || !stencil) return;
            memset(stencil->pixels, val, stencil->w*stencil->h);
        }

        void set(const uint8_t val)
        {
            if (!enabled || !stencil) return;
            value = val;
        }

        const uint8_t query(const int x, const int y)
        {
            if (!stencil) return 0;
            return stencil->pixels[x+y*stencil->w];
        }
    }

    // Inicialització de tot el que fa falta per a carregar gràfics i pintar en pantalla
    void init(const std::string &titol, const uint16_t width, const uint16_t height, const int zoom, const bool fullscreen)
    {
        screen_title = titol;
        screen_fullscreen = fullscreen;
        screen_zoom = zoom;
        screen_width = width;
        screen_height = height;

        // [TODO] Incloure gestió de pantalla completa

        // Inicialització de les estructures de SDL
        sdl_window = SDL_CreateWindow(screen_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width * screen_zoom, screen_height * screen_zoom, screen_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_SHOWN);
        sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
        sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height);

        SDL_RendererInfo info;
        const int num_render_drivers = SDL_GetNumRenderDrivers();
        printf("Available renderers:\n");
        for (int i=0; i<num_render_drivers; ++i)
        {
            SDL_GetRenderDriverInfo(i, &info);
            printf(" - %i: %s\n", i, info.name);
        }

        SDL_GetRendererInfo(sdl_renderer, &info);
        printf("\nRenderer: %s\n", info.name);

        if (screen_fullscreen)        
        {
            SDL_ShowCursor(false);
            int w, h;
            SDL_GetWindowSize(sdl_window, &w, &h);
            fullscreen_scale = h/screen_height;
            dest_rect.w = screen_width * fullscreen_scale;
            dest_rect.h = screen_height * fullscreen_scale;
            dest_rect.x = (w - dest_rect.w)/2;
            dest_rect.y = (h - dest_rect.h)/2;
        }
        else
        {
            SDL_ShowCursor(true);
            dest_rect.x = dest_rect.y = 0;
            dest_rect.w = screen_width * zoom;
            dest_rect.h = screen_height * zoom;
        }

        // Establim el tamany "logic", indepndent del tamany de finestra
        //SDL_RenderSetLogicalSize(sdl_renderer, width, height);

        // Creem la superficie "screen" i la establim com a superficie destinació
        screen = createSurface(width, height);
        setDestination(screen);
        sel_color = transparent = 0;
        for (int i=0;i<256;++i) color_indices[i] = i;

        int size;
        char *buffer = file::getFileBuffer("gifs.txt", size, true);
        char *p = buffer;
        char *n = buffer;
        while (*n!=0) {
            while (*n!='\n') n++;
            *n=0;
            loadSurface(p);
            p=++n;
        }
        free(buffer);

        textsurf = getSurface("font.gif");
        textsurf2 = getSurface("font2.gif");
    }

    // Finalització del sistema
    void quit()
    {
        for (int i=0; i<num_managed; ++i) if (managed[i]) freeSurface(managed[i]);
        //if (textsurf) freeSurface(textsurf);
        //if (textsurf2) freeSurface(textsurf2);

        // Si la superficie "screen" existia, alliberem la seua memòria
        if (screen != nullptr)
        {
            freeSurface(screen);
        }

        // Destruim tot el relacionat amb SDL
        SDL_DestroyTexture(sdl_texture);
        SDL_DestroyRenderer(sdl_renderer);
        SDL_DestroyWindow(sdl_window);

        // Fiquem tots els punters a nullptr, per si de cas no estem eixint del programa
        // i anem a tornar a inicialitzar el sistema
        sdl_window = nullptr;
        sdl_renderer = nullptr;
        sdl_texture = nullptr;
        screen = destination = source = nullptr;
    }

    void reinit()
    {
        // Destruim tot el relacionat amb SDL
        SDL_DestroyTexture(sdl_texture);
        SDL_DestroyRenderer(sdl_renderer);
        SDL_DestroyWindow(sdl_window);

        const int zoom = screen_fullscreen ? 1 : screen_zoom;
        sdl_window = SDL_CreateWindow(screen_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width * zoom, screen_height * zoom, screen_fullscreen?SDL_WINDOW_FULLSCREEN_DESKTOP:SDL_WINDOW_SHOWN);
        sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
        sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height);

        if (screen_fullscreen)        
        {
            SDL_ShowCursor(false);
            int w, h;
            SDL_GetWindowSize(sdl_window, &w, &h);
            fullscreen_scale = h/screen_height;
            dest_rect.w = screen_width * fullscreen_scale;
            dest_rect.h = screen_height * fullscreen_scale;
            dest_rect.x = (w - dest_rect.w)/2;
            dest_rect.y = (h - dest_rect.h)/2;
        }
        else
        {
            SDL_ShowCursor(true);
            dest_rect.x = dest_rect.y = 0;
            dest_rect.w = screen_width * zoom;
            dest_rect.h = screen_height * zoom;
        }

        // Establim el tamany "logic", indepndent del tamany de finestra
        //SDL_RenderSetLogicalSize(sdl_renderer, screen_width, screen_height);
    }

    void setZoom(const int value)
    {
        if (value < 1) return;

        SDL_DisplayMode dm;
        SDL_GetCurrentDisplayMode(0, &dm);

        if (screen_width*value > dm.w) return;
        if (screen_height*value > dm.h) return;

        screen_zoom = value;
        reinit();
    }

    void incZoom()
    {
        setZoom(screen_zoom+1);
    }

    void decZoom()
    {
        setZoom(screen_zoom-1);
    }

    void toggleFullscreen()
    {
        screen_fullscreen = !screen_fullscreen;
        reinit();
    }

    void setFullscreen(const bool value)
    {
        if (screen_fullscreen == value) return;
        screen_fullscreen = value;
        reinit();
    }

    const bool getFullscreen()
    {
        return screen_fullscreen;
    }

    const int getZoom()
    {
        return screen_zoom;
    }

    void toggleScreenMode()
    {
        screen_mode++;
        if (screen_mode == SCREEN_MODE_NUM_MODES) screen_mode = 0;
        //reinit();
    }

    void setScreenMode(const int value)
    {
        screen_mode = value;
    }

    const int getScreenMode()
    {
        return screen_mode;
    }

    // Crea una superficie i torna un punter a ella
    surface *createSurface(const uint16_t w, const uint16_t h)
    {
        // Primer reservem memòria per a la estructura "surface"
        surface *surf = (surface *)malloc(sizeof(surface));

        // Després reservem memòria per als pixels
        surf->pixels = (uint8_t *)malloc(w * h);

        // I apuntem el ample i alt de la superficie
        surf->w = w;
        surf->h = h;

        // Es una surface nova, no ve de arxiu ni tindrà varies referències
        surf->filename = nullptr;

        // ...i tornem la superficie creada, clar
        return surf;
    }

    // Carrega un gràfic d'un arxiu (en format GIF) a una nova superficie, i torna un punter a ella
    void loadSurface(const std::string &filename)
    {
        // Agafem un buffer de bytes de l'arxiu especificat
        // getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char
        int size;
        uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size);

        // Si ens ha tornat nullptr, es que no l'ha trobat, tornem nosaltres també nullptr ja que no s'ha pogut crear la superficie
        if (buffer == nullptr)
        {
            printf("ERROR: GIF no trobat: '%s'\n", filename.c_str());
            exit(1);
        }

        // Primer reservem memòria per a la estructura "surface"
        surface *surf = (surface *)malloc(sizeof(surface));

        // Després li passem el buffer de bytes a la funció de carregar un GIF.
        // El resultat es un array de bytes, els pixels en sí. Ja havem reservat
        //  la memòria necessaria en "LoadGif", així que no tenim que fer-ho ara,
        //  però, ojo, sí que tindrem que alliberar-la.
        surf->pixels = LoadGif(buffer, &surf->w, &surf->h);

        // Com ja no ens fa falta, alliberem la memòria del buffer del arxiu
        free(buffer);

        // Especifiquem el nom de l'arxiu del que vé i el guardem a la llista
        surf->filename = (char*)malloc(filename.length()+1);
        strcpy(surf->filename, filename.c_str());
        managed[num_managed++] = surf;
    }

    void reloadSurface(surface *surf)
    {
        free(surf->pixels);
        int size;
        uint8_t *buffer = (uint8_t *)file::getFileBuffer(surf->filename, size);
        surf->pixels = LoadGif(buffer, &surf->w, &surf->h);
        free(buffer);
    }

    void reloadAll()
    {
        for (int i=0; i<num_managed; ++i) reloadSurface(managed[i]);
    }

    surface *getSurface(const std::string &filename)
    {
        for(int i=0; i<num_managed; ++i)
        {
            // Si ja existia, pujem el nombre de referències i tornem eixa surface, i au
            if (strcmp(managed[i]->filename, filename.c_str())==0)
            {
                return managed[i];
            }
        }
        return nullptr;
    }

    // Allibera la memòria d'una superficie, els seus pixels inclosos
    void freeSurface(surface *surf)
    {
        // Si la superficie existeix...
        if (surf != nullptr)
        {
            // Si el array de pixels existeix, l'alliberem
            if (surf->pixels != nullptr)
            {
                free(surf->pixels);
            }

            // Si el nom de l'arxiu existeix, l'alliberem
            if (surf->filename != nullptr)
            {
                free(surf->filename);
            }

            free(surf);
        }
    }

    // Estableix una superficie com a superficie que rebrà les funcions de pintat (especificar nullptr per a pintar a pantalla)
    void setDestination(surface *surf)
    {
        // Si han especificat nullptr, fiquem "screen" com a destinació
        destination = surf == nullptr ? screen : surf;
        resetViewport();
    }

    // Estableix una superficie com a superficie de la que s'agafaràn els gràfics per a pintar
    void setSource(surface *surf)
    {
        // Si han especificat nullptr, fiquem "screen" com a font
        source = surf == nullptr ? screen : surf;
    }

    void pushSource()
    {
        pushedSource = source;
    }

    void popSource()
    {
        source = pushedSource;
    }

    void setViewport(const int x, const int y, const int w, const int h)
    {
        viewport.x = x<0 ? 0 : x>=destination->w ? 0 : x;
        viewport.y = y<0 ? 0 : y>=destination->h ? 0 : y;
        viewport.w = w+viewport.x<destination->w ? w : destination->w-viewport.x;
        viewport.h = h+viewport.y<destination->h ? h : destination->h-viewport.y;
    }

    void resetViewport()
    {
        viewport.x = viewport.y = 0;
        viewport.w = destination->w;
        viewport.h = destination->h;
    }

    const int getLocalX(const int x)
    {
        return x - viewport.x;
    }

    const int getLocalY(const int y)
    {
        return y - viewport.y;
    }

    // Estableix la paleta del sistema carregant-la d'un GIF
    void loadPalette(const std::string &filename)
    {
        // Agafem un buffer de bytes de l'arxiu especificat
        // getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char
        int size;
        uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size);

        // Li passem el array del arxiu a LoadPalette. Ell ens torna un array de uint32_t amb la paleta
        // Van a ser 256 entrades de 32 bits, cada entrada es un color, amb el format 0xAARRGGBB
        uint32_t *pal = LoadPalette(buffer);

        // Copiem eixe array al nostre array de la paleta de sistema. Ara ja tenim la paleta carregada.
        memcpy(palette, pal, 1024); // 32 bits per entrada == 4 bytes x 256 entrades == 1024

        // Alliberem el array que ens habia tornat LoadPalette()
        free(pal);

        // I també el buffer del arxiu
        free(buffer);
    }

    void setPaletteColor(const uint8_t index, const uint8_t r, const uint8_t g, const uint8_t b)
    {
        palette[index] = (r<<16) + (g<<8) + b;
    }

    // Esborra la superficie "destination" amb el color especificat
    void cls(const uint8_t color)
    {
        // El tamany es width x height bytes
        const int size = destination->w * destination->h;

        // Omplim la memòria dels pixels de la superficie de destinació amb "color"
        memset(destination->pixels, color_indices[color], size);
    }

    //Estableix el color especificat com a transparent
    void setTrans(const uint8_t color)
    {
        transparent = color;
    }

    // Funció interna per a pintar un pixel d'una superficie sense eixir-se'n de la memòria i petar el mame
    void pset(surface *surface, const int x, const int y, const uint8_t color)
    {
        // Si el color es transparent, eixim, ni ens molestem en mirar res més
        if (color == transparent) return;

        // Si està fora de la surface, directament passem
        if (x < 0 || y < 0 || x >= surface->w || y >= surface->h)
            return;

        // Si pintem a "destination", mirem que estiga dins del "viewport" i sinó fora
        if (surface == destination) {
            if (x+viewport.x >= 0 && y+viewport.y >= 0 && x < viewport.w && y < viewport.h)
            {
                surface->pixels[(viewport.x+x) + (y+viewport.y) * surface->w] = color_indices[color];
                if (stencil::stencil && stencil::enabled) stencil::stencil->pixels[(viewport.x+x) + (y+viewport.y) * stencil::stencil->w] = stencil::value;
            }
        } else {
            // Si no es destinations, pintem i au
            surface->pixels[x + y * surface->w] = color_indices[color];
        }
    }

    // Funció interna per a llegir un pixel d'una superficie sense eixir-se'n de la memòria i petar el mame
    const uint8_t pget(surface *surface, const int x, const int y)
    {
        // Si està fora de la surface, directament passem
        if (x < 0 || y < 0 || x >= surface->w || y >= surface->h)
            return 0;

        // Si estem llegint de "destination", mirar que estigam llegint dins del viewport
        if (surface == destination) {
            if (x+viewport.x >= 0 && y+viewport.y >= 0 && x < viewport.w && y < viewport.h)
                return surface->pixels[(viewport.x + x) + (viewport.y + y) * surface->w];
        } else {
            // Si no es "destination",
            return surface->pixels[x + y * surface->w];
        }

        return 0;
    }

    // Pinta un troç de la superficie "source" en la superficie "destination".
    void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int flip, int dw, int dh)
    {
        // Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame
        if (source == nullptr)
        {
            return;
        }

        if (dw==0) dw = w;
        if (dh==0) dh = h;

        // En principi, el quadrat de l'oritge començarà en (sx,sy) i avançarem 1 pixel en positiu tant en x com en y
        float sdx = float(w)/float(dw);
        float sdy = float(h)/float(dh);
        float ssx = sx;
        float ssy = sy;

        // Però si s'ha especificat que fem flip en horitzontal...
        if (flip & DRAW_FLIP_HORIZONTAL)
        {
            sdx = -sdx;         // Avançarem 1 pixel en negatiu
            ssx = sx + w - 1; // I començarem al final, o siga, sumarem a sx el ample
        }

        // De igual forma per al flip en vertical, per a la y
        if (flip & DRAW_FLIP_VERTICAL)
        {
            sdy = -sdy;
            ssy = sy + h - 1;
        }

        // guardem la coordenada d'oritge en x per a restablir-la a cada linea
        int csx = ssx;

        // Anem linea per linea. Les variables dels dos bucles for controlen les coordenades en la destinació, que sempre van avant.
        for (int y = dy; y < dy + dh; ++y)
        {
            ssx = csx; // fiquem la coordenada de l'oritge al principi

            // en cada linea, anem pixel a pixel
            for (int x = dx; x < dx + dw; ++x)
            {
                pset(destination, x, y, pget(source, ssx, ssy)); // Agafem pixel de l'oritge i el fiquem en la destinació
                ssx += sdx;                                      // avancem (o retrocedim) la coordenada x de l'oritge
            }
            ssy += sdy; // avancem (o retrocedim) la coordenada y de l'oritge
        }
    }

    void swapcol(const Uint8 c1, const Uint8 c2)
    {
        color_indices[c1] = c2;
    }

    void restorecol(const Uint8 c)
    {
        color_indices[c] = c;
    }

    void color(const Uint8 col)
    {
        sel_color = col;
    }

    void isoline(int x, int y, const int dx, const int dy, const int len)
    {
        for (int i=0; i<len; ++i)
        {
            pset(destination, x,y, sel_color);
            x+=dx;
            pset(destination, x,y, sel_color);
            x+=dx; y+=dy;
        }
    }

    void hline(const int x, const int y, const int w)
    {
        for (int i=x;i<x+w;++i) pset(destination, i, y, sel_color);
    }

    void vline(const int x, const int y, const int h)
    {
        for (int i=y;i<y+h;++i) pset(destination, x, i, sel_color);
    }

    void fillrect(const int x, const int y, const int w, const int h)
    {
        for (int j=y;j<y+h;++j) for (int i=x;i<x+w;++i) pset(destination, i, j, sel_color);
    }

    void rect(const int x, const int y, const int w, const int h)
    {
        hline(x,y,w);
        hline(x,y+h-1,w);
        vline(x,y,h);
        vline(x+w-1,y,h);
    }

    void pset(const int x, const int y, const uint8_t color)
    {
        pset(destination, x, y, color);
    }

    void print(const char* text, const int x, const int y, const Uint8 color, const Uint8 borde)
    {
        surface* tmp = source;
        source = textsurf;
        swapcol(1, color);
        const int len = strlen(text);
        for (int i=0;i<len;++i)
        {
            char chr = text[i];
            if (borde!=0)
            {
                swapcol(1, borde);
                draw(-1+x+i*4, y-1, 4, 6, (chr&15)*4, (chr>>4)*6);
                draw(x+i*4, y-1, 4, 6, (chr&15)*4, (chr>>4)*6);
                draw(1+x+i*4, y-1, 4, 6, (chr&15)*4, (chr>>4)*6);
                draw(-1+x+i*4, y, 4, 6, (chr&15)*4, (chr>>4)*6);
                draw(1+x+i*4, y, 4, 6, (chr&15)*4, (chr>>4)*6);
                draw(-1+x+i*4, y+1, 4, 6, (chr&15)*4, (chr>>4)*6);
                draw(x+i*4, y+1, 4, 6, (chr&15)*4, (chr>>4)*6);
                draw(1+x+i*4, y+1, 4, 6, (chr&15)*4, (chr>>4)*6);
                swapcol(1, color);
            }
            draw(x+i*4, y, 4, 6, (chr&15)*4, (chr>>4)*6);
        }
        source = tmp;
    }

    void print2(const char* text, const int x, const int y, const Uint8 color, const int zoom)
    {
        surface* tmp = source;
        source = textsurf2;
        swapcol(1, color);
        const int len = strlen(text);
        for (int i=0;i<len;++i)
        {
            char chr = text[i]-32;
            draw((x+(i*(zoom&FONT_ZOOM_HORIZONTAL?2:1)))*8, y*8, 8, 8, (chr&15)*8, (chr>>4)*8, DRAW_FLIP_NONE,zoom&FONT_ZOOM_HORIZONTAL?16:8, zoom&FONT_ZOOM_VERTICAL?16:8);
        }
        source = tmp;
    }

    void print2(const int num, const int positions, const int x, const int y, const uint8_t color, const int zoom)
    {
        const char empty = positions < 0 ? '0' : ' ';
        const int pos = positions < 0 ? -positions : positions;
        char buffer[pos+1];
        int digit = pos-1;
        int value = num<0 ? -num : num;
        while (digit>=0)
        {
            if (digit==0 && num<0) {
                buffer[digit] = '-';
            } else {
                buffer[digit] = (value%10)==0 && digit<pos-1 ? empty : (value%10)+48;
                value = value/10;
            }
            digit--;
        }
        buffer[pos]=0;
        print2(buffer, x, y, color, zoom);
    }

    // Refresca la pantalla
    void render()
    {
        
        Uint32 *sdl_pixels;                     // Punter al array de pixels que enstornarà SDL_LockTexture
        int sdl_pitch;                          // Ací estarà guardat el pitch de la textura, com es de 32 bits, no m'afecta
        const uint32_t size = screen->w * screen->h; // tamany de la superficie

        // Bloquejem la textura SDL i agafem els seus pixels (son enters de 32 bits amb format 0xAARRGGBB)
        //int result = 
        SDL_LockTexture(sdl_texture, NULL, (void **)&sdl_pixels, &sdl_pitch);

        // Cada pixel de la superficie "screen" es un enter de 8 bits que representa un index en la paleta de colors
        // Per tant, per a pintar en la textura SDL, pillem el color de la paleta que correspon al index en "screen"
        //  i el enviem a la textura SDL
        for (uint32_t i = 0; i < size; ++i)
        {
            sdl_pixels[i] = palette[screen->pixels[i]];
        }

        // Desbloquejem la textura
        SDL_UnlockTexture(sdl_texture);

        if (screen_fullscreen)
        {
            SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 255);
            SDL_RenderClear(sdl_renderer);
        }

        // Pintem la textura a pantalla
        SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, &dest_rect);

        if (screen_mode & SCREEN_MODE_SCANLINES)
        {
            if (screen_zoom>=3 || screen_fullscreen)
            {
                int zoom = screen_fullscreen ? fullscreen_scale : screen_zoom;
                SDL_SetRenderDrawBlendMode(sdl_renderer, SDL_BLENDMODE_BLEND);
                for (int y=0; y<screen_height; ++y)
                {
                    SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 192);
                    SDL_RenderDrawLine(sdl_renderer, dest_rect.x, dest_rect.y + y*zoom, dest_rect.x + dest_rect.w, dest_rect.y + y*zoom);
                    SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 96);
                    if (zoom>3) SDL_RenderDrawLine(sdl_renderer, dest_rect.x, 1+dest_rect.y + y*zoom, dest_rect.x + dest_rect.w, 1+dest_rect.y + y*zoom);
                }
                SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 16);
                for (int x=0; x<screen_width; ++x)
                {
                    SDL_RenderDrawLine(sdl_renderer, dest_rect.x + x*zoom, dest_rect.y, dest_rect.x + x*zoom, dest_rect.y + dest_rect.h);
                }
            }
        }
        // I ho presentem
        SDL_RenderPresent(sdl_renderer);
    }
    
}
