#include "room.h"
#include "jdraw.h"
#include "jfile.h"
#include "jutil.h"
#include "actor.h"
#include "editor.h"

namespace room
{
    static int current_room = 0;

    static int inner_w = 2;
    static int inner_h = 2;

    static vec3_t size = {8,8,8};   // Tamany de l'habitació en tiles
    static vec3_t tmin = {0,0,0};   // primer tile en cada coordenada
    static vec3_t tmax = {7,7,7};   // ultim tile en cada coordenada
    static vec3_t min = {0,0,0};    // primer "pixel isometric" en cada coordenada
    static vec3_t max = {64,64,64}; // ultim "pixel isometric" en cada coordenada

    static int doors = NO_DOOR; // Portes obertes
    static int door_height[4];  // Altura de cada porta
    static int exits[6];        // Habitació destí a la que du cada porta (piso i sostre inclosos)
    static int color = 0;       // Esquema de color de l'habitació
    static int original_color = 0;
    static int num_color_cycles =0;

    static int floor_type = 0;  // Tile per al piso
    static int walls_type = 0;  // Tile per a les pareds
    static int doors_type = 0;  // Textura per a les portes
    static int walldoors_type = 0;  // Textura per a baix de les portes

    static int editor_done = 0; // Nomes per al editor, per a marcar les habitacions completades i no tornarme loco

    static bool modified = false;

    // Surface on se guarden els gràfics de cada cosa
    static draw::surface *floor_surf = nullptr;
    static draw::surface *walls_surf = nullptr;
    static draw::surface *doors_surf = nullptr;
    static draw::surface *aux_surf = nullptr;

    static uint8_t color_schemes[5][4] = {
        {7, 11, 10, 9},
        {8, 11, 9, 7},
        {9, 11, 10, 8},
        {10, 11, 8, 7},
        {11, 10, 9, 8},
    };

    void init()
    {
        actor::clear();

        floor_surf = draw::getSurface("floor.gif");
        walls_surf = draw::getSurface("walls.gif");
        doors_surf = draw::getSurface("doors.gif");
        aux_surf = draw::getSurface("roomaux.gif");

        editor::updateRoomList();
    }

    void refresh()
    {
        size = {(inner_w+1)*2,(inner_h+1)*2,3};
        tmin = {3-inner_w,3-inner_h,0};
        tmax = {4+inner_w,4+inner_h,3};
        min = {tmin.x*8,tmin.y*8,0};
        max = {(tmax.x+1)*8,(tmax.y+1)*8,32};
        doors = (door_height[XP]>=0?DOOR_XP:0) | (door_height[XN]>=0?DOOR_XN:0) | (door_height[YP]>=0?DOOR_YP:0) | (door_height[YN]>=0?DOOR_YN:0);
        //door_height[0] = inner_xp; //XP
        //door_height[1] = inner_xn; //XN
        //door_height[2] = inner_yp; //YP
        //door_height[3] = inner_yn; //YN

        if (doors & DOOR_XN)
        {
            actor::actor_t *act = actor::create("DOOR_XN", {4+(tmin.x-1)*8,37,1+door_height[1]*4}, {4,4,1}, "doors.gif", {24+(doors_type%6)*40,(doors_type/6)*59,8,59}, {-18,65});
            act->flags = FLAG_NOEDITOR | FLAG_ORIENTABLE;
            act->orient = PUSH_YP;
            actor::setDirty(act, true);
        }

        if (doors & DOOR_YN)
        {
            actor::actor_t *act = actor::create("DOOR_YN", {34,4+(tmin.y-1)*8,1+door_height[3]*4}, {5,4,1}, "doors.gif", {24+(doors_type%6)*40,(doors_type/6)*59,8,59}, {-12,63});
            act->flags = FLAG_NOEDITOR;
            actor::setDirty(act, true);
        }

        if (doors & DOOR_YP)
        {
            const int floor_row_tiles = int(floor_surf->w/32);
            const uint8_t actual_floor = door_height[2]>0?0:floor_type;
            int floor_x = (actual_floor%floor_row_tiles)*32;
            int floor_y = int(actual_floor/floor_row_tiles)*16;
            actor::actor_t *act = actor::create("DOOR_YP1", {24,(tmax.y+1)*8,0}, {8,8,(door_height[2])*4}, "floor.gif", {floor_x,floor_y+1,32,15}, {0,15+door_height[2]*8});
            act->flags = FLAG_NOEDITOR;
            actor::setDirty(act, true);
            act = actor::create("DOOR_YP2", {32,(tmax.y+1)*8,0}, {8,8,(door_height[2])*4}, "floor.gif", {floor_x,floor_y+1,32,15}, {0,15+door_height[2]*8});
            act->flags = FLAG_NOEDITOR;
            actor::setDirty(act, true);

            act = actor::create("DOOR_YP", {20,(tmax.y+1)*8,1+door_height[2]*4}, {5,4,24}, "doors.gif", {(doors_type%6)*40,(doors_type/6)*59,16,48}, {-16,49});
            act->flags = FLAG_NOEDITOR;
            actor::setDirty(act, true);
        }

        if (doors & DOOR_XP)
        {
            const int floor_row_tiles = int(floor_surf->w/32);
            const uint8_t actual_floor = door_height[0]>0?0:floor_type;
            int floor_x = (actual_floor%floor_row_tiles)*32;
            int floor_y = int(actual_floor/floor_row_tiles)*16;
            actor::actor_t *act = actor::create("DOOR_XP1", {(tmax.x+1)*8,24,0}, {8,8,(door_height[0])*4}, "floor.gif", {floor_x,floor_y+1,32,15}, {0,15+door_height[0]*8});
            act->flags = FLAG_NOEDITOR;
            actor::setDirty(act, true);
            act = actor::create("DOOR_XP2", {(tmax.x+1)*8,32,0}, {8,8,(door_height[0])*4}, "floor.gif", {floor_x,floor_y+1,32,15}, {0,15+door_height[0]*8});
            act->flags = FLAG_NOEDITOR;
            actor::setDirty(act, true);

            act = actor::create("DOOR_XP", {(tmax.x+1)*8,20,1+door_height[0]*4}, {8,8,24}, "doors.gif", {(doors_type%6)*40,(doors_type/6)*59,16,48}, {0,49});
            act->flags = FLAG_NOEDITOR | FLAG_ORIENTABLE;
            act->orient = PUSH_YP;
            actor::setDirty(act, true);
        }

        actor::reorder();
    }

