if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE")=="1" then
    lldebugger=require('lldebugger')
    lldebugger.start()
    REQUEST_BREAK=lldebugger.requestBreak
else
    REQUEST_BREAK=function()end
end

require 'funcs'
DEBUG_showKey = false

PENTO_MODE = false
SAVE_DIR    = 'saves/'
REPLAY_DIR  = 'saves/replays/'
if not love.filesystem.getInfo(REPLAY_DIR) then
    love.filesystem.createDirectory(REPLAY_DIR)
end
CONFIG_FILE = 'config.sav'
HIscoreFILE = 'hiscores.sav'

-- Text "LOADING..."
local loaded = {}
local last_loading
local loadedCounter = 0
--- Show the loading text while we are loading resources<br>
--- **WARNING**: should only be used while loading the game!
function ShowLoadingText(thing)
    if last_loading then table.insert(loaded, last_loading) end
    last_loading = thing
    loadedCounter = loadedCounter + 1

    love.graphics.replaceTransform(GLOBAL_TRANSFORM)
    love.graphics.setFont(love.graphics.newFont(20))
    love.graphics.clear()
    
    drawText(
        "Loading Tromi... ["..loadedCounter.." / 3]\nPlease wait, don't touch anywhere or press any key!\n\nLoading: "..thing,
        10,0,1e99,"left"
    )
    for i, t in pairs(loaded) do
        drawText("Loaded "..t,10,80+20*i,1e99,"left")
    end

    love.graphics.flushBatch()
    love.graphics.present()
end

function love.load()
    math.randomseed(os.time())
    require "settings"

    -- Window stuffs
    love.mouse.setVisible(false)
    love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
    love.window.setFullscreen(SETTINGS["fullscreen"])

    -- Make a new transformer
    GLOBAL_TRANSFORM = love.math.newTransform()
    love.resize(love.graphics.getWidth(), love.graphics.getHeight())

    -- Now it's real time to load all stuffs!
    highscores = {}
    require "load"      -- Most game's resources are loaded in here
    require "scene"
    require "game.vctrl"   -- VCTRL

    SCENE = SETTINGS.firstTime and InputConfigScene(true) or TitleScene()
    VCTRL.toggle(love.system.getOS()=='Android' or true)
    VCTRL.new{
        -- {type='button',x=    100,y=320,key=   'up',icon=           'up',r=35,iconSize=60,alpha=0.75},
        -- {type='button',x=    160,y=380,key='right',icon=        'right',r=35,iconSize=60,alpha=0.75},
        -- {type='button',x=    100,y=440,key= 'down',icon=         'down',r=35,iconSize=60,alpha=0.75},
        -- {type='button',x=     40,y=380,key= 'left',icon=         'left',r=35,iconSize=60,alpha=0.75},
        -- {type='button',x=640-100,y=320,key=  'f16',icon='rotate_right2',r=35,iconSize=60,alpha=0.75},
        -- {type='button',x=640-160,y=380,key=  'f14',icon= 'rotate_left2',r=35,iconSize=60,alpha=0.75},
        -- {type='button',x=640-100,y=440,key=  'f15',icon= 'rotate_right',r=35,iconSize=60,alpha=0.75},
        -- {type='button',x=640- 40,y=380,key=  'f13',icon=  'rotate_left',r=35,iconSize=60,alpha=0.75},
        {type='button',x=     70,y=280,key=   'up',icon=           'up',r=45,iconSize=60,alpha=0.75},
        {type='button',x=    145,y=355,key='right',icon=        'right',r=45,iconSize=60,alpha=0.75},
        {type='button',x=     70,y=430,key= 'down',icon=         'down',r=45,iconSize=60,alpha=0.75},
        {type='button',x=     -5,y=355,key= 'left',icon=         'left',r=45,iconSize=60,alpha=0.75},
        {type='button',x=640- 70,y=280,key=  'f16',icon='rotate_right2',r=45,iconSize=60,alpha=0.75},
        {type='button',x=640-145,y=355,key=  'f14',icon= 'rotate_left2',r=45,iconSize=60,alpha=0.75},
        {type='button',x=640- 70,y=430,key=  'f15',icon= 'rotate_right',r=45,iconSize=60,alpha=0.75},
        {type='button',x=640- -5,y=355,key=  'f13',icon=  'rotate_left',r=45,iconSize=60,alpha=0.75},
    }
end

function love.resize(w, h)
    local scale_factor = math.min(w / 640, h / 480)
    GLOBAL_TRANSFORM:setTransformation(
        (w - scale_factor * 640) / 2,
        (h - scale_factor * 480) / 2,
        0,
        scale_factor
    )
