local extraBGOProperties = require("extraBGOProperties")

local onlinePlay = require("scripts/onlinePlay")
local battleCamera = require("scripts/battleCamera")
local battlePlayer = require("scripts/battlePlayer")
local battleItems = require("scripts/battleItems")

-- Give "Kromer" a random worth
function battleItems.coinAmountModifierFunc(p,amount)
    return RNG.randomInt(amount,amount*6)
end


-- BGO setup

-- Ads
for _,id in ipairs{852,853,854,855} do
    extraBGOProperties.registerID(id,{
        movementFunc = function(v,t)
            local data = extraBGOProperties.getData(v)

            if lunatime.drawtick()%8 == 0 then
                data.offsetX = RNG.random(-2/32,2/32)
                data.offsetY = RNG.random(-2/32,2/32)
            end
        end,
    })
end

-- Glowy things
for _,id in ipairs{4,53,305,850} do
    extraBGOProperties.registerID(id,{
        fragShader = "resources/solidColor.frag",
        movementFunc = function(v,t)
            local data = extraBGOProperties.getData(v)

            data.offsetY = math.sin(lunatime.drawtick()/24)*0.0625
        end,
        getUniformsFunc = function(bgoID,camIdx)
            return {
                color = Color.white,
                extremity = math.abs(math.sin(lunatime.drawtick()/32))*0.125,
            }
        end,
    })
end


-- Queen's cool mixtape
local mixtapeSound = SFX.open(Misc.resolveSoundFile("cool_mixtape"))
local mixtapeSoundObj

local mixtapeConstantRadius = 192
local mixtapeFadeRadius = 800

local mixtapeMaxVolume = 0.5


-- Gets the distance between a box and a goal point.
-- If it would be faster to wrap around than it would be to move normally, it will move
-- in the opposite direction in the expectation that it will wrap.
local function getDistanceGivenSectionWrap(x,y,width,height, goalX,goalY, sectionObj)
    local bounds = sectionObj.boundary

    local dx = goalX - (x + width*0.5)
    local dy = goalY - (y + height*0.5)

    -- Horizontal wrap
    if sectionObj.wrapH then
        if dx > 0 then -- B is below A
            -- Would it be faster to go up and wrap around?
            local preWrapDistance = math.max(0,(x + width) - bounds.left)
            local postWrapDistance = math.max(0,(bounds.right + width*0.5) - goalX)
            local totalDistance = preWrapDistance + postWrapDistance

            if totalDistance < dx then
                dx = -totalDistance
            end
        elseif dx < 0 then -- B is above A
            -- Would it be faster to go down and wrap around?
            local preWrapDistance = math.max(0,bounds.right - x)
            local postWrapDistance = math.max(0,goalX - (bounds.left - width*0.5))
            local totalDistance = preWrapDistance + postWrapDistance

            if totalDistance < -dx then
                dx = totalDistance
            end
        end
    end

    -- Vertical wrap
    if sectionObj.wrapV then
        if dy > 0 then -- B is below A
            -- Would it be faster to go up and wrap around?
            local preWrapDistance = math.max(0,(y + height) - bounds.top)
            local postWrapDistance = math.max(0,(bounds.bottom + height*0.5) - goalY)
            local totalDistance = preWrapDistance + postWrapDistance

            if totalDistance < dy then
                dy = -totalDistance
            end
        elseif dy < 0 then -- B is above A
            -- Would it be faster to go down and wrap around?
            local preWrapDistance = math.max(0,bounds.bottom - y)
            local postWrapDistance = math.max(0,goalY - (bounds.top - height*0.5))
            local totalDistance = preWrapDistance + postWrapDistance

            if totalDistance < -dy then
                dy = totalDistance
            end
        end
    end

    return dx,dy
end


local activePhantoStateMap = table.map{3,4,6,7,8}

local function isActiveQueen(queenNPC)
    local data = queenNPC.data._basegame

    return (data.initialized and activePhantoStateMap[data.state])
end


local function getMixtapeVolumeForQueen(queenNPC)
    local maxVolume = 0

    for _,p in ipairs(Player.get()) do
        if (onlinePlay.currentMode == onlinePlay.MODE_OFFLINE or p.idx == battleCamera.onlineFollowedPlayerIdx) and battlePlayer.getPlayerIsActive(p) then
            local distanceX,distanceY = getDistanceGivenSectionWrap(queenNPC.x,queenNPC.y,queenNPC.width,queenNPC.height, p.x + p.width*0.5,p.y + p.height*0.5, queenNPC.sectionObj)
            local distance = math.sqrt(distanceX*distanceX + distanceY*distanceY)

            local volume = math.clamp(1 - (distance - mixtapeConstantRadius)/mixtapeFadeRadius,0,1)

            maxVolume = math.max(maxVolume,volume)
        end
    end

    return maxVolume
end


local function getMixtapeVolume()
    local queenExists = false
    local maxVolume = 0

    for _,queenNPC in NPC.iterate(958) do
        if isActiveQueen(queenNPC) then
            maxVolume = math.max(maxVolume,getMixtapeVolumeForQueen(queenNPC))
            queenExists = true
        end
    end

    return queenExists,maxVolume
end


-- takes start and makes it get closer to goal, at speed change
local function approach(start,goal,change)
    if start > goal then
        return math.max(goal,start - change)
    elseif start < goal then
        return math.min(goal,start + change)
    else
        return goal
    end
end


function onTick()
    local queenExists,mixtapeVolume = getMixtapeVolume()

    if queenExists then
        if mixtapeSoundObj == nil or not mixtapeSoundObj:isPlaying() then
            mixtapeSoundObj = SFX.play{sound = mixtapeSound,volume = mixtapeVolume*mixtapeMaxVolume,loops = 0}
        else
            mixtapeSoundObj.volume = mixtapeVolume*mixtapeMaxVolume
        end
    else
        if mixtapeSoundObj ~= nil and mixtapeSoundObj:isPlaying() then
            mixtapeSoundObj:stop()
        end
    end

    Audio.MusicVolume(approach(Audio.MusicVolume(),(1 - mixtapeVolume)*51,1))
end