    const int find_next_room()
    {
        char filename[] = "rooms/00.txt";
        int room=0;
        while ( file::fileExists(filename) )
        {
            room++;
            filename[6] = int(room/10)+48;
            filename[7] = (room%10)+48;
        }
        return room;
    }

    const int inverse_door(const int door)
    {
        if (door==XP) return XN;
        if (door==XN) return XP;
        if (door==YP) return YN;
        if (door==YN) return YP;
        if (door==ZP) return ZN;
        if (door==ZN) return ZP;
        return XN;
    }

    //void load(int x, int y, int8_t xp, int8_t xn, int8_t yp, int8_t yn, uint8_t col, uint8_t floor, uint8_t walls, uint8_t door, uint8_t walldoor)
    void reload() { load(current_room); }
    
    void load(int room, const int door)
    {
        if (room > MAX_ROOMS || room < 0) {
            room = find_next_room();
            exits[inverse_door(door)] = room;
            if (door<4 && door_height[inverse_door(door)]==-1) door_height[inverse_door(door)]=0;
            modified = true;
        }

        if (modified && ::editor::isEditing()) editor::save();

        actor::actor_t *sel = actor::getSelected();
        char selected_actor_name[16]; selected_actor_name[0] = 0;
        if (sel) strcpy(selected_actor_name, sel->name);

        init();

        // Primer carreguem els valors per defecte
        inner_w = inner_h = 2;
        for (int i=0;i<4;++i) door_height[i] = -1;
        color = original_color = 2;
        num_color_cycles = 0;
        floor_type = walls_type = doors_type = walldoors_type = editor_done = 0;
        for (int i=0;i<6;++i) exits[i] = -1;

        // Després intentem carregar els valors segons el arxiu que toca, si existeix
        char filename[] = "rooms/00.txt";
        filename[6] = int(room/10)+48;
        filename[7] = (room%10)+48;
        int filesize=0;
        char *buffer = file::getFileBuffer(filename, filesize, true);
        char *original_buffer = buffer;

        if (buffer)
        {
            while (*buffer != 0)
            {
                const char* key = file::readString(&buffer);

                if (util::strcomp(key, "width:")) {
                    const int val = file::readInt(&buffer);
                    inner_w = SDL_clamp(val, 0, 3);
                } else if (util::strcomp(key, "height:")) {
                    const int val = file::readInt(&buffer);
                    inner_h = SDL_clamp(val, 0, 3);

                } else if (util::strcomp(key, "door-height-xp:")) {
                    const int val = file::readInt(&buffer);
                    door_height[XP] = SDL_clamp(val, -1, 5);
                } else if (util::strcomp(key, "door-height-xn:")) {
                    const int val = file::readInt(&buffer);
                    door_height[XN] = SDL_clamp(val, -1, 5);
                } else if (util::strcomp(key, "door-height-yp:")) {
                    const int val = file::readInt(&buffer);
                    door_height[YP] = SDL_clamp(val, -1, 5);
                } else if (util::strcomp(key, "door-height-yn:")) {
                    const int val = file::readInt(&buffer);
                    door_height[YN] = SDL_clamp(val, -1, 5);

                } else if (util::strcomp(key, "color:")) {
                    color = util::stringToInt(file::readString(&buffer), {"purple", "green", "cyan", "yellow", "white"}, {0, 1, 2, 3, 4});
                    original_color = color;
                } else if (util::strcomp(key, "floor-texture:")) {
                    floor_type = file::readInt(&buffer);
                } else if (util::strcomp(key, "wall-texture:")) {
                    walls_type = file::readInt(&buffer);
                } else if (util::strcomp(key, "door-texture:")) {
                    doors_type = file::readInt(&buffer);
                } else if (util::strcomp(key, "under-door-texture:")) {
                    walldoors_type = file::readInt(&buffer);

                } else if (util::strcomp(key, "exit-xp:")) {
                    const int val = file::readInt(&buffer);
                    exits[0] = SDL_clamp(val, 0, MAX_ROOMS);
                } else if (util::strcomp(key, "exit-xn:")) {
                    const int val = file::readInt(&buffer);
                    exits[1] = SDL_clamp(val, 0, MAX_ROOMS);
                } else if (util::strcomp(key, "exit-yp:")) {
                    const int val = file::readInt(&buffer);
                    exits[2] = SDL_clamp(val, 0, MAX_ROOMS);
                } else if (util::strcomp(key, "exit-yn:")) {
                    const int val = file::readInt(&buffer);
                    exits[3] = SDL_clamp(val, 0, MAX_ROOMS);
                } else if (util::strcomp(key, "exit-zp:")) {
                    const int val = file::readInt(&buffer);
                    exits[4] = SDL_clamp(val, 0, MAX_ROOMS);
                } else if (util::strcomp(key, "exit-zn:")) {
                    const int val = file::readInt(&buffer);
                    exits[5] = SDL_clamp(val, 0, MAX_ROOMS);
                } else if (util::strcomp(key, "editor-done:")) {
                    const int val = file::readInt(&buffer);
                    editor_done = SDL_clamp(val, 0, 1);

                } else if (util::strcomp(key, "actor{")) {
                    actor::actor_t *act = actor::createFromFile(&buffer);

                    if (!::editor::isEditing() && act->flags & FLAG_SPECIAL)
                    {
                        if (act->name[0]=='B') { // Es un booster
                            if (!::editor::isDevMode() && actor::hero::wasBoosterCollected((act->name[2]-48)*10+(act->name[3]-48)))
                            {
                                actor::remove(act);
                                act = nullptr;
                            }
                        } else if (act->name[0]=='S') { // Es un skill
                            if (!::editor::isDevMode() && actor::hero::wasSkillCollected(&act->name[2]))
                            {
                                actor::remove(act);
                                act = nullptr;
                            }
                        } else if (act->name[0]=='P') { // Es una part
                            if (!::editor::isDevMode() && actor::hero::wasPartCollected(&act->name[2]))
                            {
                                actor::remove(act);
                                act = nullptr;
                            }
                        } else if (act->name[0]=='G') { // Es un ghost d'una part
                            if (!::editor::isDevMode() && actor::hero::wasPartCollected(&act->name[2]))
                            {
                                act->flags &= ~FLAG_ANIMATED;
                                act->bmp_rect.x += act->bmp_rect.w;
                            }
                        } else if (act->name[0]=='A') { // Es una anbernic
                            if (!::editor::isDevMode() && actor::hero::wasAnbernicCollected(act->name))
                            {
                                actor::remove(act);
                                act = nullptr;
                            }
                        } else if (act->name[0]=='X') { // Es un objecte del prólogo sense arreplegar
                            if (!::editor::isDevMode() && actor::hero::getPrologoObjectState(act->name[2]-48)!=PROLOGO_OBJECT_INITIAL)
                            {
                                actor::remove(act);
                                act = nullptr;
                            }
                        } else if (act->name[0]=='Y') { // Es un hueco on deixar un objecte del prólogo
                            if (!::editor::isDevMode() && actor::hero::getPrologoObjectState(act->name[2]-48)==PROLOGO_OBJECT_LEFT)
                            {
                                act->name[0] = 'Z';
                            }
                        }
                    }
                    if (act) actor::setDirty(act, true);
                }
            }
            free(original_buffer);
        } else {
            if (door != -1)
            {
                exits[door] = current_room;
                if (door < 4) door_height[door] = 0;
            }
            current_room = room;
            editor::save();
            editor::updateRoomList();
        }

        current_room = room;
        actor::stats::visitRoom(room);
        refresh();

        actor::select(actor::find(selected_actor_name));
    }
    
