#include "m_editor_map.h"
#include "jdraw.h"
#include "jinput.h"
#include "misc.h"
#include <SDL3/SDL.h>
#include "room.h"
#include "actor.h"

namespace modules
{
    namespace editor_map
    {
        draw::surface *surf;
        vec2_t scroll {0,0};
        int drawn[MAX_ROOMS];
        int current_room;
        int previous_room;

        struct miniroom_t
        {
            uint8_t w;
            uint8_t h;
            uint8_t color;
            uint8_t exits[6];
            uint32_t specials;
            uint8_t editor_done;
        };
        miniroom_t minirooms[MAX_ROOMS];

        void drawLines(const int room, const int x, const int y)
        {
            if (drawn[room]) return;
            drawn[room] = true;
            if ( (x>=-32) && (x<520) && (y>=-16) && (y<240) )
            {
                draw::color(RED);
                if (minirooms[room].exits[XN] != 255) { draw::isoline(x,y,-1,-1,14); /*draw::isoline(x,y-1,-1,-1,14);*/ draw::isoline(x,y+1,-1,-1,14); }
                if (minirooms[room].exits[YN] != 255) { draw::isoline(x,y,+1,-1,14); /*draw::isoline(x,y-1,+1,-1,14);*/ draw::isoline(x,y+1,+1,-1,14); }
                if (minirooms[room].exits[XP] != 255) { draw::isoline(x,y,+1,+1,14); /*draw::isoline(x,y-1,+1,+1,14);*/ draw::isoline(x,y+1,+1,+1,14); }
                if (minirooms[room].exits[YP] != 255) { draw::isoline(x,y,-1,+1,14); /*draw::isoline(x,y-1,-1,+1,14);*/ draw::isoline(x,y+1,-1,+1,14); }
                if (minirooms[room].exits[ZN] != 255) { draw::vline(x-1,y,24); /*draw::isoline(x,y-1,-1,+1,14);*/ draw::vline(x,y,24); }
                if (minirooms[room].exits[ZP] != 255) { draw::vline(x-1,y-24,24); /*draw::isoline(x,y-1,-1,+1,14);*/ draw::vline(x,y-24,24); }
            }
            if (minirooms[room].exits[XN] != 255) drawLines(minirooms[room].exits[XN], x-24, y-12);
            if (minirooms[room].exits[XP] != 255) drawLines(minirooms[room].exits[XP], x+24, y+12);
            if (minirooms[room].exits[YN] != 255) drawLines(minirooms[room].exits[YN], x+24, y-12);
            if (minirooms[room].exits[YP] != 255) drawLines(minirooms[room].exits[YP], x-24, y+12);
            if (minirooms[room].exits[ZN] != 255) drawLines(minirooms[room].exits[ZN], x, y+24);
            if (minirooms[room].exits[ZP] != 255) drawLines(minirooms[room].exits[ZP], x, y-24);
        }

        void drawRoom(const int room, const int x, const int y, const bool shadow=false)
        {
            if (drawn[room]) return;
            drawn[room] = true;
            if ( (x>=-32) && (x<520) && (y>=-16) && (y<240) )
            {
                draw::stencil::set(room);
                draw::swapcol(1, !shadow ? minirooms[room].color : minirooms[room].editor_done==1 ? 2 : RED);
                draw::draw(x-16, y-8, 32, 16, minirooms[room].w*32, minirooms[room].h*16);
                
                if (!shadow)
                {
                    char num[] = "00"; num[0] = 48+(room/10); num[1] = 48+(room%10);
                    draw::print(num, x-4, y-3, LIGHT+(room==current_room?YELLOW:WHITE), BLACK);
                    if (minirooms[room].specials&0x000000ff) { draw::color(BLACK); draw::rect(x+3, y-4, 3, 3); draw::color(BLUE); draw::fillrect(x+4, y-3, 1, 1); }
                    if (minirooms[room].specials&0x0000ff00) { draw::color(BLACK); draw::rect(x+3, y-2, 3, 3); draw::color(GREEN); draw::fillrect(x+4, y-1, 1, 1); }
                    if (minirooms[room].specials&0x00ff0000) { draw::color(BLACK); draw::rect(x+3, y, 3, 3); draw::color(YELLOW); draw::fillrect(x+4, y+1, 1, 1); }
                    if (minirooms[room].specials&0xff000000) { draw::color(RED); draw::fillrect(x+4, y-3, 1, 5); }
                }
            }
            if (minirooms[room].exits[XN] != 255) drawRoom(minirooms[room].exits[XN], x-24, y-12, shadow);
            if (minirooms[room].exits[XP] != 255) drawRoom(minirooms[room].exits[XP], x+24, y+12, shadow);
            if (minirooms[room].exits[YN] != 255) drawRoom(minirooms[room].exits[YN], x+24, y-12, shadow);
            if (minirooms[room].exits[YP] != 255) drawRoom(minirooms[room].exits[YP], x-24, y+12, shadow);
            if (minirooms[room].exits[ZN] != 255) drawRoom(minirooms[room].exits[ZN], x, y+24, shadow);
            if (minirooms[room].exits[ZP] != 255) drawRoom(minirooms[room].exits[ZP], x, y-24, shadow);
        }