end

function love.draw()
    love.graphics.replaceTransform(GLOBAL_TRANSFORM)
    love.graphics.clear()
    love.graphics.push()

    SCENE:render()
    VCTRL.draw()

    -- -- Grid system
    -- love.graphics.replaceTransform(GLOBAL_TRANSFORM)

    -- love.graphics.setColor(1,1,1,0.5)
    -- love.graphics.setLineWidth(1)
    -- -- From 0 to X
    -- for ix=1,math.floor(64) do
    --     love.graphics.line(10*ix,0,10*ix,480)
    -- end
    -- -- From 0 to Y
    -- for iy=1,math.floor(48) do
    --     love.graphics.line(0,10*iy,640,10*iy)
    -- end

    if DEBUG_showKey then
        drawText(
            "Pressed: "..(LastPressedKey or '[NONE]').." | Released: "..(LastReleasedKey or '[NONE]'),
            0,0,1000,"left"
        )
    end

    love.graphics.pop()
end

local return_scancode, escape_scancode = love.keyboard.getScancodeFromKey('return'), love.keyboard.getScancodeFromKey('escape')
function love.touchpressed(id,x,y)
    local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
    if not VCTRL.press(x,y,id) then
        if x >= 320 and x <= 640 then
            love.keypressed('escape', escape_scancode)
        elseif x >= 0 and x <= 320 then
            love.keypressed('return', return_scancode)
        end
    end
end
function love.touchreleased(id,x,y)
    if not VCTRL.release(id) then
        if x >= 320 and x <= 640 then
            love.keyreleased('escape', escape_scancode)
        elseif x >= 0 and x <= 320 then
            love.keyreleased('return', return_scancode)
        end
    end
end

function love.keypressed(key, scancode)
    local input_pressed=nil

    -- global hotkeys
    if scancode == "f4" then
        SETTINGS["fullscreen"] = not SETTINGS["fullscreen"]
        love.window.setFullscreen(SETTINGS["fullscreen"])
    elseif scancode == "f2" and SCENE.title ~= "Input Config" and SCENE.title ~= "Game" then
        SCENE = InputConfigScene()
    -- function keys are reserved
    elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f1[0-2]+$") then
        return
    -- escape is reserved for menu_back
    elseif scancode == "escape" or scancode == "acback" then
        SCENE:onInputPress({input="menu_back", type="key", key=key, scancode=scancode})
    -- pass any other key to the scene, with its configured mapping
    else
        if SETTINGS.input and SETTINGS.input.keys then
            input_pressed = SETTINGS.input.keys[scancode]
        end
        SCENE:onInputPress({input=input_pressed, type="key", key=key, scancode=scancode})
    end

    LastPressedKey = input_pressed or scancode
end

function love.keyreleased(key, scancode)
    local input_released = nil

    -- escape is reserved for menu_back
    if scancode == "escape" or scancode == 'acback' then
        SCENE:onInputRelease({input="menu_back", type="key", key=key, scancode=scancode})
    -- function keys are reserved
    elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f1[0-2]+$") then
        return
    -- handle all other keys; tab is reserved, but the input config scene keeps it from getting configured as a game input, so pass tab to the scene here
    else
        if SETTINGS.input and SETTINGS.input.keys then
            input_released = SETTINGS.input.keys[scancode]
        end
        SCENE:onInputRelease({input=input_released, type="key", key=key, scancode=scancode})
    end

    LastReleasedKey = input_released or scancode
end

function love.joystickpressed(joystick, button)
    local input_pressed = nil
    if
        SETTINGS.input and
        SETTINGS.input.joysticks and
        SETTINGS.input.joysticks[joystick:getName()] and
        SETTINGS.input.joysticks[joystick:getName()].buttons
    then
        input_pressed = SETTINGS.input.joysticks[joystick:getName()].buttons[button]
    end
    SCENE:onInputPress({input=input_pressed, type="joybutton", name=joystick:getName(), button=button})
end

function love.joystickreleased(joystick, button)
    local input_released = nil
    if
        SETTINGS.input and
        SETTINGS.input.joysticks and
        SETTINGS.input.joysticks[joystick:getName()] and
        SETTINGS.input.joysticks[joystick:getName()].buttons
    then
        input_released = SETTINGS.input.joysticks[joystick:getName()].buttons[button]
    end
    SCENE:onInputRelease({input=input_released, type="joybutton", name=joystick:getName(), button=button})
end