    void update()
    {
        actor::remove(actor::find("DOOR_XN"));
        actor::remove(actor::find("DOOR_YN"));
        actor::remove(actor::find("DOOR_XP"));
        actor::remove(actor::find("DOOR_XP1"));
        actor::remove(actor::find("DOOR_XP2"));
        actor::remove(actor::find("DOOR_YP"));
        actor::remove(actor::find("DOOR_YP1"));
        actor::remove(actor::find("DOOR_YP2"));

        refresh();
    }

    void draw()
    {
        if (num_color_cycles > 0)
        {
            color++;
            if (color>4) color = 0;
            if (color==original_color) num_color_cycles--;
            if (num_color_cycles==0) {
                actor::actor_t * hero = actor::find("HERO");
                if (!hero) {
                    if (actor::hero::getLives()==0) {
                        actor::hero::die();
                    } else {
                        actor::hero::init(false);
                        load(current_room);
                    }
                }
            }
        }

        draw::pushSource();
        draw::swapcol(1, color_schemes[color][0]);

        const int floor_row_tiles = int(floor_surf->w/32);
        int floor_x = (floor_type%floor_row_tiles)*32;
        int floor_y = int(floor_type/floor_row_tiles)*16;

        const int walls_row_tiles = int(walls_surf->w/16);
        const int walls_x = (walls_type%walls_row_tiles)*16;
        const int walls_y = int(walls_type/walls_row_tiles)*48;

        const int doors_row_tiles = int(doors_surf->w/40);
        const int doors_x = (doors_type%doors_row_tiles)*40;
        const int doors_y = int(doors_type/doors_row_tiles)*59;

        const int walldoors_row_tiles = int(walls_surf->w/16);
        const int walldoors_x = (walldoors_type%walldoors_row_tiles)*16;
        const int walldoors_y = int(walldoors_type/walldoors_row_tiles)*48;

        // RUTINES DE PINTAT DE LA PORTA DE DALT A LA DRETA
        if (doors & DOOR_YN)
        {
            // Si la porta està elevada, pintar la part frontal de baix de la porta
            if (door_height[3] > 0) {
                draw::setSource(walls_surf);
                draw::draw(  164+3*16-tmin.y*16, (36+3*8+tmin.y*8) + (5-door_height[3])*8, 16, 48-(5-door_height[3])*8, walldoors_x, walldoors_y+(5-door_height[3])*8);
                draw::draw(  164+4*16-tmin.y*16, (36+4*8+tmin.y*8) + (5-door_height[3])*8, 16, 48-(5-door_height[3])*8, walldoors_x, walldoors_y+(5-door_height[3])*8);
            }

            // Pintem els dos tiles baix de la porta
            draw::setSource(walls_surf);
            draw::draw(164+4*16-(tmin.y-1)*16, -door_height[3]*8+84+4*8+(tmin.y-1)*8, 16, 15, walls_x, walls_y+33, DRAW_FLIP_HORIZONTAL);   // Vora
            draw::setSource(floor_surf);
            if (floor_type==11) {
                draw::draw(148+3*16-(tmin.y-1)*16, -door_height[3]*8+76+3*8+(tmin.y-1)*8, 32, 15, 0, 1);      // Tile de Piso
                draw::draw(148+4*16-(tmin.y-1)*16, -door_height[3]*8+76+4*8+(tmin.y-1)*8, 32, 15, 0, 1);      // Tile de Piso
            } else {
                draw::draw(148+3*16-(tmin.y-1)*16, -door_height[3]*8+76+3*8+(tmin.y-1)*8, 32, 15, floor_x, floor_y+1);      // Tile de Piso
                draw::draw(148+4*16-(tmin.y-1)*16, -door_height[3]*8+76+4*8+(tmin.y-1)*8, 32, 15, floor_x, floor_y+1);      // Tile de Piso
            }

            // Pintem la porta
            draw::setSource(doors_surf);
            draw::draw(164+3*16-tmin.y*16, -door_height[3]*8+32+3*8+tmin.y*8,40,59,doors_x,doors_y);
        }

        // RUTINES DE PINTAT DE LA PORTA DE DALT A LA ESQUERRA
        if (doors & DOOR_XN)
        {
            // Si la porta està elevada, pintar la part frontal de baix de la porta
            if (door_height[1] > 0) {
                draw::setSource(walls_surf);
                draw::draw(148+tmin.x*16-3*16, (36+tmin.x*8+3*8)+(5-door_height[1])*8, 16, 48-(5-door_height[1])*8, walldoors_x, walldoors_y+(5-door_height[1])*8, DRAW_FLIP_HORIZONTAL);
                draw::draw(148+tmin.x*16-4*16, (36+tmin.x*8+4*8)+(5-door_height[1])*8, 16, 48-(5-door_height[1])*8, walldoors_x, walldoors_y+(5-door_height[1])*8, DRAW_FLIP_HORIZONTAL);
            }

            // Pintem els dos tiles baix de la porta
            draw::setSource(walls_surf);
            draw::draw(164+(tmin.x-1)*16-5*16, -door_height[1]*8+84+(tmin.x-1)*8+4*8, 16, 15, walls_x, walls_y+33);   // Vora
            draw::setSource(floor_surf);
            if (floor_type==11) {
                draw::draw(148+(tmin.x-1)*16-3*16, -door_height[1]*8+76+(tmin.x-1)*8+3*8,32,15,0,1);
                draw::draw(148+(tmin.x-1)*16-4*16, -door_height[1]*8+76+(tmin.x-1)*8+4*8,32,15,0,1);
            } else {
                draw::draw(148+(tmin.x-1)*16-3*16, -door_height[1]*8+76+(tmin.x-1)*8+3*8,32,15,floor_x, floor_y+1);
                draw::draw(148+(tmin.x-1)*16-4*16, -door_height[1]*8+76+(tmin.x-1)*8+4*8,32,15,floor_x, floor_y+1);
            }

            // Pintem la porta
            draw::setSource(doors_surf);
            draw::draw(164+(tmin.x-1)*16-4*16-8,  -door_height[1]*8+32+3*8+9+(tmin.x-1)*8,  40,59, doors_x,doors_y, DRAW_FLIP_HORIZONTAL);
        }

        draw::setSource(walls_surf);
        for (int x=tmin.x;x<=tmax.x;++x)
        {
            // Si hi ha porta en YP i està a altura 0, no pintem la vorera en eixos dos tiles
            if (exits[ZN]==-1) if ( !(doors & DOOR_YP) || (door_height[2] != 0) || (x!=3 && x!=4) ) draw::draw(148+x*16-tmax.y*16,84+x*8+tmax.y*8,16,15,walls_x, walls_y+33);

            // Si hi ha porta en YN, no pintem la pared en eixos dos tiles
            if ( !(doors & DOOR_YN) || (x!=3 && x!=4) ) draw::draw(164+x*16-tmin.y*16,36+x*8+tmin.y*8,16,48,walls_x, walls_y);
        }

        for (int y=tmin.y;y<=tmax.y;++y)
        {
            draw::setSource(walls_surf);
            // Si hi ha porta en XP i està a altura 0, no pintem la vorera en eixos dos tiles
            if (exits[ZN]==-1) if ( !(doors & DOOR_XP) || (door_height[0] != 0) || (y!=3 && y!=4) ) draw::draw(164+tmax.x*16-y*16,84+tmax.x*8+y*8,16,15,walls_x, walls_y+33, DRAW_FLIP_HORIZONTAL);

            // Si hi ha porta en XN, no pintem la pared en eixos dos tiles
            if ( !(doors & DOOR_XN) || (y!=3 && y!=4) ) draw::draw(148+tmin.x*16-y*16,36+tmin.x*8+y*8,16,48,walls_x, walls_y, DRAW_FLIP_HORIZONTAL);

            // Pintem tots els tiles del piso
            if (exits[ZN]==-1)
            {
                draw::setSource(floor_surf);
                for (int x=tmin.x;x<=tmax.x;++x)
                {
                    draw::draw(148+x*16-y*16,76+x*8+y*8,32,15,floor_x, floor_y+1);
                }
            }
        }  
        draw::popSource();      
    }

