local TABAS_ContextMenuShower = {}

local TABAS_Utils = require("TABAS_Utils")
local TABAS_Common = require("TABAS_ContextMenuCommon")
local WaterReader = require("TABAS_WaterReader")

local COLOR_RED = "<RGB:1,0.5,0.5>"
-- local COLOR_YELLOW = " <RGB:1,1,0.5> "

function TABAS_ContextMenuShower.ShowerContextCreateMenu(player, context, worldObjects, test)
    local showerSprites = TABAS_Utils.getShowerSprites()
    local showerObj = TABAS_Utils.getObjectFromWorldObjects(worldObjects, showerSprites)
    if showerObj == nil then return end

    local displayName = ISWorldObjectContextMenu.getMoveableDisplayName(showerObj)

    -- Remove vanilla menu. They will be added back later.
    if context:getOptionFromName(displayName) then
        context:removeOptionByName(displayName)
    end

    local mainMenu = context:addOptionOnTop(displayName)
    local subMenu = ISContextMenu:getNew(context)
    context:addSubMenu(mainMenu, subMenu)

    TABAS_ContextMenuShower.doShowerMenu(player, showerObj, subMenu)
    TABAS_Common.setTemperatureMenu(player, showerObj, subMenu)
    TABAS_Common.vanillaFluidMenu(player, worldObjects, test, showerObj, subMenu)

    TABAS_Common.doDebugMenu(player, showerObj, subMenu)
    if showerObj:getModData().using then
        local unUsing = function(object)
            object:getModData().using = nil
        end
        subMenu:addOption("Unlock [Using]", showerObj, unUsing)
    end
end


