local game = {}
--[[
    TODO: DIALOGUE ABOUT HOW MUCH YOU LOVE ANTS ON YOUR DICK
    TODO: CUM CUM CUM CUM CUM CU  "UCM CUMC UCMCUCUMCUCMASODHFAOHFWA
]]
local IMG_PATH = "games/i-love-the-feeling-of-ants-on-my-dick/imgs/"
local _loadImage = loadImage
local function loadImage(file)
    return _loadImage(IMG_PATH .. file)
end

local function loadMap(fileName)
    -- load up map under the file name
    local map = {}
    for line in love.filesystem.lines("games/i-love-the-feeling-of-ants-on-my-dick/maps/" .. fileName) do
        local row = {}
        for char in line:gmatch("%S") do
            table.insert(row, char)
        end
        table.insert(map, row)
    end
    return map
end

local function loadMaps()
    local maps = {}
    local fileNames = love.filesystem.getDirectoryItems("games/i-love-the-feeling-of-ants-on-my-dick/maps")
    for _, fileName in ipairs(fileNames) do
        table.insert(maps, loadMap(fileName))
    end
    return maps
end

function game:readMap(x, y)
    return self.maps[1 + self.mapX + self.mapY * 3][1 + y][1 + x]
end

function game:clearSpot(x, y)
    self.maps[1 + self.mapX + self.mapY * 3][1 + y][1 + x] = "."
end

function game:setup()
    size(512, 448) 
    self.maps = loadMaps()
    self.tiles = {}
    self.tiles.b = loadImage("bush.png")
    self.tiles.g = loadImage("grass.png")
    self.tiles.G = loadImage("grass2.png")
    self.tiles.f = loadImage("grass3.png")
    self.tiles.F = loadImage("grass4.png")
    self.tiles.h = loadImage("anthill-0001.png")
    self.anthillTimer = 0
    self.anthillFrame = 0
    self.sprites = 
        { anthill = 
            { loadImage("anthill-0001.png")
            , loadImage("anthill-0002.png")
            }
        , player = 
            { loadImage("you-0001.png")
            , loadImage("you-0002.png")
            }
        , antA = 
            { loadImage("ant1-0001.png")
            , loadImage("ant1-0002.png")
            }
        , antB =
            { loadImage("ant2-0001.png")
            , loadImage("ant2-0002.png")
            }
        , dick =
            { loadImage("dick-0001.png")
            , loadImage("dick-0002.png")
            }
        , bigAnthill =
            { loadImage("anthill-large-0001.png")
            , loadImage("anthill-large-0002.png")
            }
        , bigAnthillHole = 
            { loadImage("anthill-large-back-0001.png")
            , loadImage("anthill-large-back-0002.png")
            }
        , cumshot = 
            { loadImage("cumshotA-0001.png")
            , loadImage("cumshotA-0002.png")
            , loadImage("cumshotA-0003.png")
            , loadImage("cumshotA-0004.png")
            , loadImage("cumshotA-0005.png")
            , loadImage("cumshotA-0006.png")
            , loadImage("cumshotB-0001.png")
            , loadImage("cumshotB-0002.png")
            , loadImage("cumshotB-0003.png")
            , loadImage("cumshotB-0004.png")
            , loadImage("cumshotB-0005.png")
            , loadImage("cumshotB-0006.png")
            }
        }
    self.mapX = 0
    self.mapY = 0
    self.playerX = 4
    self.playerY = 4
    self.playerFrame = 0
    self.playerTimer = 0
    self.playerMoving = false
    self.playerMoveTimer = 0
    self.dickX = width / 2 - 29 -- half of the image width
    self.dickY = 0
    self.dickTimer = 0
    self.dickFrame = 0
    self.cumTimer = 0
    self.cumFrame = 0
    self.bigAnthillTimer = 0
    self.bigAnthillFrame = 0
    self.gameState = "playing"
    self.hillFucked = false
    self.antTimer = 0
    self.antFrame = 0
    self.antHillsLeft = 9
    self.cumCountdown = 2
    self.ants = {}
    self.antTypes = {"antA", "antB"}
    self.sfx = {}
    self.sfx.step = love.audio.newSource("sfx/grassy-footstep.wav", "static")
    self.sfx.cum = love.audio.newSource("sfx/guy-jerk.wav", "static")
    self.moans = {}
    self.activeMoans = {}
    self.antDialogues = {}
    self.currentDialogue = 1
    for line in love.filesystem.lines("games/i-love-the-feeling-of-ants-on-my-dick/moans.txt") do
        table.insert(self.moans, line)
    end 
    for line in love.filesystem.lines("games/i-love-the-feeling-of-ants-on-my-dick/ant-dialogues.txt") do
        table.insert(self.antDialogues, line)
    end
