require "abad"
require "gps"
require "gorro"
require "peu"
require "premiere"
require "elalien"
require "batman"
require "bol"
require "gota"
require "invisibl"
require "zombie"
require "caco"
require "trigger"
require "score"
require "imp"
require "bambolla"
require "cacau"
require "fireball"
require "switches"

modes={playing=0,editing=1}
--mode=modes.editing
mode=modes.playing

seltile = 0

actors={}
cameras={}
camera_names={[0]="GPS","Gorro","Peu de Paco","Premiere","EL_ALIEN","BatMan"}
current_camera=0
mute=false

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

function playmus(song,loop)
    if not mute then
        playmusic(song,loop)
    end
end

function playsnd(sound,volume)
    if not mute then
        --print(sound)
        return playsound(sound,volume)
    end
end

function game_init(menu)
    actors={}
    cameras={}
    camera_names={[0]="GPS","Gorro","Peu de Paco","Premiere","EL_ALIEN","BatMan"}
    current_camera=0

    -- ACTORS PRINCIPALS
    abad_init()
    table.insert(actors,abad)

    gps.init()
    table.insert(actors,gps)

    gorro.init()
    table.insert(actors,gorro)

    peu.init()
    table.insert(actors,peu)

    premiere.init()
    table.insert(actors,premiere)

    elalien.init()
    table.insert(actors,elalien)

    batman.init()
    table.insert(actors,batman)

    bol.init()
    table.insert(actors,bol)

    -- MALOTES PERSISTENTS
    table.insert(actors,gota.new(70,40,8,20))
    table.insert(actors,gota.new(70,72,8,30))
    table.insert(actors,gota.new(63,40,4,25))
    table.insert(actors,gota.new(63,72,4,20))
    table.insert(actors,gota.new(64,24,4,10))
    table.insert(actors,gota.new(64,48,4,25))
    table.insert(actors,gota.new(65,56,4,10))
    table.insert(actors,gota.new(65,63,4,25))
    table.insert(actors,gota.new(66,24,4,10))
    table.insert(actors,gota.new(66,32,4,15))
    table.insert(actors,gota.new(77,16,4,30))
    table.insert(actors,gota.new(77,72,4,25))

    table.insert(actors,invisible.new(77,40,32))
    table.insert(actors,invisible.new(77,48,32))
    table.insert(actors,invisible.new(58,16,32))
    table.insert(actors,invisible.new(58,16,32))

    table.insert(actors,zombie.new(2,24,24,false))
    table.insert(actors,caco.new(13,24,16,true))
    table.insert(actors,caco.new(20,24,16,false))
    table.insert(actors,zombie.new(32,24,24,false))
    table.insert(actors,caco.new(41,24,16,false))
    table.insert(actors,zombie.new(44,24,24,false))

    table.insert(actors,caco.new(50,24,16,false))
    table.insert(actors,caco.new(61,24,16,false))

    table.insert(actors,zombie.new(73,24,24,false))
    table.insert(actors,zombie.new(54,24,24,false))
    table.insert(actors,zombie.new(68,24,24,false))
    table.insert(actors,caco.new(57,24,16,false))
    table.insert(actors,zombie.new(46,24,24,false))
    table.insert(actors,caco.new(37,24,16,false))
    table.insert(actors,caco.new(26,24,16,false))
    table.insert(actors,zombie.new(28,24,24,false))
    table.insert(actors,caco.new(17,24,16,false))

    -- TRIGGERS
    if not menu then table.insert(actors,trigger.new(10,57,32,triggers.escena_abad_inici)) end
    table.insert(actors,trigger.new(11,16,32,triggers.escena_abad_corfes))

    table.insert(actors,trigger.new(31,12,32,triggers.escena_abad_portes))
    table.insert(actors,trigger.new(31,48,32,triggers.escena_abad_portes))
    table.insert(actors,trigger.new(71,56,24,triggers.escena_abad_portes))

    table.insert(actors,trigger.new(53,40,32,triggers.escena_abad_porta_casa))
    table.insert(actors,trigger.new(56,32,32,triggers.escena_abad_porta_batman))

    table.insert(actors,trigger.new(19,32,32,triggers.escena_habitacio_batman))

    table.insert(actors,trigger.new(14,40,32,triggers.teleport_a))
    table.insert(actors,trigger.new(67,8,32,triggers.teleport_b))
    table.insert(actors,trigger.new(29,40,32,triggers.teleport_c))
    table.insert(actors,trigger.new(61,8,32,triggers.teleport_d))
    score.create()
    
    cameras[0]=gps
    table.insert(cameras,gorro)
    table.insert(cameras,peu)
    table.insert(cameras,premiere)
    table.insert(cameras,elalien)
    table.insert(cameras,batman)

    mapa_do_backup()

    if menu then
        menu_sel=0
        menu_state=0
        abad.update = abad_nop
        game_update=update_menu
        menu_count=0
        menu_change_room=300
        menu_room=rnd(60)
        playmus(audio_main_song)
    else
       game_update=update_game
        stopmusic()
    end
    --fade.fadein()