function TABAS_ContextMenuShower.doShowerMenu(player, object, context)
    local playerObj = getSpecificPlayer(player)

    local temperatureConcept = SandboxVars.TakeABathAndShower.WaterTemperatureConcept
    local waterRequired = SandboxVars.TakeABathAndShower.ShowerConsumeWater

    local soapList = {}
    local soapRemaining = 0
    local soapRequired = TABAS_Utils.getRequiredSoap(playerObj)
    if soapRequired > 1 then
        soapList = TABAS_Utils.getSoapList(playerObj, object)
        soapRemaining = TABAS_Utils.getSoapRemaining(soapList)
    end
    local waterAmount = WaterReader.getWaterAmount(object)
    local waterCapacity = WaterReader.getWaterCapacity(object)
    local waterSourceCount = WaterReader.getExternalContainerCount(object)

    local canHot = TABAS_Utils.canHot(object)
    local temperature = 22.0
    if canHot then
        temperature = object:getModData().idealTemperature or 40.0
    end

    local notPiped = waterSourceCount == 0 and object:getModData().canBeWaterPiped
    local using = object:getModData().using
    local requireTowel = TABAS_Utils.ModOptionsValue("AfterBathingDrySelf")
    local towel = nil
    if requireTowel then
        towel = TABAS_Utils.getAvailableTowel(playerObj)
    end
    local asIsWearing = not TABAS_Utils.ModOptionsValue("AutoClothesChange")

    local bodyBlood, bodyDirt = TABAS_Utils.getBodyBloodAndDirt(playerObj)
    local bodyGrime = TABAS_Utils.getBodyGrime(playerObj)
    
    local subOptionTooltip = function(optionName, usesHot)
        local option = context:addGetUpOption(optionName, player, TABAS_ContextMenuShower.onTakeShower, object, soapList, soapRequired, towel, asIsWearing, usesHot)
        local icon = "media/ui/Icons/tabas_shower"
        if temperatureConcept then
            if usesHot and temperature >= 38 then
                icon = icon .. "_hot.png"
            else
                icon = icon .. "_cold.png"
            end
        else
            icon = icon .. ".png"
        end
        option.iconTexture = getTexture(icon)

        local tooltip = ISWorldObjectContextMenu.addToolTip()
        if notPiped or using or temperature > 45 then
            option.notAvailable = true
            if notPiped then
                tooltip.description = TABAS_Common.notPipedTooltipText
            elseif using then
                tooltip.description = COLOR_RED .. getText("ContextMenu_TABAS_CurrentlyUsing")
            elseif temperature > 45 then
                tooltip.description = COLOR_RED .. getText("ContextMenu_TABAS_TooHot")
            end
        else
            local width = 0
            local font = UIFont[getCore():getOptionTooltipFont()] or UIFont.Small
            width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_WaterName") .. ":") + 20)
            width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_TABAS_RequiredWater") .. ":") + 20)
            width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_TABAS_SoapRemain") .. ":") + 20)
            width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_TABAS_SoapRequired") .. ":") + 20)
            width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_TABAS_UseTowel") .. ":") + 20)

            tooltip.defaultMyWidth = width

            local col = waterAmount < waterRequired and {1, 1, 0.5}
            tooltip.description = tooltip.description .. TABAS_Common.formatWaterAmount(getText("ContextMenu_WaterName"), width, waterAmount, waterCapacity, col)
            if waterSourceCount > 0 then
                tooltip.description = tooltip.description .. " / " .. tostring(waterSourceCount)
            end
            tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndValue(getText("ContextMenu_TABAS_RequiredWater"), width, waterRequired .. "L")
            if temperatureConcept then
                tooltip.description = tooltip.description .. " <LINE> " ..  TABAS_Common.formatLabelAndValue(getText("ContextMenu_TABAS_SetTemperature"), width, TABAS_Utils.formatedCelsiusOrFahrenheit(temperature))
            end
            if bodyBlood > 0 then
                -- tooltip.description = tooltip.description .. " <LINE> " .. getText("Tooltip_clothing_bloody") .. ": " .. math.ceil(bodyBlood / BloodBodyPartType.MAX:index() * 100) .. " / 100"
                tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndInteger(getText("Tooltip_clothing_bloody"), width, bodyBlood, 100)
            end
            if bodyDirt > 0 then
                tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndInteger(getText("Tooltip_clothing_dirty"), width, bodyDirt, 100)
            end
            if bodyGrime > 0 then
                tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndInteger(getText("ContextMenu_TABAS_BodyGrime"), width, bodyGrime, 100)
            end
            if soapRequired > 1 then
                tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndInteger(getText("ContextMenu_TABAS_SoapRemain"), width, soapRemaining)
                tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndInteger(getText("ContextMenu_TABAS_SoapRequired"), width, soapRequired)
                local availableSoap = (soapRequired <= soapRemaining)
                tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndBoolean(getText("ContextMenu_TABAS_UseSoap"), width, availableSoap)
            else
                tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndValue(getText("ContextMenu_TABAS_UseSoap"), width, getText("ContextMenu_TABAS_SoapNoNeed"))
            end
            if requireTowel then
                local canDry = towel ~= nil
                tooltip.description = tooltip.description .. " <LINE> " .. TABAS_Common.formatLabelAndBoolean(getText("ContextMenu_TABAS_UseTowel"), width, canDry)
            end
            if waterAmount < waterRequired * 0.25 then
                option.notAvailable = true
                tooltip.description = tooltip.description .. " <BR> " .. COLOR_RED .. getText("ContextMenu_TABAS_NotEnoughWater")
            elseif usesHot and not canHot then
                option.notAvailable = true
                tooltip.description = tooltip.description .. " <BR> " .. COLOR_RED .. getText("ContextMenu_TABAS_ElectricityRequired")
            end
        end
        option.toolTip = tooltip
    end

    if temperatureConcept then
        if TABAS_Utils.ModOptionsValue("DisplaysAvailableShower") then
            if canHot and temperature >= 35 then
                subOptionTooltip(getText("ContextMenu_TABAS_TakeShowerHot"), true)
            else
                subOptionTooltip(getText("ContextMenu_TABAS_TakeShowerCold"), false)
            end
        else
            subOptionTooltip(getText("ContextMenu_TABAS_TakeShowerHot"), true)
            subOptionTooltip(getText("ContextMenu_TABAS_TakeShowerCold"), false)
        end
    else
        subOptionTooltip(getText("ContextMenu_TABAS_TakeShowerHot"), true)
    end
