
-- original by xavier
-- editing abilities added by UberGoober
-- maze with achievable goal added by UberGoober

-- Use this function to perform your initial setup
displayMode(OVERLAY)

function setup()
    
    stick = Stick()
    
    empty = Floor()
    unerasable = Wall("Cargo Bot:Crate Yellow 2")
    pylon = Wall("Cargo Bot:Crate Red 2")
    wall = Wall("Cargo Bot:Crate Yellow 2")
    floor = Floor("Cargo Bot:Crate Green 2")
    secretDoor = Wall("Cargo Bot:Crate Yellow 2")
    secretFloor = Floor("Cargo Bot:Crate Green 2")
    goal = Floor("Project:Goal")
    local goalImage = makeGoalImage()
    goal.model.texture = goalImage
    
    world = World()
    hero = Hero(4,17)
    
    gameWon = false
    winBanner = YouWinBanner()

    TO_DEG = 180/math.pi
    
    eraseMode = false
    eraseModeToggle = function ()
        if eraseMode == false then
            eraseMode = true
            world.editMode = true
            print("erase mode ON")
            return
        end
        eraseMode = false
        print("erase mode OFF")
    end
    writeMap = function()
        local dataAsString = getString(world.activeData,"saveData")
        saveProjectTab("WorldData", "savedMap = "..dataAsString)
        print("map saved")
    end
    parameter.watch("Instructions")
    Instructions = "Enjoy this simple map puzzle. Find the star to win! There might be a secret tunnel somewhere..."
    parameter.watch("Editor")
    Editor = "You can use the buttons below to create your own mazes. Saving and loading doesn't really work correctly unless you exit to the editor after saving, and sometimes even that is weird. Sorry! Good luck!"
    parameter.watch("Clearing")
    Clearing = "Clear the map and make your own! Create paths just by rolling. Empty spaces will be filled with walls after you save it, exit to the editor, start again and enter test mode."
    parameter.action("clear map", function ()
        world.activeData = world.clearMap
        world.editMode = true
    end)
    parameter.watch("Erasing")
    Erasing = "Erase paths wherever you roll."
    parameter.action("turn erase on/off", function () eraseModeToggle() end)
    parameter.watch("Saving")
    Saving = "Write the current map to the WorldData tab. You can't load it again until you quit and restart and I don't know why."
    parameter.action("save map", function () writeMap() end)
    parameter.watch("Loading")
    Loading = "Load the currently saved map map for editing. For some reason won't load a map saved in the current gameplay session, you have to quit and restart first."
    parameter.action("load map", function () 
        world.activeData = savedMap
        world.editMode = true
    end)
    parameter.watch("Testing")
    Testing = "Play your saved map. With walls!"
    parameter.action("test", function ()
        world.activeData = savedMap
        world.editMode = false
    end)
    parameter.watch("Resetting")
    Resetting = "Reset the world to the default game map."
    parameter.action("reset map", function () restart() end)


end

function makeGoalImage()
    local goalImage = readImage("Cargo Bot:Crate Green 1")
    setContext(goalImage)
    tint(21, 21, 21, 255)
    sprite("SpaceCute:Star", goalImage.width/2,(goalImage.height/2)-2,goalImage.width, goalImage.height)
    noTint()
    sprite("SpaceCute:Star", goalImage.width/2,goalImage.height/2,goalImage.width, goalImage.height)
    setContext()
    return goalImage
end

-- This function gets called once every frame
function draw()
    background(0)
    local TO_DEG = TO_DEG
    local hero = hero

    perspective(60)
    camera(hero.x, 3, 1 + hero.z, hero.x, 0, hero.z, 0, 1, 0)

-- Draw world
    pushMatrix()
    world:draw() 
    popMatrix()

-- Draw hero
    translate(hero.x, hero.y, hero.z)
    rotate(stick.direction*TO_DEG, 0, 1, 0)

-- roll animation
    if stick.active then
        rotate(-ElapsedTime*10*TO_DEG, 0, 0, 1)
    end

    scale(.25, .25, .25)
    hero:draw()

-- Restore orthographic projection
    ortho()
    viewMatrix(matrix())
    resetMatrix()

-- corner fade overlay
    sprite("Cargo Bot:Background Fade", WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)
    if gameWon then
        winBanner:draw()
    end

    if stick.active then
        local ceil = math.ceil
        stick:draw()

        -- move hero based on stick direction
        local mvtx = math.cos(stick.direction)/50*stick.dist
        local mvtz = -math.sin(stick.direction)/50*stick.dist
        hero.x = hero.x + mvtx
        hero.z = hero.z + mvtz

        -- convert to table coordinates
        hero.px = ceil(hero.x - .5)
        hero.py = ceil(hero.z - .5)

        -- lazy collision check
        if eraseMode and world.activeData[hero.py][hero.px] ~= 5 then 
            world.activeData[hero.py][hero.px] = -1 --in erase mode erase anything but unerasable tiles
        elseif world.activeData[hero.py][hero.px] == 3 then
            world.activeData = world.data2 --touching a secret wall switches maps
        elseif world.activeData[hero.py][hero.px] == 4 then
            world.activeData = world.data --touching a secret floor tile switches maps back
        elseif world.editMode and world.activeData[hero.py][hero.px] == -1 then
            world.activeData[hero.py][hero.px] = 0 --in edit mode draw floor under player
        elseif world.activeData[hero.py][hero.px] == 6 then
            gameWon = true --touching goal tile wins game
        elseif world.activeData[hero.py][hero.px] ~= 0 then --otherwise, collision (prevents motion)
            hero.x = hero.x - mvtx 
            hero.z = hero.z - mvtz
            hero.px = ceil(hero.x - .5)
            hero.py = ceil(hero.z - .5)
        end
    end
end

function touched(touch)
        stick:touched(touch)
end

function offsetFromCenter(touch)
    local centerX, centerY = WIDTH/2,HEIGHT/2
    return touch.x - centerX, touch.y - centerY
end

function worldCoordinatesAt(touch)
    local offsetX, offsetY = offsetFromCenter(touch)
    local totalSquaresHigh, squaresAbove, squaresBelow = 5, 2.5, 1.5
    local approxTileScreenHeight = HEIGHT/totalSquaresHigh
    local screenHeightAboveAndBelowCenterTile = (HEIGHT - approxTileScreenHeight)/2
    local upperTileApproxScreenHeight = screenHeightAboveAndBelowCenterTile / squaresAbove
    local lowerTileApproxScreenHeight = screenHeightAboveAndBelowCenterTile / squaresBelow
    local totalSquaresWide, squaresLeftOrRight = 6, 2.5
    local approxTileScreenWidth = WIDTH/totalSquaresWide
    local verticalTileOffset, horizontalTileOffset
    if offsetX < 0 then
    end
end


