local shine_step = 1
local shine_wait = 0
local shine_pos  = 0
local map_backup = {}
local actors_backup = {}

function distancia(a, b, hv)
    local dx = (a.x-b.x)
    local dy = (a.y-b.y)
    local r = 0
    if hv==nil then 
        r = math.sqrt(dx*dx+dy*dy)
    elseif hv=="h" then
        if math.abs(dy)<=16 then r=dx else r=999999 end
    elseif hv=="v" then
        if math.abs(dx)<=16 then r=dy else r=999999 end
    end
    return math.abs(r)
end

function in_table(tabla, valor)
    for _, v in ipairs(tabla) do
        if v == valor then return true end
    end
    return false
end

function table_key (tabla, valor)
    for k, v in pairs(tabla) do
        if v==valor then return k end
    end
    return 0
end

function collision(a, b)
    return     (a.x+a.bb.x+a.bb.w > b.x+b.bb.x) 
           and (a.x+a.bb.x < b.x+b.bb.x+b.bb.w) 
           and (a.y+a.bb.y+a.bb.h > b.y+b.bb.y) 
           and (a.y+a.bb.y < b.y+b.bb.y+b.bb.h)
end

function half_collision(a, b)
    return     ((a.x+a.bb.x+a.bb.w >= b.x+b.bb.x) 
           and (a.x+a.bb.x <= b.x+b.bb.x+b.bb.w) )
           or ((a.y+a.bb.y+a.bb.h >= b.y+b.bb.y) 
           and (a.y+a.bb.y <= b.y+b.bb.y+b.bb.h))
end

function v_collision(a, b)
    return     ((a.x+a.bb.x+a.bb.w >= b.x+b.bb.x) 
           and (a.x+a.bb.x <= b.x+b.bb.x+b.bb.w) )
           
end

function h_collision(a, b)
    return ((a.y+a.bb.y+a.bb.h >= b.y+b.bb.y) 
           and (a.y+a.bb.y <= b.y+b.bb.y+b.bb.h))
end

function remove_actor(actor)
    for index, value in pairs(actors) do
        if value == actor then
            table.remove(actors,index)
        end
    end
end

function set_actors_enabled_by_room(_enabled, _reason, room0, room1)
-- print("set_actors_enabled_by_room")
-- print(" hab_list")
    room1 = room1 or room0
    local rw=(room1-room0)%mapa_rooms_per_piso
    local hab_list = {}
    y = room0
    while y<=room1 do
        for x=y, y+rw do
            hab_list[x]=true
            -- print("  "..x)
        end
        y = y+mapa_rooms_per_piso
    end
    
    for index, actor in pairs(actors) do
        if hab_list[actor.hab] and actor~=abad then
            -- if actor.name then print(" "..actor.name) end
            -- if actor.disable_reason then print(" "..actor.disable_reason) end
            -- if actor.enabled then print("ENABLED") end
            
            if not _enabled then
            -- print("DISABLE ACTORS")
                -- disable
                if actor.enabled then
                    -- Si el actor està actiu -> deshabilitar amb motiu
                    actor.enabled=_enabled
                    actor.disable_reason = _reason
                    -- print("-> ".._reason)
                end
            else
                -- enable
                if actor.disable_reason and actor.disable_reason==_reason  then
                    -- Si l'actor te un motiu per haver estat deshabilitat -> habilitar i borrar motiu
                    actor.enabled=_enabled
                    actor.disable_reason = ""
                else
                    -- Habilitar l'actor si no te atribut disable_reason
                    actor.enabled=_enabled
                end
            end
        end
    end
end

function disable_actor_by_id( remove_set )
    local id_list = {}
    local ok = false
    -- Construir llista per a eliminar
    if type(remove_set) == "string" then
        id_list[remove_set] = true
        ok = true
    elseif type(remove_set) == "table" then
        for _, v in ipairs(remove_set) do 
            ok = true
            id_list[v] = true
        end
    end

    -- eliminar
    if ok then
        for index, actor in pairs(actors) do
            if id_list[actor.id] then
                -- actors[index]=nil
                actor.enabled=false
            end
        end
    end
