local TABAS_ContextMenuBathtub = {}

local TABAS_Utils = require("TABAS_Utils")
local TABAS_Common = require("TABAS_ContextMenuCommon")
local TABAS_WaterReader = require("TABAS_WaterReader")
local TFC_Menu = require("TABAS_TubFluidContainerMenu")
local TFC_DebugMenu = require("TABAS_TubFluidContainerDebugMenu")


function TABAS_ContextMenuBathtub.BathContextCreateMenu(player, context, worldObjects, test)
    local bathSprites = TABAS_Utils.getBathSprites()
    local bathObj = TABAS_Utils.getBathingObjectFromWorldObjects(worldObjects, bathSprites)
    if not bathObj then return end

    local faucetObj, tubObj = TABAS_Utils.getFullyBathObject(bathObj)
    if not faucetObj or not tubObj then return end

    local displayName = ISWorldObjectContextMenu.getMoveableDisplayName(faucetObj)

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

    local tfc_Base = TABAS_Utils.getTfcBaseOnBathObject(faucetObj)
    if not tfc_Base then return end

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

    TABAS_Common.doWalkInTheTubMenu(player, faucetObj, tubObj, subMenu)

    local using = tfc_Base:isUsing()
    if using then
        mainMenu.notAvailable = true
        local tooltip = ISWorldObjectContextMenu.addToolTip()
        tooltip.description = TABAS_Common.usingTooltipText
        mainMenu.toolTip = tooltip
        if isDebugEnabled() then
            TABAS_Common.doDebugMenu(player, faucetObj, subMenu)
        end
    end

    -- TFC Info Panel
    -- TFC_Menu.doInfoMenu(player, tfc_Base, subMenu) -- This is not yet complete.
    
    -- Take Bath Menu
    if tfc_Base:getRatio() > tfc_Base.filledConst.HalfLow and not using then
        TABAS_ContextMenuBathtub.doTakeBathMenu(player, tfc_Base, subMenu)
    end

    -- Tub FLuid Container Menu
    local hasTfc = tfc_Base:hasTfc()
    if hasTfc then
        -- Remove vanilla fluid menu for tfc.
        context.dontShowLiquidOption = true
        local tfcName = tfc_Base:getTfcName()
        if tfcName and context:getOptionFromName(tfcName) then
            context:removeOptionByName(tfcName)
        end
        local tfcObject = tfc_Base.tfcObject
        local fluidUiName = tfcObject:getFluidUiName()
        if context:getOptionFromName(fluidUiName) then
            context:removeOptionByName(fluidUiName)
        end
        if using then return end

        -- TubFluidContainerMenu
        local tfcMenu = subMenu:addOption(getText("ContextMenu_TABAS_TubFluidContainer"))
        local tfcSubMenu = ISContextMenu:getNew(subMenu)
        subMenu:addSubMenu(tfcMenu, tfcSubMenu)
        local icon = "media/ui/Icons/tabas_tubicon.png"
        tfcMenu.iconTexture = getTexture(icon)
        local temperatureConcept = SandboxVars.TakeABathAndShower.WaterTemperatureConcept
        local enableReheat = SandboxVars.TakeABathAndShower.EnableReheat
        local canHot = TABAS_Utils.canHot(faucetObj)

        if not tfc_Base:isFull() then
            TFC_Menu.doFillTubWaterMenu(player, tfc_Base, tfcSubMenu, canHot)
        end

        if tfc_Base:hasFluid() then
            TFC_Menu.doEmptyTubWaterMenu(player, tfc_Base, tfcSubMenu)
            if temperatureConcept and enableReheat and canHot then
                TFC_Menu.doReheatTubWater(player, tfc_Base, subMenu)
            end
        else
            TFC_Menu.doRemoveTubStopperMenu(player, tfc_Base, tfcSubMenu)
        end

        if not tfc_Base:isEmpty() then
            TFC_Menu.doAddBathSaltMenu(player, tfc_Base, tfcSubMenu)
        end

        local allowedVanillaFluidMenu = true
        if allowedVanillaFluidMenu and not using then
            TABAS_Common.vanillaFluidMenu(player, nil, nil, tfcObject, tfcSubMenu)
            local fluidContainer = tfc_Base:getTubFluidContainer()
            tfcSubMenu:addOption(getText("Fluid_Transfer_Fluids"), player, ISWorldObjectContextMenu.onFluidTransfer, fluidContainer)
        end
    else
        -- First, Put Tub Stopper
        TFC_Menu.doPutTubStopperMenu(player, tfc_Base, subMenu)
    end
    
    -- Set Temperature
    TABAS_Common.setTemperatureMenu(player, faucetObj, subMenu)

    -- Vanilla FLuid Menu from Faucet
    local faucetMenu = subMenu:addOption(getText("ContextMenu_TABAS_FaucetMenu"))
    local waterSourceCount = TABAS_WaterReader.getExternalContainerCount(faucetObj)
    local icon = "media/ui/Icons/tabas_bathFaucet.png"
    faucetMenu.iconTexture = getTexture(icon)
    local notPiped = waterSourceCount == 0 and faucetObj:getModData().canBeWaterPiped
    if notPiped then
        faucetMenu.notAvailable = true
        local tooltip = ISWorldObjectContextMenu.addToolTip()
        tooltip.description = TABAS_Common.notPipedTooltipText
        faucetMenu.toolTip = tooltip
    else
        local faucetSubMenu = ISContextMenu:getNew(subMenu)
        subMenu:addSubMenu(faucetMenu, faucetSubMenu)
        TABAS_Common.vanillaFluidMenu(player, worldObjects, test, faucetObj, faucetSubMenu)
    end

    -- Take Shower Menu -- This is no longer necessary.

    -- Clean tub
    if not faucetObj:getModData().isClean then
        TABAS_ContextMenuBathtub.doCleanTubMenu(player, faucetObj, tubObj, hasTfc, subMenu)
    end
    -- Common Debug Menu
    if isDebugEnabled() then
        local debugMenu = TABAS_Common.doDebugMenu(player, faucetObj, subMenu)
        if faucetObj:getModData().isClean then
            debugMenu:addDebugOption(getText("ContextMenu_TABAS_RevertTub"), player, TABAS_ContextMenuBathtub.onRevertTub, tfc_Base)
        end
        -- TFC Debug
        if hasTfc then
            TFC_DebugMenu.donDebugMenu(tfc_Base, subMenu)
        end
    end