    void draw2()
    {
        draw::pushSource();
        draw::swapcol(1, color_schemes[color][0]);

        const int doors_row_tiles = int(doors_surf->w/40);
        const int doors_x = (doors_type%doors_row_tiles)*40;
        const int doors_y = int(doors_type/doors_row_tiles)*59;

        const int walldoors_row_tiles = int(walls_surf->w/16);
        const int walldoors_x = (walldoors_type%walldoors_row_tiles)*16;
        const int walldoors_y = int(walldoors_type/walldoors_row_tiles)*48;

        if (doors & DOOR_YP)
        {
            // Pintem les voreres dels dos tiles extra per a la porta YP
            draw::setSource(walls_surf);
            draw::draw(164+4*16-(tmax.y+1)*16, -door_height[2]*8+84+4*8+(tmax.y+1)*8, 16, 15+door_height[2]*8, walldoors_x, walldoors_y+1, DRAW_FLIP_HORIZONTAL);
            draw::draw(148+3*16-(tmax.y+1)*16, -door_height[2]*8+84+3*8+(tmax.y+1)*8, 16, 15+door_height[2]*8, walldoors_x, walldoors_y+1);
            draw::draw(148+4*16-(tmax.y+1)*16, -door_height[2]*8+84+4*8+(tmax.y+1)*8, 16, 15+door_height[2]*8, walldoors_x, walldoors_y+1);

            draw::setSource(aux_surf);
            draw::draw(164+4*16-(tmax.y+1)*16, 91+4*8+(tmax.y+1)*8, 16, 8, 16, 0);
            draw::draw(148+3*16-(tmax.y+1)*16, 91+3*8+(tmax.y+1)*8, 16, 8, 0, 0);
            draw::draw(148+4*16-(tmax.y+1)*16, 91+4*8+(tmax.y+1)*8, 16, 8, 0, 0);

            // Pintem la porta YP
            draw::setSource(doors_surf);
            draw::draw(16+164+3*16-8-(tmax.y+1)*16, -door_height[2]*8+32+3*8+4+(tmax.y+1)*8,24,59,doors_x+16,doors_y);
        }
        if (doors & DOOR_XP)
        {
            // Pintem les voreres dels dos tiles extra per a la porta XP
            draw::setSource(walls_surf);
            draw::draw(148+(tmax.x+1)*16-4*16, -door_height[0]*8+84+(tmax.x+1)*8+4*8,16,15+door_height[0]*8,walldoors_x, walldoors_y+1);
            draw::draw(164+(tmax.x+1)*16-3*16, -door_height[0]*8+84+(tmax.x+1)*8+3*8,16,15+door_height[0]*8,walldoors_x, walldoors_y+1, DRAW_FLIP_HORIZONTAL);
            draw::draw(164+(tmax.x+1)*16-4*16, -door_height[0]*8+84+(tmax.x+1)*8+4*8,16,15+door_height[0]*8,walldoors_x, walldoors_y+1, DRAW_FLIP_HORIZONTAL);

            draw::setSource(aux_surf);
            draw::draw(148+(tmax.x+1)*16-4*16, 91+(tmax.x+1)*8+4*8,16,8,0,0);
            draw::draw(164+(tmax.x+1)*16-3*16, 91+(tmax.x+1)*8+3*8,16,8,16,0);
            draw::draw(164+(tmax.x+1)*16-4*16, 91+(tmax.x+1)*8+4*8,16,8,16,0);

            // Pintem la porta XP
            draw::setSource(doors_surf);
            draw::draw(  164+(tmax.x+1)*16-4*16-16,  -door_height[0]*8+32+3*8+4+(tmax.x+1)*8,  24,59, doors_x+16,doors_y, DRAW_FLIP_HORIZONTAL);
        }
        draw::popSource();
    }