end

function draw_shiny_rect(x, y, w, h, color, shine_color)
    draw.rect(x,y,w,h,color)
    
    local shine_w= 18
    
    -- Convertir el rectangle en una linea en checkpoints
    local p0 = 0
    local p1 = p0+w-1
    local p2 = p1+h
    local p3 = p2+w
    local p4 = p3+h
    
    -- Punt inicial y final de la recta del brillo
    local s0 = shine_step
    local s1 = s0+shine_w
    local y0 = 0

    if s0==p4 then
        shine_step=0
        draw.line(x, y, x+shine_w, y, shine_color)
    elseif s0<p1 then
        if s1<p1 then
            draw.line(x+s0, y, x+s1, y, shine_color)
        elseif s1<p2 then
            segment = s1-p1
            draw.line(x+s0, y, x+w-1, y, shine_color)
            draw.line(x+w-1, y, x+w-1, y+segment, shine_color)
        end
    elseif s0<p2 then
        if s1<p2 then
            segment = shine_w
            x0 = x+w-1
            y0= y+(s0-p1)-1
            draw.line(x0, y0, x0, y0+segment, shine_color)
        elseif s1<p3 then
            segment = s1-p2
            x0= x+w-1-segment
            y0= y+h-1
            draw.line(x0, y0, x0+segment, y0, shine_color)
            segment = p2-s0-1
            x0= x+w-1
            y0= y+(s0-p1)
            draw.line(x0, y0, x0, y0+segment, shine_color)
        end
    elseif s0<p3 then
        if s1<p3 then
            segment=shine_w
            x0 = x+w-1-(s1-p2)
            y0 = y+h-1
            draw.line(x0, y0, x0+shine_w, y0, shine_color)
        elseif s1<p4 then
            segment = s1-p3
            y0 = y+h-1
            draw.line(x,y0,x,y0-segment,shine_color)
            segment = p3-s0
            y0 = y+h-1
            draw.line(x,y0,x+segment,y0,shine_color)
        end
    elseif s0<p4 then
        if s1<p4 then
            segment = shine_w
            y0 = y+p4-s1
            draw.line(x,y0,x,y0+segment,shine_color)
        else
            segment = s1-p4
            draw.line(x,y,x+segment,y,shine_color)
            segment = p4-s0
            draw.line(x,y,x,y+segment,shine_color)
        end
    end
    shine_step = shine_step+1
end

function arc_text(str, x, y, col)
    font.current(font_sf)
    draw.text(str,x,y,col)
end

function arc_textB(str, x, y, col)
    font.current(font_sf)
    -- Crear el borde negre
	draw.text(str, x-1, y-1, 16)
    draw.text(str, x  , y-1, 16)
    draw.text(str, x+1, y-1, 16)
    
    draw.text(str, x-1, y,   16)
    draw.text(str, x+1, y,   16)
    
    draw.text(str, x-1, y+1, 16)
    draw.text(str, x  , y+1, 16)
    draw.text(str, x+1, y+1, 16)
	-- Escriure la cadena
    draw.text(str,x,y,col)
end

function editor_to_map_tile(editor_tile)
    local result = 0
    if editor_tile<256 then result = editor_tile + arcade_config.tiles_offset end
    return result
end

function map_to_editor_tile(map_tile)
    local result = map_tile - arcade_config.tiles_offset
    if map_tile==0 then result = 256  end
    return result
end

function mapa_backup(tx,ty,tile)
    table.insert(map_backup,{x=tx,y=ty,val=tile})
end

function mapa_restore_backup()
    for i = 1, #map_backup do
        local e = map_backup[i]
        map.tile(e.x, e.y, e.val)
    end
    map_backup = {}
end