end

function TABAS_ContextMenuBathtub.doTakeBathMenu(player, tfc_Base, context)
    local playerObj = getSpecificPlayer(player)
    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 option = context:addGetUpOption(getText("ContextMenu_TABAS_TakeBath"), player, TABAS_ContextMenuBathtub.onTakeBath, tfc_Base, towel, asIsWearing)
    local icon = "media/ui/Icons/tabas_takeBath.png"

    local tooltip = ISWorldObjectContextMenu.addToolTip()
    option.iconTexture = getTexture(icon)

    local tubCapacity = tfc_Base:getCapacity()
    local tubAmount = tfc_Base:getAmount()
    local temperature = tfc_Base:getWaterData("temperature")
    local bathSalt = tfc_Base:getWaterData("bathSalt")
    local dirtyLevel = tfc_Base:getDirtyLevel()

    local width = 0
    local font = UIFont[getCore():getOptionTooltipFont()] or UIFont.Small
    width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_TABAS_TubWaterAmount") .. ":") + 20)
    width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_TABAS_BathTemperature") .. ":") + 20)
    width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_TABAS_BathSalt") .. ":") + 20)
    width = math.max(width, getTextManager():MeasureStringX(font, getText("ContextMenu_TABAS_UseTowel") .. ":") + 20)

    tooltip.defaultMyWidth = width
    local lineBreaks = " <LINE> "
    tooltip.description = tooltip.description .. TABAS_Common.formatWaterAmount(getText("ContextMenu_TABAS_TubWaterAmount"), width, tubAmount, tubCapacity)
    local formatedTemp = TABAS_Utils.formatedCelsiusOrFahrenheit(temperature)
    tooltip.description = tooltip.description .. lineBreaks ..  TABAS_Common.formatLabelAndValue(getText("ContextMenu_TABAS_BathTemperature"), width, formatedTemp)
    if bathSalt then
        tooltip.description = tooltip.description .. lineBreaks ..  TABAS_Common.formatLabelAndValue(getText("ContextMenu_TABAS_BathSalt"), width, getText("IGUI_TABAS_BathSalt_" .. bathSalt))
    end

    tooltip.description = tooltip.description .. lineBreaks ..  TABAS_Common.formatLabelAndValue(getText("IGUI_TABAS_BathtubInfo_Dirty"), width, dirtyLevel)

    if requireTowel then
        local canDry = towel ~= nil
        tooltip.description = tooltip.description .. lineBreaks .. TABAS_Common.formatLabelAndBoolean(getText("ContextMenu_TABAS_UseTowel"), width, canDry)
    end
    lineBreaks = " <BR> "
    if tfc_Base:getWaterData("isDirty") then
        tooltip.description = tooltip.description .. lineBreaks .. " <RGB:1,0.5,0.5> " ..  (getText("ContextMenu_TABAS_TubWaterDirty"))
        lineBreaks = " <LINE> "
    end
    if tfc_Base:getRatio() < tfc_Base.filledConst.Half then
        tooltip.description = tooltip.description .. lineBreaks .. " <RGB:1,0.5,0.5> " ..  (getText("ContextMenu_TABAS_NotEnoughWaterTakeBath"))
        lineBreaks = " <LINE> "
    end
    if temperature > 45 then
        option.notAvailable = true
        tooltip.description = tooltip.description .. lineBreaks .. " <RGB:1,0.5,0.5> " ..  (getText("ContextMenu_TABAS_TooHot"))
    end

    option.toolTip = tooltip