end

function game:spawnAnt()
    table.insert(self.ants,
        { type = random(self.antTypes), x = love.math.random(0, 59), y = love.math.random(0, 130) }
    )
end

function game:drawAnts()
    self.antTimer = self.antTimer + deltaTime / 1000
    if self.antTimer > 1 / 12 then
        self.antTimer = 0
        self.antFrame = (self.antFrame + 1) % 2
    end
    imageMode(CENTER)
    for _, ant in ipairs(self.ants) do
        image(self.sprites[ant.type][1 + self.antFrame], self.dickX + ant.x, self.dickY + ant.y)
    end
    imageMode(CORNER)
end

function game:drawAntsInverted()
    self.antTimer = self.antTimer + deltaTime / 1000
    if self.antTimer > 1 / 12 then
        self.antTimer = 0
        self.antFrame = (self.antFrame + 1) % 2
    end
    imageMode(CENTER)
    for _, ant in ipairs(self.ants) do
        image(self.sprites[ant.type][1 + self.antFrame], self.dickX + ant.x, height + ant.y - 159 + 20)
    end
    imageMode(CORNER)
end

function game:startFuckingAnts()
    self.dickX = width / 2 - 29 -- half of the image width
    self.dickY = 0
    self.dickTimer = 0
    self.dickFrame = 0
    self.bigAnthillTimer = 0
    self.bigAnthillFrame = 0
    self.hillFucked = false
    self.gameState = "fucking ants"
end

function game:playerAnimation()
    return self.sprites.player
end

function game:playerCurrentFrame()
    return self:playerAnimation()[1 + self.playerFrame]
end

function game:playerFrameCount()
    return #self:playerAnimation()
end

function game:playerAnimate()
    self.playerTimer = self.playerTimer + deltaTime / 1000
    if self.playerTimer > 1 / 12 then
        self.playerTimer = 0
        self.playerFrame = self.playerFrame + 1
    end
    self.playerFrame = self.playerFrame % self:playerFrameCount()
end

function game:playerDraw()
    self:playerAnimate()
    image(self:playerCurrentFrame(), (self.playerX) * 64, (self.playerY) * 64)
end

function game:applyMoveDelay()
    if self.playerMoving and (keyIsDown "up" or keyIsDown "down" or keyIsDown "right" or keyIsDown "left") then 
        self.playerMoveTimer = self.playerMoveTimer + deltaTime / 1000
    else
        self.playerMoving = false
        self.playerMoveTimer = math.huge
    end
end

function game:canMove()
    return self.playerMoveTimer > 1/6 and (keyIsDown "up" or keyIsDown "down" or keyIsDown "right" or keyIsDown "left")
end

function game:tryVertical()
    if keyIsDown "up" then
        self.playerY = (self.playerY + 6) % 7
        if self.playerY == 6 then
            self.mapY = (self.mapY + 2) % 3
        end
    elseif keyIsDown "down" then
        self.playerY = (self.playerY + 1) % 7
        if self.playerY == 0 then
            self.mapY = (self.mapY + 1) % 3
        end
    end 
end