end

function TABAS_ContextMenuShower.onTakeShower(player, object, soapList, useSoap, towel, asIsWearing, useHot)
    local playerObj = getSpecificPlayer(player)
    local targetSqr = object:getSquare()
    local facing = TABAS_Utils.getObjectFacing(object)
    local TABAS_UnEquipItems = require("TABAS_UnEquipItems")

    local climbObj = nil
    local isSolid = targetSqr:isSolidTrans()
    if isSolid then
        climbObj = TABAS_Utils.getBathObjectOnSquare(targetSqr)
    end
    local prepSqr = TABAS_Common.FindFrontFreeSquare(targetSqr, facing)
    if not prepSqr then
        if climbObj then
            local prepSqr1 = TABAS_Common.FindAdjacentTubSquare(playerObj, climbObj, facing)
            if not prepSqr1 or prepSqr1:getProperties():has("BlocksPlacement") then
                climbObj = TABAS_Utils.getGridExtensionBath(climbObj)
                local prepSqr2 = TABAS_Common.FindAdjacentTubSquare(playerObj, climbObj, facing)
                if prepSqr2 and not prepSqr2:getProperties():has("BlocksPlacement") then
                    prepSqr = prepSqr2
                else
                    prepSqr = prepSqr1
                    climbObj = object
                end
            else
                prepSqr = prepSqr1
            end
        else
            if not prepSqr then
                prepSqr = TABAS_Common.FindClosestAdjacent3Square(playerObj, targetSqr, facing)
                if not prepSqr or prepSqr:getProperties():has("BlocksPlacement") then
                    local freeSqr = TABAS_Common.FindClosestAdjacentFreeSquare(playerObj, targetSqr, facing)
                    if freeSqr then
                        prepSqr = freeSqr
                    end
                end
            end
        end
    end
    if not prepSqr then
        playerObj:Say(getText("IGUI_TABAS_Unreachable"))
        return
    end
    local inTub = isSolid and climbObj
    local tfc_Base = inTub and TABAS_Utils.getTfcBaseOnBathObject(climbObj) or nil

    ISTimedActionQueue.add(ISWalkToTimedAction:new(playerObj, prepSqr))
    if towel then
        ISWorldObjectContextMenu.transferIfNeeded(playerObj, towel)
    end
    TABAS_UnEquipItems.doUnequip(player, asIsWearing)
    if inTub and tfc_Base then
        ISTimedActionQueue.add(TABAS_ClimbOverTubEdge:new(playerObj, tfc_Base, climbObj, prepSqr, true))
        ISTimedActionQueue.add(TABAS_WalkInTheTubAction:new(playerObj, tfc_Base, climbObj, targetSqr))
    else
        ISTimedActionQueue.add(ISWalkToTimedAction:new(playerObj, targetSqr))
    end
    ISTimedActionQueue.add(TABAS_TakeShower:new(playerObj, object, soapList, useSoap, inTub, useHot))
    if inTub then
        ISTimedActionQueue.add(TABAS_WalkInTheTubAction:new(playerObj, tfc_Base, climbObj, climbObj:getSquare()))
        ISTimedActionQueue.add(TABAS_ClimbOverTubEdge:new(playerObj, tfc_Base, climbObj, prepSqr))
    else
        ISTimedActionQueue.add(ISWalkToTimedAction:new(playerObj, prepSqr))
    end
    ISTimedActionQueue.add(TABAS_DrySelf:new(playerObj, towel))
    ISTimedActionQueue.add(TABAS_ReEquipItems:new(playerObj, player))
end

Events.OnFillWorldObjectContextMenu.Add(TABAS_ContextMenuShower.ShowerContextCreateMenu)

return TABAS_ContextMenuShower