function load_tilemap( sf_mapa, replace_map )
    local mapa_tw, mapa_th = surf.size(sf_mapa)
    local nrooms = mapa_rooms_per_piso*mapa_pisos
    local x = 0
    local y = 0
    local yroom = 0
    local xroom = 0

    map.surf(sf_mapa)
    if replace_map==nil then
        for ty=0,mapa_th-1 do
            if y == mapa_room_rows then
                yroom = yroom + mapa_rooms_per_piso 
                y = 0
            end
            xroom = yroom
            for tx=0,mapa_tw-1 do
                local tile=editor_to_map_tile(mapa[1+xroom][1+x+y*mapa_room_cols])
                map.tile(tx, ty, tile)
                x = x + 1
                if x == mapa_room_cols then 
                    x = 0
                    xroom = xroom + 1
                end
            end
            y = y +1
        end
    else
        local mapa_x0, mapa_y0 = coords.room_to_mini_tile( replace_map.r0.r, replace_map.r0.x, replace_map.r0.y )
        local mapa_x1, mapa_y1 = coords.room_to_mini_tile( replace_map.r1.r, replace_map.r1.x, replace_map.r1.y )
        local replace_rooms_per_piso = ((replace_map.r1.r-replace_map.r0.r)+1)%mapa_rooms_per_piso
        -- print(mapa_x0..", "..mapa_y0)
        -- print(mapa_x1..", "..mapa_y1)
        -- print(mapa_x1-mapa_x0..", "..mapa_y1-mapa_y0)
        -- print(replace_rooms_per_piso)
        
        y = 0
        for ty=mapa_y0,mapa_y1 do --24 -> 41 = 17 (18)
            if y == mapa_room_rows then
                yroom = yroom + replace_rooms_per_piso 
                y = 0
            end
            xroom = yroom
            for tx=mapa_x0, mapa_x1 do -- 36 -> 59 = 23 (24)
                -- print("ROOM= "..xroom.." ( "..x..", "..y.." ) <= "..(1+xroom)..", "..(1+x+y*mapa_room_cols))
                -- print(replace_map.map[1+xroom][1+x+y*mapa_room_cols])
                
                local tile=editor_to_map_tile(replace_map.map[1+xroom][1+x+y*mapa_room_cols])
                mapa_backup(tx, ty, map.tile(tx,ty))
                map.tile(tx, ty, tile)
                x = x + 1
                if x == mapa_room_cols then 
                    x = 0
                    xroom = xroom + 1
                end
            end
            y = y +1
        end
    end
end

-- DEBUG

-- Imprime cualquier valor, incluyendo tablas anidadas
function dump(value, indent)
    indent = indent or ""
    if type(value) ~= "table" then
        return tostring(value)
    end

    local parts = {"{"}
    for k, v in pairs(value) do
        local key = (type(k) == "string") and k or "["..tostring(k).."]"
        table.insert(parts,
            string.format("%s  %s = %s,",
                indent, key, dump(v, indent.."  ")))
    end
    table.insert(parts, indent.."}")
    return table.concat(parts, "\n")
end

function msg_print(x, y, msg, direct_print )
    local scr_x, scr_y
    direct_print = direct_print or false
    if direct_print then 
        scr_x = x
        scr_y = y
    else 
        scr_x, scr_y = viewp:screen_coords(x, y)
    end
    draw.rectf(scr_x,scr_y,64,8,16)
    draw.text(msg,scr_x+1,scr_y+1,2)
end

function view_coord(x, y, w, h, color)
    local scr_x, scr_y = viewp:screen_coords(x, y)
    draw.rect(scr_x, scr_y, w, h, color)
end

function debug.write_tile(x, y, yplus, print_type, align )
    local scr_x, scr_y = viewp:screen_coords(x, y)
    local hab, xx, yy = coords.world_to_tile(x, y)
    
    yplus = yplus or 0
    print_type = print_type or false
    align = align or "R"
    
    local txt_offset = -7
    if align=="R" then txt_offset = -14
    elseif align=="L" then txt_offset = 0
    end     
    
    draw.rectf(scr_x+txt_offset,scr_y+yplus,14,7,16)
    -- local msg = mapa_get_tile(hab,xx,yy)
    local msg = arc_get_tile(x,y)
    if print_type then
        msg = msg.." "..arc_check_tile(x, y)
    end
    draw.text(msg,scr_x+txt_offset+1,scr_y+1+yplus,2)
end

function empty_table(t)
  for _ in pairs(t) do
    return false
  end
  return true
end