function love.joystickaxis(joystick, axis, value)
    local input_pressed = nil
    local positive_released = nil
    local negative_released = nil
    if
        SETTINGS.input and
        SETTINGS.input.joysticks and
        SETTINGS.input.joysticks[joystick:getName()] and
        SETTINGS.input.joysticks[joystick:getName()].axes and
        SETTINGS.input.joysticks[joystick:getName()].axes[axis]
    then
        if math.abs(value) >= 1 then
            input_pressed = SETTINGS.input.joysticks[joystick:getName()].axes[axis][value >= 1 and "positive" or "negative"]
        end
        positive_released = SETTINGS.input.joysticks[joystick:getName()].axes[axis].positive
        negative_released = SETTINGS.input.joysticks[joystick:getName()].axes[axis].negative
    end
    if math.abs(value) >= 1 then
        SCENE:onInputPress({input=input_pressed, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
    else
        SCENE:onInputRelease({input=positive_released, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
        SCENE:onInputRelease({input=negative_released, type="joyaxis", name=joystick:getName(), axis=axis, value=value})
    end
end

local last_hat_direction = ""
local directions = {
    ["u"] = "up",
    ["d"] = "down",
    ["l"] = "left",
    ["r"] = "right",
}

function love.joystickhat(joystick, hat, direction)
    local input_pressed = nil
    local has_hat = false
    if
        SETTINGS.input and
        SETTINGS.input.joysticks and
        SETTINGS.input.joysticks[joystick:getName()] and
        SETTINGS.input.joysticks[joystick:getName()].hats and
        SETTINGS.input.joysticks[joystick:getName()].hats[hat]
    then
        if direction ~= "c" then
            input_pressed = SETTINGS.input.joysticks[joystick:getName()].hats[hat][direction]
        end
        has_hat = true
    end
    if input_pressed then
        for i = 1, #direction do
            local char = direction:sub(i, i)
            local _, count = last_hat_direction:gsub(char, char)
            if count == 0 then
                SCENE:onInputPress({input=SETTINGS.input.joysticks[joystick:getName()].hats[hat][char], type="joyhat", name=joystick:getName(), hat=hat, direction=char})
            end
        end
        for i = 1, #last_hat_direction do
            local char = last_hat_direction:sub(i, i)
            local _, count = direction:gsub(char, char)
            if count == 0 then
                SCENE:onInputRelease({input=SETTINGS.input.joysticks[joystick:getName()].hats[hat][char], type="joyhat", name=joystick:getName(), hat=hat, direction=char})
            end
        end
        last_hat_direction = direction
    elseif has_hat then
        for i, direction in ipairs{"d", "l", "ld", "lu", "r", "rd", "ru", "u"} do
            SCENE:onInputRelease({input=SETTINGS.input.joysticks[joystick:getName()].hats[hat][direction], type="joyhat", name=joystick:getName(), hat=hat, direction=direction})
        end
        last_hat_direction = ""
    elseif direction ~= "c" then
        for i = 1, #direction do
            local char = direction:sub(i, i)
            local _, count = last_hat_direction:gsub(char, char)
            if count == 0 then
                SCENE:onInputPress({input=directions[char], type="joyhat", name=joystick:getName(), hat=hat, direction=char})
            end
        end
        for i = 1, #last_hat_direction do
            local char = last_hat_direction:sub(i, i)
            local _, count = direction:gsub(char, char)
            if count == 0 then
                SCENE:onInputRelease({input=directions[char], type="joyhat", name=joystick:getName(), hat=hat, direction=char})
            end
        end
        last_hat_direction = direction
    else
        for i, direction in ipairs{"d", "l", "ld", "lu", "r", "rd", "ru", "u"} do
            SCENE:onInputRelease({input=nil, type="joyhat", name=joystick:getName(), hat=hat, direction=direction})
        end
        last_hat_direction = ""
    end
end

function love.focus(f)
    return
end

local TARGET_FPS = 60

function love.run()
    if love.load then love.load(love.arg.parseGameArguments(arg), arg) end

    if love.timer then love.timer.step() end

    local dt = 0

    local last_time = love.timer.getTime()
    local time_accumulator = 0
    return function()
        if love.event then
            love.event.pump()
            for name, a,b,c,d,e,f in love.event.poll() do
                if name == "quit" then
                    if not love.quit or not love.quit() then
                        return a or 0
                    end
                end
                love.handlers[name](a,b,c,d,e,f)
            end
        end

        if SCENE and SCENE.update and love.timer then
            SCENE:update()

            local frame_duration = 1.0 / TARGET_FPS
            if time_accumulator < frame_duration then
                if love.graphics and love.graphics.isActive() and love.draw then
                    love.graphics.origin()
                    love.graphics.clear(love.graphics.getBackgroundColor())
                    love.draw()
                    love.graphics.present()
                end
                local end_time = last_time + frame_duration
                local time = love.timer.getTime()
                while time < end_time do
                    love.timer.sleep(0.001)
                    time = love.timer.getTime()
                end
                time_accumulator = time_accumulator + time - last_time
            end
            time_accumulator = time_accumulator - frame_duration
        end
        last_time = love.timer.getTime()
    end
end

local minos = {'R_d', 'O_d', 'Y_d', 'G_d', 'C_d', 'B_d', 'M_d'}
local main_bg_grid = {}
for x=1, 40 do
    main_bg_grid[x] = {}
    for y=1, 30 do
        main_bg_grid[x][y] = 0
    end
end
local main_bg_cur_pos = {20,6}
local main_bg_cur_color = minos[love.math.random(1,7)]
local main_bg_cur_mino = 1
local main_bg_draw_frame = 0
local main_bg_last_color = nil

function MainBackground()
    if SETTINGS["music"] and not SOUNDS["bgm_title"]:isPlaying() then
        SOUNDS["bgm_title"]:setVolume(0.3)
        SOUNDS["bgm_title"]:play()
    end
    local y = 40
    if main_bg_draw_frame >= 16 then
        while y > 1 do
            for x = 1, 40 do
                main_bg_grid[x][y] = main_bg_grid[x][y-1]
            end
            y = y - 1
        end
        for x=1, 40 do
            main_bg_grid[x][1] = 0
        end
        main_bg_draw_frame = 0
        main_bg_cur_pos[2] = main_bg_cur_pos[2] + 1
    end
    local directions = { {0,-1},{1,0}, {-1,0}}
    local test_dir = directions[love.math.random(1,3)]
    main_bg_cur_pos[1] = main_bg_cur_pos[1] + test_dir[1]
    main_bg_cur_pos[2] = main_bg_cur_pos[2] + test_dir[2]
    if main_bg_cur_pos[1] > 40 then main_bg_cur_pos[1] = 40 end
    if main_bg_cur_pos[1] < 1 then main_bg_cur_pos[1] = 1 end
    if main_bg_cur_pos[2] > 30 then main_bg_cur_pos[2] = 30 end
    if main_bg_cur_pos[2] < 1 then main_bg_cur_pos[2] = 1 end
    if main_bg_grid[main_bg_cur_pos[1]][main_bg_cur_pos[2]] == 0 then
        main_bg_grid[main_bg_cur_pos[1]][main_bg_cur_pos[2]] = main_bg_cur_color
        main_bg_cur_mino = main_bg_cur_mino + 1
    end
    for x=1,40 do
        for y=1,30 do
            if main_bg_grid[x][y] ~= 0 then
                love.graphics.setColor(1, 1, 1, 0.4)
                if ((x-1)*48)-560 > 0 and ((x-1)*48)-560 < 640 then love.graphics.draw(BLOCKS["2tie"][main_bg_grid[x][y]], ((x-1)*48)-570, (((y+2)*48)+main_bg_draw_frame*3)-480,0, 3) end
                love.graphics.setColor(1, 1, 1, 1)
            end
        end
    end
    for x=1,40 do
        for y=1,30 do
            if main_bg_grid[x][y] ~= 0 then
                love.graphics.setColor(1, 1, 1, 1)
                love.graphics.draw(BLOCKS["2tie"][main_bg_grid[x][y]], (x-1)*16, ((y-1)*16)+main_bg_draw_frame)
            end
        end
    end
    for x=1,40 do
        for y=1,30 do
            if main_bg_grid[x][y] ~= 0 then
                love.graphics.setColor(1, 1, 1, 0.6)
                if ((x-1)*32)-320 > 0 and ((x-1)*32)-320 < 640 then love.graphics.draw(BLOCKS["2tie"][main_bg_grid[x][y]], ((x-1)*32)-320, (((y+1)*32)+main_bg_draw_frame*2)-320,0, 2) end
                love.graphics.setColor(1, 1, 1, 1)
            end
        end
    end
    if main_bg_cur_mino == 5 then
        --if main_bg_cur_pos[2] < 4 then
        --    main_bg_cur_pos[2] = 4
        --    main_bg_cur_pos[1] = love.math.random(4, 36)
        --end
        main_bg_cur_pos = {love.math.random(16,24),6}
        main_bg_last_color = main_bg_cur_color
        while main_bg_cur_color == main_bg_last_color do main_bg_cur_color = minos[love.math.random(1,7)] end
        main_bg_cur_mino = 1
    end
    main_bg_placed = false
    main_bg_draw_frame = main_bg_draw_frame + 1
end