end

function TABAS_ContextMenuBathtub.onTakeBath(player, tfc_Base, towel, asIsWearing, bathTime)
    if not tfc_Base then return end

    local playerObj = getSpecificPlayer(player)
    local object = tfc_Base.bathObject
    local targetSqr = tfc_Base.square
    local facing = tfc_Base.facing
    local TABAS_UnEquipItems = require("TABAS_UnEquipItems")
    local climbObj = nil

    local prepSqr
    local prepSqr1 = TABAS_Common.FindAdjacentTubSquare(playerObj, object, facing)
    if not prepSqr1 or prepSqr1:getProperties():Is("BlocksPlacement") then
        climbObj = tfc_Base.linkedBathObject
        local prepSqr2 = TABAS_Common.FindAdjacentTubSquare(playerObj, climbObj, facing)
        if prepSqr2 and not prepSqr2:getProperties():Is("BlocksPlacement") then
            prepSqr = prepSqr2
        else
            prepSqr = prepSqr1
            climbObj = nil
        end
    else
        prepSqr = prepSqr1
    end
    if not prepSqr then
        playerObj:Say(getText("IGUI_TABAS_Unreachable"))
        return
    end

    ISTimedActionQueue.add(ISWalkToTimedAction:new(playerObj, prepSqr))
    TABAS_UnEquipItems.doUnequip(player, asIsWearing, true)
    if climbObj then
        ISTimedActionQueue.add(TABAS_ClimbOverTubEdge:new(playerObj, climbObj, prepSqr, true))
        ISTimedActionQueue.add(TABAS_WalkInTheTubAction:new(playerObj, climbObj, targetSqr))
    else
        ISTimedActionQueue.add(TABAS_ClimbOverTubEdge:new(playerObj, object, prepSqr, true))
    end
    ISTimedActionQueue.add(TABAS_TakeBath:new(playerObj, tfc_Base, targetSqr, bathTime))
    if climbObj then
        ISTimedActionQueue.add(TABAS_WalkInTheTubAction:new(playerObj, climbObj, climbObj:getSquare()))
        ISTimedActionQueue.add(TABAS_ClimbOverTubEdge:new(playerObj, climbObj, prepSqr))
    else
        ISTimedActionQueue.add(TABAS_ClimbOverTubEdge:new(playerObj, object, prepSqr))
    end
    ISTimedActionQueue.add(TABAS_DrySelf:new(playerObj, towel))
    ISTimedActionQueue.add(TABAS_ReEquipItems:new(playerObj, player))