function game:tryHorizontal()
    if keyIsDown "right" then
        self.playerX = (self.playerX + 1) % 8
        if self.playerX == 0 then
            self.mapX = (self.mapX + 1) % 3
        end
    elseif keyIsDown "left" then
        self.playerX = (self.playerX + 7) % 8
        if self.playerX == 7 then
            self.mapX = (self.mapX + 2) % 3
        end
    end
end

function game:move()
    self:applyMoveDelay()
    if self:canMove() then
        local sfx = self.sfx.step:clone()
        sfx:setPitch(random(0.9, 1.1))
        sfx:play()
        self.playerMoving = true
        self.playerMoveTimer = 0
        self:tryVertical()
        self:tryHorizontal()
        local tile = self:readMap(self.playerX, self.playerY)
        if tile == "h" then
            self:clearSpot(self.playerX, self.playerY)
            self:startFuckingAnts()
            self.antHillsLeft = self.antHillsLeft - 1
        end
    end
end

function game:drawCurrentMap()
    for y, row in ipairs(self.maps[1 + self.mapX + self.mapY * 3]) do
        for x, char in ipairs(row) do
            if char ~= "." and char ~= "h" then
                image(self.tiles[char], (x - 1) * 64, (y - 1) * 64)
            elseif char == "h" then
                self.anthillTimer = self.anthillTimer + deltaTime / 1000
                if self.anthillTimer > 1 / 12 then
                    self.anthillTimer = 0
                    self.anthillFrame = (self.anthillFrame + 1) % 2
                end
                image(self.sprites.anthill[1 + self.anthillFrame], (x - 1) * 64, (y - 1) * 64)
            end
        end
    end
end

function game:drawBigAnthillHole()
    self.bigAnthillTimer = self.bigAnthillTimer + deltaTime / 1000
    if self.bigAnthillTimer > 1 / 12 then
        self.bigAnthillTimer = 0
        self.bigAnthillFrame = (self.bigAnthillFrame + 1) % 2
    end
    image(self.sprites.bigAnthillHole[1 + self.bigAnthillFrame], 172, height - 90)
end

function game:drawDick()
    self.dickTimer = self.dickTimer + deltaTime / 1000
    if self.dickTimer > 1 / 12 then
        self.dickTimer = 0
        self.dickFrame = (self.dickFrame + 1) % 2
    end
    if keyIsDown("down") then
        self.dickY = self.dickY + (deltaTime / 1000) * 200
        self.dickY = math.min(height - 80, self.dickY)
    elseif keyIsDown("up") then
        self.dickY = self.dickY - (deltaTime / 1000) * 200
        self.dickY = math.max(0, self.dickY)
    end
    image(self.sprites.dick[1 + self.dickFrame], self.dickX, self.dickY)
end

function game:drawBigAnthill()
    image(self.sprites.bigAnthill[1 + self.bigAnthillFrame], 172, height - 90)
end

function game:isHillFucked()
    if self.dickY == (height - 80) and not self.hillFucked then
        self.hillFucked = true
        for i = 1, 5 do
            self:spawnAnt()
        end
    end
end

function game:isHillDoneFucked()
    if self.dickY == 0 and self.hillFucked then
        self.hillFucked = false
        self.currentDialogue = self.currentDialogue + 2
        if self.antHillsLeft == 0 then
            self.gameState = "about to cum"
        else
            self.gameState = "playing"
        end
    end
end

function game:drawHillFuckingDialogue()
    local dialogueA, dialogueB = self.antDialogues[self.currentDialogue], self.antDialogues[self.currentDialogue + 1]
    local widestLineA, wrappingA = L5_env.currentFont:getWrap(dialogueA, 125)
    local widestLineB, wrappingB = L5_env.currentFont:getWrap(dialogueB, 125)
    local heightA = #wrappingA * textHeight()
    local heightB = #wrappingB * textHeight()
    local halfHeightA = math.floor(heightA / 2)
    local halfHeightB = math.floor(heightB / 2)
    rectMode(CENTER)
    fill(0)
    rect(128, 224, widestLineA + 20, heightA + 20)
    fill(255)
    love.graphics.printf(dialogueA, 128 - math.floor(widestLineA / 2), 224 - halfHeightA, 125)
    fill(255, 0, 0)
    if self.hillFucked then
        fill(0)
        rect(384, 224, widestLineB + 20, heightB + 20)
        fill(255)
        love.graphics.printf(dialogueB, 384  - math.floor(widestLineB / 2), 224 - halfHeightB, 125)
    end
    rectMode(CORNER)