    void cycleColor(int times)
    {
        num_color_cycles = times;
    }

    int getCurrent()
    {
        return current_room;
    }

    vec3_t getSize()
    {
        return size;
    }

    vec3_t getMin()
    {
        return min;
    }

    vec3_t getMax()
    {
        return max;
    }

    vec3_t getTMin()
    {
        return tmin;
    }

    vec3_t getTMax()
    {
        return tmax;
    }

    int getDoors()
    {
        return doors;
    }

    int getDoor(const int d)
    {
        return door_height[d];
    }

    int getExit(const int d)
    {
        return exits[d];
    }

    int getColor(int which)
    {
        return color_schemes[color][which];
    }

    int getFloor()
    {
        return floor_type;
    }

    int getFloorCount()
    {
        return int(floor_surf->w / 32) * int(floor_surf->h / 16);
    }

    int getDoorCount()
    {
        return int(doors_surf->w / 40) * int(doors_surf->h / 59);
    }

    int getWallsCount()
    {
        int num = int(walls_surf->w / 16) * int(walls_surf->h / 48);
        return num;
    }


    namespace editor
    {
        static bool room_exists[256];

        int &refWidth() { return inner_w; }
        int &refHeight() { return inner_h; }

        int &refDoor(const int which) { return door_height[which]; }

