local battleMenu = require("scripts/battleMenu")

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

local textplus = require("textplus")

local maskCollection,menus,hud

local shop = {}


shop.blocks = {
    {
        powerup = POWERUP_FIRE,
        blockID = 675,
        prices = {5,10,15},
        x = -179104,
        y = -179872 + 16,
    },
    {
        powerup = POWERUP_ICE,
        blockID = 679,
        prices = {8,15,20},
        x = -179104 + 48,
        y = -179872 + 16,
    },
    {
        powerup = POWERUP_LEAF,
        blockID = 676,
        prices = {5,10,15},
        x = -179104 + 48*2,
        y = -179872 + 16,
    },
    {
        powerup = POWERUP_TANOOKI,
        blockID = 677,
        prices = {10,15,25},
        x = -179104 + 48*3,
        y = -179872 + 16,
    },
    {
        powerup = POWERUP_HAMMER,
        blockID = 678,
        prices = {20,40,60},
        x = -179104 + 48*4,
        y = -179872 + 16,
    },
}

shop.upgradeBlockID = 66

shop.upgrades = {"launcher"}
shop.upgradePrices = {
    launcher = {20,40,60},
}


shop.invalidSound = Misc.resolveSoundFile("resources/menu/unselectable")


local purchasePowerupCommand = onlinePlay.createCommand("maskCollection_shop_purchasePowerup",onlinePlay.IMPORTANCE_MAJOR)
local purchaseUpgradeCommand = onlinePlay.createCommand("maskCollection_shop_purchaseUpgrade",onlinePlay.IMPORTANCE_MAJOR)
local toggleUpgradeCommand = onlinePlay.createCommand("maskCollection_shop_toggleUpgrade",onlinePlay.IMPORTANCE_MAJOR)

local shopLayer


local function getBlockDataFromID(blockID)
    for _,blockData in ipairs(shop.blocks) do
        if blockData.blockID == blockID then
            return blockData
        end
    end

    return nil
end