end

function draw_hab(hab,x,y,editing)
    camera(-x,-y)
    mapa_draw(hab)

    if not editing then
        for key,actor in pairs(actors) do
            if actor.hab==hab then
                actor:draw()
            end
        end
        if imp.hab==hab then imp.draw() end
        if bambolla.hab==hab then bambolla.draw() end
        if cacau.hab==hab then cacau:draw() end
        if fireball.hab==hab then fireball:draw() end
    end
    camera(0,0)
end

function update_dialog()
    rectfill(16,16,112,50,12)
    rect(15,15,113,51,16)
    text("Save the map?",20,20,2)
    text("This cannot be undone",20,27,2)
    text("(Y)es         (N)o",25,40,2)

    if btnp(KEY_N) then
        game_update=update_game
    elseif btnp(KEY_Y) then
        mapa_save()
        game_update=update_game
    end
end

scroll=0
function update_game()
    cls(16)

    if mode==modes.editing then
        draw_hab(abad.hab,0,0,true)
        text(abad.hab,120,1,2)

        blit(0,64+scroll*8,128,48,0,48)
        color(3)
        local xx=(seltile&15)*8
        local yy=48+(seltile>>4)*8
        rect(xx,yy,xx+8,yy+8)
            text("EDIT",100,1,3)
        local hx = abad.hab%10
        local hy = math.floor(abad.hab/10)
        scroll=0
        if btnp(KEY_RIGHT) and hx<9 then
            abad.hab=abad.hab+1
        elseif btnp(KEY_LEFT) and hx>0 then
            abad.hab=abad.hab-1
        elseif btnp(KEY_DOWN) and hy<7 then
            abad.hab=abad.hab+10
        elseif btnp(KEY_UP) and hy>0 then
            abad.hab=abad.hab-10
        elseif btnp(KEY_RETURN) then
            mode=modes.playing
        elseif btnp(KEY_S) and (btn(KEY_LCTRL) or btn(KEY_LGUI)) then
            game_update=update_dialog
        elseif btnp(KEY_C) then
            mapa_cycle_colors(abad.hab)
        elseif btnp(KEY_M) then
            mapa_create_minimap()
            return
        end
        if btn(KEY_TAB) then
            scroll=2
        end

        local mx,my=mousex(),mousey()
        if mx>>3 < 12 and my>>3 < 6 then
            text(mx>>3,100,10,2)
            text(my>>3,111,10,2)
            text((mx>>3)+(my>>3)*12,118,10,2)
        end
        if mbtn(1) then
            if my>=48 then
                seltile=(mx>>3)+((my-48+(scroll*8))>>3)*16
            elseif mx<96 then
                mapa_set_tile(abad.hab,mx>>3,my>>3,seltile)
            end
        elseif mbtn(3) then
            if my<48 and mx<96 then
                mapa_set_tile(abad.hab,mx>>3,my>>3,256)
            end
        end
        if mx>>3 < 12 and my>>3 < 6 then
            local tx,ty=(mx>>3)<<3,(my>>3)<<3
            rect(tx,ty,tx+8,ty+8,3)
        end
    else
        if abad.hurting == 0 then
            draw_hab(abad.hab,0,0)
            --text(abad.hab,1,1,2)
            draw_hab(cameras[current_camera].hab,0,48)
            text(camera_names[current_camera],2,49,8)

            score.draw()
            setsource(tiles)
            prnt("x"..abad.vides,114,13,2)
            rectfill(102+(abad.energia>>1),30,122,37,16)
        else
            blit(0,0,16,9,50,40,16,9,true)
            if abad.hurting > 40 then
                prnt("x"..abad.vides+1,63,43,3)
            elseif abad.hurting < 20 then
                prnt("x"..abad.vides,63,43,2)
            end
        end

        mapa_update(abad.hab,cameras[current_camera].hab)

        for key,actor in pairs(actors) do
            actor:update()
            if actor.hab==cacau.hab and actor~=abad then
                if aabb(actor,cacau) then
                    if actor.hit~=nil then
                        actor:hit()
                        cacau.hab=-1
                    end
                end
            end
        end
        imp.update()
        bambolla.update()
        cacau.update()
        fireball.update()
        switches.update()
        
        --local hx = abad.hab%10
        --local hy = math.floor(abad.hab/10)
        --if btnp(KEY_RETURN) then
        --    mode=modes.editing
        --    mapa_restore_backup()
        --elseif btn(KEY_LSHIFT) and btnp(KEY_RIGHT) and hx<9 then
        --    abad.hab=abad.hab+1
        --elseif btn(KEY_LSHIFT) and btnp(KEY_LEFT) and hx>0 then
        --    abad.hab=abad.hab-1
        --elseif btn(KEY_LSHIFT) and btnp(KEY_DOWN) and hy<7 then
        --    abad.hab=abad.hab+10
        --elseif btn(KEY_LSHIFT) and btnp(KEY_UP) and hy>0 then
        --    abad.hab=abad.hab-10
        --elseif btnp(KEY_M) then
        --    mute = not mute
        --elseif btnp(KEY_ESCAPE) then
        --    pause()
        --end
        if btnp(KEY_ESCAPE) or padp(btnPause) then
            pause()
        end
        if abad.objects.gps~=nil then
            if btnp(KEY_1) then
                if abad.objects.gorro==nil and abad.objects.clau_premiere==nil then current_camera=1 end
            elseif btnp(KEY_2) then
                if abad.objects.peu==nil and abad.objects.clau_elalien==nil then current_camera=2 end
            elseif btnp(KEY_3) then
                current_camera=3
            elseif btnp(KEY_4) then
                current_camera=4
            elseif btnp(KEY_5) then
                current_camera=5
            end
            if padp(btnCycle1) then
                current_camera=current_camera+1
                if current_camera==6 then current_camera=1 end
                if current_camera==1 and (abad.objects.gorro or abad.objects.clau_premiere) then current_camera=2 end
                if current_camera==2 and (abad.objects.peu or abad.objects.clau_elalien) then current_camera=3 end
            elseif padp(btnCycle2) then
                current_camera=current_camera-1
                if current_camera==0 then current_camera=5 end
                if current_camera==2 and (abad.objects.peu or abad.objects.clau_elalien) then current_camera=1 end
                if current_camera==1 and (abad.objects.gorro or abad.objects.clau_premiere) then current_camera=5 end
            end
        end
    end