        int &refColor() { return color; }
        int &refFloorTex() { return floor_type; }
        int &refWallTex() { return walls_type; }
        int &refDoorTex() { return doors_type; }
        int &refWallDoorTex() { return walldoors_type; }

        int &refExit(const int which) { return exits[which]; }

        int &refEditorDone() { return editor_done; }

        bool roomExists(const int which) { return room_exists[which]; }

        void updateRoomList()
        {
            if (!::editor::isDevMode()) return;
            
            for (int room=0; room<MAX_ROOMS; ++room)
            {
                char filename[] = "rooms/00.txt";
                filename[6] = int(room/10)+48;
                filename[7] = (room%10)+48;
                room_exists[room] = (file::fileExists(filename));
            };
        }

        int getCurrentRoom() { return current_room; }

        const char *numToColor(uint8_t value)
        {
            const char* colors[5] = {"PURPLE", "GREEN", "CYAN", "YELLOW", "WHITE"};
            return colors[value];
        }

        void modify() { modified = true; }

        const bool isModified()
        {
            return modified;
        }

        void save()
        {
            char filename[] = "data/rooms/00.txt";
            filename[11] = int(current_room/10)+48;
            filename[12] = (current_room%10)+48;
            FILE *f = fopen(filename, "w");

            fprintf(f, "width: %i\n", inner_w);
            fprintf(f, "height: %i\n", inner_h);
            if (door_height[XP]!=-1) fprintf(f, "door-height-xp: %i\n", door_height[XP]);
            if (door_height[XN]!=-1) fprintf(f, "door-height-xn: %i\n", door_height[XN]);
            if (door_height[YP]!=-1) fprintf(f, "door-height-yp: %i\n", door_height[YP]);
            if (door_height[YN]!=-1) fprintf(f, "door-height-yn: %i\n", door_height[YN]);

            fprintf(f, "color: %s\n", numToColor(color));
            fprintf(f, "floor-texture: %i\n", floor_type);
            fprintf(f, "wall-texture: %i\n", walls_type);
            fprintf(f, "door-texture: %i\n", doors_type);
            fprintf(f, "under-door-texture: %i\n", walldoors_type);

            if (exits[XP]!=-1) fprintf(f, "exit-xp: %i\n", exits[XP]);
            if (exits[XN]!=-1) fprintf(f, "exit-xn: %i\n", exits[XN]);
            if (exits[YP]!=-1) fprintf(f, "exit-yp: %i\n", exits[YP]);
            if (exits[YN]!=-1) fprintf(f, "exit-yn: %i\n", exits[YN]);
            if (exits[ZP]!=-1) fprintf(f, "exit-zp: %i\n", exits[ZP]);
            if (exits[ZN]!=-1) fprintf(f, "exit-zn: %i\n", exits[ZN]);

            if (editor_done!=0) fprintf(f, "editor-done: %i\n", editor_done);

            actor::actor_t *act = actor::alphaOrder(actor::getFirst());
            while (act)
            {
                if ( (act->flags&(FLAG_HERO|FLAG_NOEDITOR))==0 ) actor::saveToFile(f, act);
                act = act->next_alpha;
            }

            fclose(f);
            modified = false;
        }
    }

}