        void loadMiniRoom()
        {
            const int room = room::getCurrent();
            if (drawn[room]) return;
            drawn[room] = true;

            minirooms[room].color = room::getColor(0);
            minirooms[room].w = (room::getSize().x >> 1)-1;
            minirooms[room].h = (room::getSize().y >> 1)-1;
            minirooms[room].specials = 0;
            minirooms[room].editor_done = room::editor::refEditorDone();

            // Recolectem els especials de l'habitació per a mostrar-los
            actor::actor_t *act = actor::getFirst();
            while (act)
            {
                if (act->flags & FLAG_SPECIAL)
                {
                    if (act->name[0]=='B') { // Es un booster
                        minirooms[room].specials |= actor::hero::getBoosterFromString(&act->name[5]);
                    } else if (act->name[0]=='S') { // Es un skill
                        minirooms[room].specials |= (actor::hero::getSkillFromString(&act->name[2])<<8);
                    } else if (act->name[0]=='P') { // Es una part
                        minirooms[room].specials |= (actor::hero::getPartFromString(&act->name[2])<<16);
                    } else {
                        minirooms[room].specials |= (1<<24); // Es algo invalid
                    }
                }
                act = act->next;
            }

            for (int i=0; i<=ZN; ++i) minirooms[room].exits[i] = room::getExit(i);

            for (int i=0; i<=ZN; ++i) {
                const int next_room = minirooms[room].exits[i];
                if ( (next_room >= 0) && (next_room <= MAX_ROOMS) && (!drawn[next_room]) ) {
                    room::load(next_room);
                    loadMiniRoom();
                }
            }
        }

        void init()
        {
            surf = draw::getSurface("mapa.gif");
            scroll = {260,120};
            draw::resetViewport();
            for (int i=0;i<MAX_ROOMS;++i) drawn[i]=false;

            current_room = room::getCurrent();
            previous_room = current_room;
            loadMiniRoom();
            room::load(42);

            for (int i=0;i<MAX_ROOMS;++i) drawn[i]=false;
            draw::cls(2);
            draw::setSource(surf);

            drawLines(room::getCurrent(), scroll.x, scroll.y);

            for (int y=-1; y<=1; ++y)
                for (int x=-1; x<=1; ++x)
                {
                    for (int i=0;i<MAX_ROOMS;++i) drawn[i]=false;
                    drawRoom(room::getCurrent(), scroll.x+x, scroll.y+y, true);
                }

            draw::stencil::enable();
            draw::stencil::clear(255);

            for (int i=0;i<MAX_ROOMS;++i) drawn[i]=false;
            drawRoom(room::getCurrent(), scroll.x, scroll.y);

            draw::render();
        }


        bool loop()
        {
            if (input::keyPressed(SDL_SCANCODE_ESCAPE) || input::keyPressed(SDL_SCANCODE_TAB))
            {
                room::load(previous_room);
                return false;
            }

            //draw::stencil::enable();
            //draw::stencil::clear(255);

            //for (int i=0;i<MAX_ROOMS;++i) drawn[i]=false;
            //drawRoom(room::getCurrent(), scroll.x, scroll.y);

            const int hover = draw::stencil::query(input::mouseX(), input::mouseY());
            if (hover!=255) {
                draw::color(BLACK); draw::fillrect(0,0,60,60);
                int line = 4;
                draw::print2(hover, -2, 1, 1, WHITE, FONT_ZOOM_VERTICAL);
                if (minirooms[hover].specials & 0x000000ff) draw::print2(actor::hero::getBoosterName(minirooms[hover].specials & 0xff), 1, line++, BLUE, FONT_ZOOM_NONE);
                if (minirooms[hover].specials & 0x0000ff00) draw::print2(actor::hero::getSkillName((minirooms[hover].specials>>8) & 0xff), 1, line++, GREEN, FONT_ZOOM_NONE);
                if (minirooms[hover].specials & 0x00ff0000) draw::print2(actor::hero::getPartName((minirooms[hover].specials>>16) & 0xff), 1, line++, YELLOW, FONT_ZOOM_NONE);
            }

            draw::render();

            if (input::mouseClk(1)) {
                const int clicked = draw::stencil::query(input::mouseX(), input::mouseY());
                if (clicked!=255) {
                    room::load(clicked);
                    return false;
                }
            }

            return true;
        }
    }
}
