require ":modules.menu"
require ":utils.msgbox"
require ":modules.items"

editor = {

    layer = LAYER_FOREGROUND,
    brush={w=2,h=1,tiles={16,17}},
    selection=nil,
    ants=0xc936,
    modified = false,
    item_selected=nil,
    item_hovered=nil,
    item_dragged=nil,
    dragged_start_pos=nil,
    flip=false,
    msg=nil,
    msg_timeout=0,

    enable = function()
        app.update = editor.update
        sys.beat(5)
        shader.disable();
        pal.set(palfade.original)
    end,

    update = function()
        if sys.beat() then
            editor.ants = (editor.ants<<12) | (editor.ants>>4)
        end

        view.origin(0,0)
        surf.target(0)

        -- Pintar fondo quadrejat, per si la capa background està oculta
        for y=0,104,8 do
            for x=0,160,8 do
                local color = (((x+y)//8)%2==0) and 23 or 16
                draw.rectf(x, y, 8, 8, color);
            end
        end

        -- Pintar el mapa i sprites
        rooms.draw()


        local mx, my = mouse.pos()
        local tx, ty = (mx>>3), (my>>3)
        mx, my = tx<<3, ty<<3

        if menu.hidden then
            if editor.layer==LAYER_BACKGROUND or editor.layer==LAYER_FOREGROUND then
                if editor.selection then
                    local rx1,ry1,rx2,ry2=editor.selection.x1<<3,editor.selection.y1<<3,editor.selection.x2<<3,editor.selection.y2<<3
                    if rx1>rx2 then rx1,rx2=rx2,rx1 end
                    if ry1>ry2 then ry1,ry2=ry2,ry1 end
                    draw.mode(draw.PATTERN)
                    draw.pattern(editor.ants)
                    draw.rect(rx1-1, ry1-1, rx2-rx1+10, ry2-ry1+10, 28)
                    draw.mode(draw.NORMAL)
                else
                    draw.rect(mx-1, my-1, editor.brush.w*8+2, editor.brush.h*8+2, 28)
                    draw.rect(mx, my, editor.brush.w*8, editor.brush.h*8, 1)
                end
                if mouse.down(mouse.LEFT) then
                    editor.stamp(tx,ty)
                    editor.modified = true
                    --map.tile(tx,ty,editor.brush.tiles[1])
                end
                if mouse.down(mouse.RIGHT) then
                    if editor.selection then
                        editor.selection.x2=tx
                        editor.selection.y2=ty
                    else
                        editor.selection={}
                        editor.selection.x1=tx
                        editor.selection.y1=ty
                        editor.selection.x2=tx
                        editor.selection.y2=ty
                    end
                else
                    if editor.selection then
                        editor.create_stamp()
                        editor.selection=nil
                    end
                end
            else
                if editor.item_dragged then
                    if mouse.down(mouse.LEFT) then
                        local sprite = sprites.list[editor.item_dragged]
                        --sprite.pos.x, sprite.pos.y = tx*8, ty*8
                        sprite.pos = {x=tx*8, y=ty*8}
                    else
                        map.surf(rooms.surf_items)
                        local tile = map.tile(editor.dragged_start_pos.x//8,editor.dragged_start_pos.y//8)
                        map.tile(editor.dragged_start_pos.x//8,editor.dragged_start_pos.y//8,0)
                        map.tile(tx,ty,tile)
                        editor.item_dragged = nil
                        --local sprite = sprites.list[editor.item_dragged]
                        --sprite.pos.x,sprite.pos.y = editor.dragged_start_pos.x,editor.dragged_start_pos.y
                    end
                elseif mouse.down(mouse.LEFT) and editor.item_hovered then
                    editor.item_dragged = editor.item_hovered
                    --print("item dragged: "..editor.item_dragged.."\n")
                    local sprite = sprites.list[editor.item_dragged]
                    editor.dragged_start_pos = {x=sprite.pos.x, y=sprite.pos.y}
                    editor.modified = true
                end
                if mouse.press(mouse.LEFT) then
                    if not editor.item_hovered and not editor.item_dragged and editor.item_selected then
                        map.surf(rooms.surf_items)
                        --print(editor.item_selected)
                        map.tile(tx,ty,editor.item_selected)
                        local room = tx + ty * 8
                        table.insert(sprites.list, templates.create(items[editor.item_selected].name, {pos={x=tx*8, y=ty*8},flipped=editor.flip, room=room}))
                        editor.modified = true
                        --surf.target(0)
                    end
                end
                if mouse.press(mouse.RIGHT) then
                    editor.item_selected = nil
                end
                if not editor.item_hovered and not editor.item_dragged and editor.item_selected then
                    local k = items[editor.item_selected]
                    surf.source(surf_sprites)
                    draw.surf(k.visual.x, k.visual.y, k.visual.w, k.visual.h, mx, my, k.visual.w, k.visual.h, editor.flip)
                end
            end

            if key.press(key.ESCAPE) then
                --editor.quit()
                menu.toggle()
            elseif key.press(key.RIGHT) and rooms.pos.x < 20*7 then
                rooms.pos.x = rooms.pos.x + 20
                sprites.add_from_room(rooms.pos.x, rooms.pos.y)
            elseif key.press(key.LEFT) and rooms.pos.x > 0 then
                rooms.pos.x = rooms.pos.x - 20
                sprites.add_from_room(rooms.pos.x, rooms.pos.y)
            elseif key.press(key.DOWN) and rooms.pos.y < 13*7 then
                rooms.pos.y = rooms.pos.y + 13
                sprites.add_from_room(rooms.pos.x, rooms.pos.y)
            elseif key.press(key.UP) and rooms.pos.y > 0 then
                rooms.pos.y = rooms.pos.y - 13
                sprites.add_from_room(rooms.pos.x, rooms.pos.y)
            elseif key.press(key.TAB) or key.press(key.ESCAPE) then
                if editor.layer==LAYER_BACKGROUND or editor.layer==LAYER_FOREGROUND then
                    editor.tilepicker.show()
                else
                    editor.itempicker.show()
                end
            elseif key.press(key.P) then
                sprites.hero.pos.x = tx*8-4
                sprites.hero.pos.y = ty*8-9
            elseif key.press(key.F9) then
                editor.play()
            elseif key.press(key.F11) then
                reload_textures()
            elseif key.press(key.N1) then
                editor.layer=LAYER_FOREGROUND
                editor.msg="FOREGROUND"
                editor.msg_timeout = 20
            elseif key.press(key.N2) then
                editor.layer=LAYER_BACKGROUND
                editor.msg="BACKGROUND"
                editor.msg_timeout = 20
            elseif key.press(key.N3) then
                editor.layer=LAYER_ITEMS
                editor.msg="ITEMS"
                editor.msg_timeout = 20
            end

            if editor.layer==LAYER_ITEMS then
                if key.press(key.F) then
                    if not editor.item_hovered and editor.item_selected then
                        editor.flip = not editor.flip
                    elseif editor.item_hovered then
                        local sprite = sprites.list[editor.item_hovered]
                        sprite.flipped = not sprite.flipped
                        map.surf(rooms.surf_items)
                        local tile = map.tile(sprite.pos.x//8, sprite.pos.y//8)
                        if tile > 0x7f then tile = tile & 0x7f else tile = tile | 0x80 end
                        map.tile(sprite.pos.x//8, sprite.pos.y//8, tile)
                        editor.modified = true
                    end
                end
                if editor.item_hovered and key.press(key.DELETE) then
                    local sprite = sprites.list[editor.item_hovered]
                    map.surf(rooms.surf_items)
                    map.tile(sprite.pos.x//8,sprite.pos.y//8,0)
                    sprites.remove(sprite)
                end
            end
        end
        view.origin(0,0)
        draw.text(rooms.pos.x//20,1,96,28)
        draw.text(rooms.pos.y//13,5,96,28)

        if editor.msg_timeout > 0 then
            editor.msg_timeout = editor.msg_timeout - 1
            draw.text(editor.msg, 10, 96, 8)
        end

        menu.draw()

    end,

    create_stamp=function()
        if editor.layer == LAYER_FOREGROUND then
            map.surf(rooms.surf_foreground)
        elseif editor.layer == LAYER_BACKGROUND then
            map.surf(rooms.surf_background)
        end
        local tx1,ty1,tx2,ty2=editor.selection.x1,editor.selection.y1,editor.selection.x2,editor.selection.y2
        if tx1>tx2 then tx1,tx2=tx2,tx1 end
        if ty1>ty2 then ty1,ty2=ty2,ty1 end
        editor.brush.w=tx2-tx1+1
        editor.brush.h=ty2-ty1+1
        local w,h=editor.brush.w,editor.brush.h
        local p=1
        for y=1,h do
            for x=1,w do
                editor.brush.tiles[p]=map.tile(tx1+x-1,ty1+y-1)
                --map.tile(tx+x-1,ty+y-1,editor.brush.tiles[p])
                p=p+1
            end
        end
    end,

    stamp=function(tx,ty)
        if editor.layer == LAYER_FOREGROUND then
            map.surf(rooms.surf_foreground)
        elseif editor.layer == LAYER_BACKGROUND then
            map.surf(rooms.surf_background)
        end

        local w,h=editor.brush.w,editor.brush.h
        local p=1
        for y=1,h do
            for x=1,w do
                local fx, fy = tx+x-1, ty+y-1
                if fx < rooms.pos.x+20 and fy < rooms.pos.y+13 then
                    map.tile(fx,fy,editor.brush.tiles[p])
                end
                p=p+1
            end
        end
    end,

    quit=function()
        if editor.modified then
            msgbox.show("SAVE CHANGES BEFORE CLOSING?",
                {"YOU HAVE UNSAVED CHANGES. IF YOU EXIT", "WITHOUT SAVING, CHANGES WILL BE LOST."}, 
                {
                    {"CANCEL", app.pop},
                    {" EXIT ", sys.quit},
                    {" SAVE ", function() rooms.save() sys.quit() end}
                } )
        else
            sys.quit()
        end
    end,

    play=function()
        if editor.modified then
            msgbox.show("IE MEN!",
                {"Hi ha canvis sense guardar.", "Vols guardar-los abans de jugar?"}, 
                {
                    {"Cancel", app.pop},
                    {"No", function() app.pop() game.enable() end},
                    {"Yes", function() app.pop() rooms.save() game.enable() end}
                } )
        else
            game.enable()
        end
    end,

    tilepicker = {
        surf_back = nil,
        pos_y = 24,

        show = function()
            if editor.tilepicker.surf_back == nil then editor.tilepicker.surf_back = surf.new(160,104) end
            surf.source(0)
            surf.target(editor.tilepicker.surf_back)
            view.origin(0,0)
            surf.clip()
            draw.surf(0,0,160,104,0,0)
            app.push(editor.tilepicker.update_tiles)
            tweening.add(104,24,0.25,easing.easeOutCubic,function(value,n,finished)editor.tilepicker.pos_y=value end)
        end,

        close = function()
            tweening.add(24,104,0.25,easing.easeInCubic,function(value,n,finished)editor.tilepicker.pos_y=value if finished then app.pop() end end)
        end,

        update_tiles = function()
            surf.source(editor.tilepicker.surf_back)
            surf.target(0)
            view.origin(0,0)
            surf.clip()
            draw.surf(0,0,160,104,0,0)

            view.origin(8,editor.tilepicker.pos_y)
            draw.rrect(0,-1,144,84,3,17)
            draw.rrectf(0,0,144,84,3,20)
            draw.text("CHOOSE TILES:",8,2,17)

            view.origin(16,editor.tilepicker.pos_y+8)

            -- Pintar fondo quadrejat, per si la capa background està oculta
            for y=0,56,8 do
                for x=0,120,8 do
                    local color = (((x+y)//8)%2==0) and 23 or 16
                    draw.rectf(x, y, 8, 8, color);
                end
            end

            surf.source(surf_tiles)
            --surf.cls(1)
            draw.surf(0,0,128,128,0,0)

            local mx, my = mouse.pos()
            local tx, ty = mx>>3, my>>3
            mx, my = tx<<3, ty<<3

            draw.rect(mx-1, my-1, 10, 10, 28)
            draw.rect(mx, my, 8, 8, 1)

            if mouse.press(mouse.LEFT) then
                if tx<16 and ty<16 then
                    editor.brush.w=1
                    editor.brush.h=1
                    editor.brush.tiles={}
                    editor.brush.tiles[1]=ty*16+tx
                end
                editor.tilepicker.close()
            end

            if key.press(key.TAB) or key.press(key.ESCAPE) then
                editor.tilepicker.close()
            end

        end
    },

    itempicker = {
        surf_back = nil,
        pos_y = 24,
        scroll = 0,

        show = function()
            if editor.itempicker.surf_back == nil then editor.itempicker.surf_back = surf.new(160,104) end
            surf.source(0)
            surf.target(editor.itempicker.surf_back)
            view.origin(0,0)
            surf.clip()
            draw.surf(0,0,160,104,0,0)
            app.push(editor.itempicker.update_items)
            tweening.add(104,24,0.25,easing.easeOutCubic,function(value,n,finished)editor.itempicker.pos_y=value end)
        end,

        close = function()
            tweening.add(24,104,0.25,easing.easeInCubic,function(value,n,finished)editor.itempicker.pos_y=value if finished then app.pop() end end)
        end,

        update_items = function()
            surf.source(editor.itempicker.surf_back)
            surf.target(0)
            view.origin(0,0)
            surf.clip()
            draw.surf(0,0,160,104,0,0)

            view.origin(8,editor.itempicker.pos_y)
            draw.rrect(0,-1,144,84,3,17)
            draw.rrectf(0,0,144,84,3,20)
            draw.text("CHOOSE ITEM:",8,2,17)

            view.origin(16,editor.itempicker.pos_y+8-editor.itempicker.scroll)
            surf.clip(16,editor.itempicker.pos_y+8,128,64)

            surf.source(surf_sprites)
            local mx, my = mouse.pos()
            local x,y = 0,0
            for i,k in pairs(items) do
                local w = math.max(k.visual.w, #k.label*4)
                if x+w > 128 then
                    y=y+32
                    x=0
                end
                local ox = (w-k.visual.w)/2
                draw.text(k.label, x, y, 15)
                draw.surf(k.visual.x, k.visual.y, k.visual.w, k.visual.h, x+ox, y+7)
                if mx>x and mx<x+w and my>y and my<y+7+k.visual.h then
                    draw.rect(x+ox, y+7, k.visual.w, k.visual.h, 28)
                    if mouse.press(mouse.LEFT) then
                        editor.item_selected = i
                        editor.itempicker.close()
                    end
                end
                x=x+w+4
            end
            y=y+32
            local lift_h = math.floor(4096/y)
            local lift_y = math.floor(((64-lift_h)*editor.itempicker.scroll)/(y-64))

            view.origin(16,editor.itempicker.pos_y+8)
            surf.clip()

            draw.rrectf(124,0,5,64,1,17)
            draw.rrectf(124,lift_y,5,lift_h,1,2)

            local mw = mouse.wheel()
            editor.itempicker.scroll = editor.itempicker.scroll - mw*8

            if key.press(key.TAB) or key.press(key.ESCAPE) then
                editor.itempicker.close()
            elseif key.press(key.UP) then
                editor.itempicker.scroll = editor.itempicker.scroll - 16
            elseif key.press(key.DOWN) then
                editor.itempicker.scroll = editor.itempicker.scroll + 16
            end

            if editor.itempicker.scroll < 0 then editor.itempicker.scroll = 0 end
            if editor.itempicker.scroll > y-64 then editor.itempicker.scroll = y-64 end

            draw.text(tostring(editor.itempicker.scroll),20,20,1)
        end
    }
}