function shop.getPrice(prices)
    local saveFile = maskCollection.getSaveFile()
    local playerCount = 1

    if saveFile ~= nil then
        playerCount = saveFile.lastWavePlayerCount or playerCount
    end

    return prices[math.min(#prices,playerCount)]
end


local function buyUpgrade(playerIdx,upgrade)
    if shop.upgradePrices[upgrade] == nil then
        return
    end

    local playerSaveInfo = maskCollection.getPlayerSaveInfo(playerIdx)
    local price = shop.getPrice(shop.upgradePrices[upgrade])

    if playerSaveInfo == nil then
        return
    end

    if playerSaveInfo.purchasedUpgradeMap[upgrade] then
        return
    end

    playerSaveInfo.coins = math.max(0,playerSaveInfo.coins - price)
    playerSaveInfo.purchasedUpgradeMap[upgrade] = true
    playerSaveInfo.equippedUpgradeMap[upgrade] = true

    maskCollection.pushSaveFile()
end

function shop.tryPurchaseUpgrade(playerIdx,upgrade)
    local playerSaveInfo = maskCollection.getPlayerSaveInfo(playerIdx)
    local price = shop.getPrice(shop.upgradePrices[upgrade])

    if playerSaveInfo == nil or playerSaveInfo.coins < price or playerSaveInfo.purchasedUpgradeMap[upgrade] then
        return false
    end

    if onlinePlay.currentMode == onlinePlay.MODE_CLIENT then
        purchaseUpgradeCommand:send(onlinePlay.hostPlayerIdx, upgrade)
        return true
    end

    buyUpgrade(playerIdx,upgrade)

    return true
end

function shop.ownsUpgrade(playerIdx,upgrade)
    local playerSaveInfo = maskCollection.getPlayerSaveInfo(playerIdx)

    return (playerSaveInfo ~= nil and playerSaveInfo.purchasedUpgradeMap[upgrade])
end

function shop.upgradeEquipped(playerIdx,upgrade)
    local playerSaveInfo = maskCollection.getPlayerSaveInfo(playerIdx)

    return (playerSaveInfo ~= nil and playerSaveInfo.equippedUpgradeMap[upgrade])
end

function shop.toggleUpgrade(playerIdx,upgrade, isEquipped)
    if onlinePlay.currentMode == onlinePlay.MODE_CLIENT then
        toggleUpgradeCommand:send(onlinePlay.hostPlayerIdx, upgrade,isEquipped)
        return
    end

    local playerSaveInfo = maskCollection.getPlayerSaveInfo(playerIdx)

    if playerSaveInfo ~= nil then
        playerSaveInfo.equippedUpgradeMap[upgrade] = isEquipped
        maskCollection.pushSaveFile()
    end
end


local function drawPrice(x,y,coinCount)
    local layout = textplus.layout(tostring(coinCount),nil,hud.counterTextFormat)

    local counterWidth = layout.width + hud.coinCounterIconGap + hud.coinCounterIconImage.width
    local counterHeight = math.max(layout.height,hud.coinCounterIconImage.height)

    x = x - math.floor(counterWidth*0.25)*2
    y = y + math.floor(counterHeight*0.25)*2

    Graphics.drawImageToSceneWP(hud.coinCounterIconImage,x,y - hud.coinCounterIconImage.height,hud.coinCounterOpacity,1)
    x = x + hud.coinCounterIconImage.width + hud.coinCounterIconGap

    textplus.render{
        layout = layout,
        priority = 1,
        color = Color.white*hud.coinCounterOpacity,
        sceneCoords = true,
        x = x,
        y = y - layout.height + hud.coinCounterTextOffsetY,
    }
end


function shop.onStart()
    shopLayer = Layer.get("(Mask Collection) (Base) Powerups")
end

function shop.onTick()
    if shopLayer.isHidden then
        hud.coinCounterOpacity = math.max(0,hud.coinCounterOpacity - 0.1)
    else
        hud.coinCounterOpacity = math.min(1,hud.coinCounterOpacity + 0.1)
    end
end

function shop.onDraw()
    if not maskCollection.activeOnClientside or hud.coinCounterOpacity <= 0 then
        return
    end

    for blockIndex,blockData in ipairs(shop.blocks) do
        local side = (blockIndex%2)*2 - 1

        drawPrice(blockData.x,blockData.y + 26*side,shop.getPrice(blockData.prices))
    end
end


function shop.onBlockHit(eventObj,block,fromTop,playerObj)
    local blockData = getBlockDataFromID(block.id)

    if blockData == nil then
        return
    end

    if playerObj == nil or not onlinePlayPlayers.ownsPlayer(playerObj) or playerObj.forcedState ~= FORCEDSTATE_NONE or playerObj.invincibilityTimer > 0 then
        block:bump()

        eventObj.cancelled = true
        return
    end

    local playerSaveInfo = maskCollection.getPlayerSaveInfo(playerObj.idx)

    if playerObj.powerup == blockData.powerup or playerSaveInfo == nil or playerSaveInfo.coins < shop.getPrice(blockData.prices) then
        SFX.play(shop.invalidSound)

        block:bump()

        eventObj.cancelled = true
        return
    end
end

function shop.onPostBlockHit(block,fromTop,playerObj)
    if block.id == shop.upgradeBlockID then
        if playerObj == nil then
            return
        end

        local upgrade = "launcher"
        local price = shop.getPrice(shop.upgradePrices[upgrade])

        if battleMenu.currentMenu == nil then
            if onlinePlay.currentMode == onlinePlay.MODE_OFFLINE then
                menus.upgradeMenu:open({upgrade = upgrade,price = price},1,playerObj,true)
            elseif playerObj.idx == onlinePlay.playerIdx then
                menus.upgradeMenu:open({upgrade = upgrade,price = price},1,playerObj,false)
            end
        end

        playerObj.speedX = playerObj.speedX*0.25

        return
    end

    local blockData = getBlockDataFromID(block.id)

    if blockData == nil then
        return
    end

    if playerObj == nil or not onlinePlayPlayers.ownsPlayer(playerObj) then
        return
    end

    local playerSaveInfo = maskCollection.getPlayerSaveInfo(playerObj.idx)

    if playerSaveInfo == nil then
        return
    end

    playerSaveInfo.coins = math.max(0,playerSaveInfo.coins - shop.getPrice(blockData.prices))
    playerSaveInfo.powerup = blockData.powerup

    hud.coinCounterBumpTimer = 1

    if onlinePlay.currentMode == onlinePlay.MODE_CLIENT then
        purchasePowerupCommand:send(onlinePlay.hostPlayerIdx, playerSaveInfo.powerup,playerSaveInfo.coins)
    else
        maskCollection.pushSaveFile()
    end
end


function purchasePowerupCommand.onReceive(sourcePlayerIdx, powerup,newCoinCount)
    if onlinePlay.currentMode ~= onlinePlay.MODE_HOST then
        return
    end

    local playerSaveInfo = maskCollection.getPlayerSaveInfo(sourcePlayerIdx)

    if playerSaveInfo ~= nil then
        playerSaveInfo.powerup = powerup
        playerSaveInfo.coins = newCoinCount

        maskCollection.pushSaveFile()
    end
end

function purchaseUpgradeCommand.onReceive(sourcePlayerIdx, upgrade)
    if onlinePlay.currentMode ~= onlinePlay.MODE_HOST then
        return
    end

    buyUpgrade(sourcePlayerIdx, upgrade)
end

function toggleUpgradeCommand.onReceive(sourcePlayerIdx, upgrade,isEquipped)
    if onlinePlay.currentMode ~= onlinePlay.MODE_HOST then
        return
    end

    local playerSaveInfo = maskCollection.getPlayerSaveInfo(sourcePlayerIdx)

    if playerSaveInfo ~= nil then
        playerSaveInfo.equippedUpgradeMap[upgrade] = isEquipped
        maskCollection.pushSaveFile()
    end
end


function shop.onInitAPI()
    registerEvent(shop,"onStart")
    registerEvent(shop,"onTick")
    registerEvent(shop,"onDraw")
    registerEvent(shop,"onBlockHit")
    registerEvent(shop,"onPostBlockHit")

    maskCollection = require("maskCollection/scripts/maskCollection")
    menus = require("maskCollection/scripts/menus")
    hud = require("maskCollection/scripts/hud")


    function maskCollection.onSaveFilePush()
        if maskCollection.gameState == maskCollection.GAME_STATE.WAITING_ROOM then
            if maskCollection.getSaveFile() ~= nil then
                shopLayer:show(true)
            else
                shopLayer:hide(true)
            end
        end
    end
end


return shop