end

local function predicateCleaningLiquid(item)
	return item:getFluidContainer() and item:getFluidContainer():contains(Fluid.CleaningLiquid) and (item:getFluidContainer():getAmount() >= ZomboidGlobals.CleanBloodBleachAmount)
end

local function predicateNotBrokenSponge(item)
	return item:getType() == "Sponge" and not item:isBroken()
end

function TABAS_ContextMenuBathtub.doCleanTubMenu(player, faucetObj, tubObj, hasTfc, subMenu)
    local playerObj = getSpecificPlayer(player)
	local playerInv = playerObj:getInventory()
    local bleach = playerInv:getFirstEvalRecurse(predicateCleaningLiquid)
    local sponge = playerInv:getFirstTagEvalRecurse("CleanStains", predicateNotBrokenSponge)

    local option = subMenu:addOption(getText("ContextMenu_TABAS_CleanTub"), player, TABAS_ContextMenuBathtub.onCleanTub,  faucetObj, tubObj, sponge, bleach)
    local tooltip = ISWorldObjectContextMenu.addToolTip()
    local icon = "media/ui/Icons/tabas_cleantub.png"
    option.iconTexture = getTexture(icon)
    tooltip.description = getText("ContextMenu_TABAS_CleanTub_tooltip")
    if not sponge or not bleach then
        option.notAvailable = true
        tooltip.description = tooltip.description .. " <BR> " .. getText("ContextMenu_TABAS_CleanTub_Required")
    elseif hasTfc then
        option.notAvailable = true
        tooltip.description = tooltip.description .. " <BR> " .. getText("ContextMenu_TABAS_CleanTub_ToEmpty")
    end
    option.toolTip = tooltip
end

function TABAS_ContextMenuBathtub.onCleanTub(player, faucetObj, tubObj, sponge, bleach)
    local playerObj = getSpecificPlayer(player)
	if TABAS_Common.walkToAdjTub(playerObj, faucetObj, true) then
		ISWorldObjectContextMenu.transferIfNeeded(playerObj, bleach)
        ISWorldObjectContextMenu.transferIfNeeded(playerObj, sponge)
        ISInventoryPaneContextMenu.equipWeapon(sponge, true, false, player)
        ISInventoryPaneContextMenu.equipWeapon(bleach, false, false, player)
		ISTimedActionQueue.add(TABAS_CleanTub:new(playerObj, faucetObj, tubObj, bleach))
	end
end

function TABAS_ContextMenuBathtub.onRevertTub(player, tfc_Base)
    local faucetObj = tfc_Base.bathObject
    local tubObj = tfc_Base.linkedBathObject
    local square = faucetObj:getSquare()
    local subSquare = tubObj:getSquare()
    tfc_Base:remove()
    TABAS_CleanTub.createNewTub(faucetObj, square)
    TABAS_CleanTub.createNewTub(tubObj, subSquare)
    if isClient() then
        square:transmitRemoveItemFromSquare(faucetObj)
        subSquare:transmitRemoveItemFromSquare(tubObj)
    end
    if isServer() then
        square:transmitRemoveItemFromSquareOnClients(faucetObj)
        subSquare:transmitRemoveItemFromSquareOnClients(tubObj)
    end
    -- subSquare:RemoveTileObject(tubObj)
    square:RemoveTileObject(faucetObj)
    square:RecalcProperties()
    square:RecalcAllWithNeighbours(true)
end

Events.OnFillWorldObjectContextMenu.Add(TABAS_ContextMenuBathtub.BathContextCreateMenu)

return TABAS_ContextMenuBathtub