local battlePlayer = require("scripts/battlePlayer")
local battlePhanto = require("scripts/battlePhanto")

local onlinePlay = require("scripts/onlinePlay")
local onlinePlayNPC = require("scripts/onlinePlay_npc")
local onlinePlayPlayers = require("scripts/onlinePlay_players")

local easing = require("ext/easing")
local spline = require("spline")

local maskCollection,waveManager,hud

local phantoCollection = {}


phantoCollection.pointSound = Misc.resolveSoundFile("resources/point")


phantoCollection.effects = {}


local collectFromPlayerCommand = onlinePlay.createCommand("maskCollection_collectPlayer",onlinePlay.IMPORTANCE_MAJOR)
local collectFromNPCCommand = onlinePlay.createCommand("maskCollection_collectNPC",onlinePlay.IMPORTANCE_MAJOR)


local function createEffect(collectPosition,collectDirection,npcID,x,y)
    table.insert(phantoCollection.effects,{
        npcID = npcID,

        splineSegment = spline.segment{
            startTan = vector.zero2,
            stopTan = collectDirection*100,
            start = vector(x,y),
            stop = collectPosition,
        },

        collectDirection = collectDirection,

        moveTimer = 0,
        speedY = 0,
        x = x,
        y = y,
    })
end

local function collectInternal(p)
    if onlinePlayPlayers.ownsPlayer(p) then
        SFX.play(phantoCollection.pointSound)
        battlePlayer.addPointEffect(p,1,hud.phantoCounterIconImage)

        maskCollection.progressGuide(maskCollection.GUIDE_STATE.PIPE,maskCollection.GUIDE_STATE.INACTIVE)
    end

    -- Increment the number of Phantos collected
    waveManager.collectedMasks = waveManager.collectedMasks + 1
    hud.phantoCounterBumpTimer = 1
    hud.updatePhantoCounterLayout()

    -- Increment the player's mask stat
    local playerSaveInfo = maskCollection.getPlayerSaveInfo(p.idx)

    if playerSaveInfo ~= nil then
        playerSaveInfo.collectedMaskCount = playerSaveInfo.collectedMaskCount + 1
    end
end


local function collectFromPlayerInternal(p,collectPosition,collectDirection)
    if battlePhanto.isWearingMask(p) then
        local maskX,maskY,_,_,_ = battlePhanto.getMaskPosition(p)
        local maskData = battlePhanto.getMaskData(p)

        createEffect(collectPosition,collectDirection,maskData.wornNPCID,maskX,maskY)

        battlePhanto.removeMaskInternal(p)
    end

    collectInternal(p)
end

--[[local function collectFromNPCInternal(npc,playerIdx,collectPosition,collectDirection)
    local p = Player(playerIdx)

    createEffect(collectPosition,collectDirection,maskData.wornNPCID,maskX,maskY)
    collectInternal(p)
end]]


function phantoCollection.collectFromPlayer(p,collectPosition,collectDirection)
    if maskCollection.gameState ~= maskCollection.GAME_STATE.WAVE or not battlePhanto.isWearingMask(p) then
        return
    end

    if onlinePlay.currentMode ~= onlinePlay.MODE_OFFLINE then
        collectFromPlayerCommand:send(0, collectPosition,collectDirection)
    end

    collectFromPlayerInternal(p,collectPosition,collectDirection)
end

function phantoCollection.collectFromNPC(npc,playerIdx,collectPosition,collectDirection)
    if maskCollection.gameState ~= maskCollection.GAME_STATE.WAVE then
        return
    end

    local x = npc.x + npc.width*0.5
    local y = npc.y + npc.height*0.5

    if onlinePlay.currentMode ~= onlinePlay.MODE_OFFLINE then
        collectFromNPCCommand:send(0, collectPosition,collectDirection, onlinePlayNPC.getUIDFromNPC(npc),npc.id,x,y)
    end

    createEffect(collectPosition,collectDirection,npc.id,x,y)
    collectInternal(Player(playerIdx))

    onlinePlayNPC.forceKillNPC(npc,HARM_TYPE_VANISH)
end


function phantoCollection.onTick()
    local i = 1

    while (phantoCollection.effects[i] ~= nil) do
        local effect = phantoCollection.effects[i]

        if effect.moveTimer < 1 then
            effect.moveTimer = math.min(1,effect.moveTimer + 1/48)

            local point = effect.splineSegment:evaluate(easing.inQuad(effect.moveTimer,0,1,1))

            effect.speedY = point.y - effect.y
            effect.x = point.x
            effect.y = point.y

            i = i + 1
        else
            local bounds = Section(maskCollection.section).origBoundary

            effect.speedY = effect.speedY + effect.collectDirection.y*0.1
            effect.y = effect.y + effect.speedY

            if effect.y < (bounds.top - 32) or effect.y > (bounds.bottom + 32) then
                table.remove(phantoCollection.effects,i)
            else
                i = i + 1
            end
        end
    end
end

function phantoCollection.onDraw()
    for _,effect in ipairs(phantoCollection.effects) do
        local npcConfig = NPC.config[effect.npcID]

        local image = npcConfig.wornImage
        local width = image.width
        local height = image.height/battlePhanto.maskRotationalFrames

        Graphics.drawBox{
            texture = image,priority = -66,
            centred = true,sceneCoords = true,

            x = effect.x,
            y = effect.y,
            sourceWidth = width,
            sourceHeight = height,
        }
    end
end


function collectFromPlayerCommand.onReceive(sourcePlayerIdx, collectPosition,collectDirection)
    collectFromPlayerInternal(Player(sourcePlayerIdx),collectPosition,collectDirection)
end

function collectFromNPCCommand.onReceive(sourcePlayerIdx, collectPosition,collectDirection, npcUID,npcID,x,y)
    local npc = onlinePlayNPC.getNPCFromUID(npcUID)

    if npc ~= nil then
        x = npc.x + npc.width*0.5
        y = npc.y + npc.height*0.5
        onlinePlayNPC.forceKillNPC(npc,HARM_TYPE_VANISH)
    end

    createEffect(collectPosition,collectDirection,npcID,x,y)
    collectInternal(Player(sourcePlayerIdx))
end


function phantoCollection.onInitAPI()
    registerEvent(phantoCollection,"onTick")
    registerEvent(phantoCollection,"onDraw")

    maskCollection = require("maskCollection/scripts/maskCollection")
    waveManager = require("maskCollection/scripts/waveManager")
    hud = require("maskCollection/scripts/hud")
end


return phantoCollection