end

function redraw_menu_hab()
    draw_hab(menu_room,16,41)
    rectfill(0,0,14,96,16)
    rectfill(114,0,191,96,16)
    rect(15,40,113,89,2)
    mapa_update(abad.hab,menu_room)

    for key,actor in pairs(actors) do
        actor:update()
    end
    imp.update()
    bambolla.update()
    cacau.update()
    fireball.update()
    switches.update()
end

function update_menu()
    menu_change_room=menu_change_room-1
    if menu_change_room==0 then
        menu_room = rnd(60)
        menu_change_room=300
    end

    cls(16)
    text("C A C A U S", 42, 8, 15)

    if menu_state == 0 then
        menu_count=menu_count+1
        local parpadeig=false
        if menu_count>=20 then
            parpadeig=true
            if menu_count>40 then menu_count=0 end
        end
        if (not parpadeig or menu_sel~=0) then text("JUGAR", 54, 16, 13) end
        if (not parpadeig or menu_sel~=1) then text("REDEFINIR TECLAT", 32, 24, 13) end
        if (not parpadeig or menu_sel~=2) then text("REDEFINIR GAMEPAD", 30, 32, 13) end

        redraw_menu_hab()

        if btnp(keyShoot) or btnp(KEY_SPACE) or padp(BTN_A) or padp(btnShoot) then
            if menu_sel==0 then
                game_exit()
                game_init()
                fade.fadeoutin()
            elseif menu_sel==1 then
                menu_count=0
                menu_state=1
            else
                menu_count=0
                menu_state=2
            end
        elseif btnp(keyDown) or btnp(KEY_DOWN) or padp(BTN_DOWN) or padp(btnDown) then
            menu_sel=menu_sel+1
            if menu_sel==3 then menu_sel=0 end
        elseif btnp(keyUp) or btnp(KEY_UP) or padp(BTN_UP) or padp(btnUp) then
            menu_sel=menu_sel-1
            if menu_sel==-1 then menu_sel=2 end
        elseif btnp(KEY_M) then
            mute = not mute
            if mute then
                stopmusic()
            else
                playmus(audio_main_song)
            end
        elseif btnp(KEY_ESCAPE) or padp(btnPause) then
            quit()
        end
    elseif menu_state==1 then
        if btnp(KEY_ESCAPE) then
            menu_count = 0
            menu_state = 0
        end
        if menu_count==0 then
            text("PULSA TECLA PER A AMUNT", 20, 24, 13)
            local key = btnp();
            if key ~= 0 and key~=KEY_ESCAPE then
                menu_count = 1
                keyUp=key
                setconf("keyup", keyUp)
            end
        elseif menu_count==1 then
            text("PULSA TECLA PER A AVALL", 20, 24, 13)
            local key = btnp();
            if key ~= 0 and key~=KEY_ESCAPE then
                menu_count = 2
                keyDown=key
                setconf("keydown", keyDown)
            end
        elseif menu_count==2 then
            text("PULSA TECLA PER A ESQUERRA", 14, 24, 13)
            local key = btnp();
            if key ~= 0 and key~=KEY_ESCAPE then
                menu_count = 3
                keyLeft=key
                setconf("keleft", keyLeft)
            end
        elseif menu_count==3 then
            text("PULSA TECLA PER A DRETA", 20, 24, 13)
            local key = btnp();
            if key ~= 0 and key~=KEY_ESCAPE then
                menu_count = 4
                keyRight=key
                setconf("keyright", keyRight)
            end
        elseif menu_count==4 then
            text("PULSA TECLA PER A BOTAR", 20, 24, 13)
            local key = btnp();
            if key ~= 0 and key~=KEY_ESCAPE then
                menu_count = 5
                keyJump=key
                setconf("keyjump", keyJump)
            end
        elseif menu_count==5 then
            text("PULSA TECLA PER A DISPAR", 18, 24, 13)
            local key = btnp();
            if key ~= 0 and key~=KEY_ESCAPE then
                menu_count = 0
                menu_state = 0
                keyShoot=key
                setconf("keyshoot", keyShoot)
            end
        end
    else
        if btnp(KEY_ESCAPE) then
            menu_count = 0
            menu_state = 0
        end
        if menu_count==0 then
            text("PULSA BOTÓ PER A AMUNT", 22, 24, 13)
            local btn = padp();
            if btn ~= -1 then
                menu_count = 1
                btnUp=btn
                setconf("btnup", btnUp)
            end
        elseif menu_count==1 then
            text("PULSA BOTÓ PER A AVALL", 22, 24, 13)
            local btn = padp();
            if btn ~= -1 then
                menu_count = 2
                btnDown=btn
                setconf("btndown", btnDown)
            end
        elseif menu_count==2 then
            text("PULSA BOTÓ PER A ESQUERRA", 16, 24, 13)
            local btn = padp();
            if btn ~= -1 then
                menu_count = 3
                btnLeft=btn
                setconf("keleft", btnLeft)
            end
        elseif menu_count==3 then
            text("PULSA BOTÓ PER A DRETA", 22, 24, 13)
            local btn = padp();
            if btn ~= -1 then
                menu_count = 4
                btnRight=btn
                setconf("btnright", btnRight)
            end
        elseif menu_count==4 then
            text("PULSA BOTÓ PER A BOTAR", 22, 24, 13)
            local btn = padp();
            if btn ~= -1 then
                menu_count = 5
                btnJump=btn
                setconf("btnjump", btnJump)
            end
        elseif menu_count==5 then
            text("PULSA BOTÓ PER A DISPAR", 20, 24, 13)
            local btn = padp();
            if btn ~= -1 then
                menu_count = 0
                menu_state = 0
                btnShoot=btn
                setconf("btnshoot", btnShoot)
            end
        end
    end