end

function game:drawDickForCumming()
    self.dickTimer = self.dickTimer + deltaTime / 1000
    if self.dickTimer > 1 / 12 then
        self.dickTimer = 0
        self.dickFrame = (self.dickFrame + 1) % 2
    end
    local sprite = self.sprites.dick[1 + self.dickFrame]
    image(sprite, self.dickX, height, sprite:getWidth(), -sprite:getHeight())
end

function game:spawnMessage()
    local moan = random(self.moans)
    table.insert(self.activeMoans,
        { text = moan
        , x = love.math.random(20, 512 - 20 - textWidth(moan))
        , y = love.math.random(20, height - 40 - textHeight())
        }
    )
    if #self.activeMoans > 10 then
        table.remove(self.activeMoans, 1)
    end
end

function game:drawMessages()
    for _, message in ipairs(self.activeMoans) do
        fill(0)
        rect(message.x - 10, message.y - 10, textWidth(message.text) + 20, textHeight() + 10)
        fill(255)
        text(message.text, message.x, message.y + 10)
    end
end

function game:drawCumShot()
    self.cumTimer = self.cumTimer + deltaTime / 1000
    if self.cumTimer > 1 / 12 then
        self.cumTimer = 0
        self.cumFrame = (self.cumFrame + 1) % #self.sprites.cumshot
    end
    if (self.cumFrame == 2 or self.cumFrame == 8) and self.cumTimer == 0 then
        local cumSound = self.sfx.cum:clone()
        cumSound:setPitch(random(0.8, 1.2))
        cumSound:play()
        self:spawnMessage()
    end
    image(self.sprites.cumshot[1 + self.cumFrame], width / 2 - 32, height - 159 - 192)
end

function game:draw()
    background(255)
    if self.gameState == "playing" then 
        self:move()
        self:drawCurrentMap()
        self:playerDraw()
    elseif self.gameState == "fucking ants" then
        self:drawBigAnthillHole()
        self:drawDick()
        self:drawAnts()
        self:drawBigAnthill()
        self:drawHillFuckingDialogue()
        self:isHillFucked()
        self:isHillDoneFucked()
    elseif self.gameState == "about to cum" then
        fill(0)
        rect(math.floor(width / 2 - textWidth("OH FUCK, I'M ABOUT TO CUM") / 2 - 10), 148, textWidth("OH FUCK, I'M ABOUT TO CUM") + 20, textHeight() + 20)
        fill(255)
        textAlign(LEFT, TOP)
        text("OH FUCK, I'M ABOUT TO CUM", math.floor(width / 2 - textWidth("OH FUCK, I'M ABOUT TO CUM") / 2), 158)
        textAlign(LEFT, BOTTOM)
        self:drawDickForCumming()
        self:drawAntsInverted()
        self.cumCountdown = self.cumCountdown - deltaTime / 1000
        if self.cumCountdown < 0 then
            self.gameState = "cumming"
        end
    elseif self.gameState == "cumming" then
        self:drawMessages()
        self:drawDickForCumming()
        self:drawCumShot()
        self:drawAntsInverted()
    end 
end

function game:keyPressed()
end 

return {
      name = "I LOVE THE FEEL OF ANTS ON MY DICK"
    , themes = {"Insectophilia", "Infestation", "Fucking Hills of Dirt"}
    , about = "ANT ON MY DICK. ANTS ON MY DICK. ANTS ON MY DICK. ANTS ON MY DICK. ANTS ON MY DICK. ANTS ON MY DICK."
    , game = game
    , id = 2
}