end

function game_exit()
    mapa_restore_backup()
    actors={}
    cameras={}
end

function aabb(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 pause()
    setsource(0)
    setdest(back)
    blit(0,0,128,96,0,0)
    setdest(0)
    setsource(tiles)
    pausa_option=1
    pause_old_update=game_update
    game_update=update_pause
end

function update_pause()
    rectfill(16,16,112,80,16)
    rect(16,16,112,80,15)
    prnt("PAUSA",54,30,15)
    if pausa_option==1 then
        rect(28,48,100,56,13)
    else
        rect(28,58,100,66,13)
    end
    prnt("CONTINUAR",30,50,14)
    prnt("EIXIR",30,60,14)

    if btnp(KEY_ESCAPE) then
        setsource(back)
        blit(0,0,128,96,0,0)
        setsource(tiles)    
        game_update = pause_old_update
    elseif btnp(keyDown) or btnp(keyUp) or padp(btnDown) or padp(btnUp) then
        if pausa_option==1 then pausa_option=2 else pausa_option=1 end
    elseif btnp(keyShoot) or padp(btnShoot) then
        if pausa_option==1 then
            setsource(back)
            blit(0,0,128,96,0,0)
            setsource(tiles)    
            game_update = pause_old_update
        else
            game_exit()
            game_init(true)
        end
    end
end
