local TABAS_TFCSystem = {}

local TABAS_Utils = require("TABAS_Utils")
local TFC_Utils = require("TABAS_TFCSystem_Utils")

function TABAS_TFCSystem.register(tfc_Base)
    local facing = tfc_Base.facing
    local amount = tfc_Base:getAmount()
    local temperature = tfc_Base:getWaterData("temperature")
    local lastUpdate = tfc_Base:getLastUpdate()
    local args = {
        x = tfc_Base.x,
        y = tfc_Base.y,
        z = tfc_Base.z,
        f = facing,
        amount = amount,
        lastUpdate = lastUpdate,
        temperature = temperature,
    }
    sendClientCommand(getSpecificPlayer(0), 'tfcCommands', 'Register', args)
    TFC_Utils.noise("Registered", TFC_Utils.formatCoords(tfc_Base.x, tfc_Base.y, tfc_Base.z))
end

function TABAS_TFCSystem.isRegistered(x, y, z)
    local id = TFC_Utils.getIdByCoords(x, y, z)
    local gData = GetTFCSystemData()
    for k, _ in pairs(gData.Registered) do
        if k == id then return true end
    end
    return false
end

function TABAS_TFCSystem.unregister(x, y, z)
    if not TABAS_TFCSystem.isRegistered(x, y, z) then return end
    local args = {
        x = x,
        y = y,
        z = z,
    }
    sendClientCommand(getSpecificPlayer(0), 'tfcCommands', 'Unregister', args)
    TFC_Utils.noise("Unregistered", TFC_Utils.formatCoords(x, y, z))
end

function TABAS_TFCSystem.Activate(x, y, z, facing, state, activate)
    local args = {
        x = x,
        y = y,
        z = z,
        f = facing,
        state = state,
        activate = activate
    }
    sendClientCommand(getSpecificPlayer(0), 'tfcCommands', 'Activated', args)
    TFC_Utils.noise("TFC Activate", state .. " = " .. tostring(activate))
end

function TABAS_TFCSystem.currentActivatedState(x, y, z)
    local gData = GetTFCSystemData()
    local id = TFC_Utils.getIdByCoords(x, y, z)
    if gData.Activated[id] then
        return gData.Activated[id].state
    end
    return ""
end

function TABAS_TFCSystem.isActivated(x, y, z)
    local gData = GetTFCSystemData()
    local id = TFC_Utils.getIdByCoords(x, y, z)
    if gData.Activated[id] then
        return gData.Activated[id].activate
    else
        return false
    end
end

function TABAS_TFCSystem.syncData(x, y, z, facing)
    local gData = GetTFCSystemData()
    local id = TFC_Utils.getIdByCoords(x, y, z)
    local data = gData.Registered[id]
    if not data then return end

    local square = getCell():getGridSquare(x, y, z)
    if not square then return end

    local tfcObject = TABAS_Utils.getTfcObjectOnSquare(square, facing)
    if tfcObject then
        local modData = tfcObject:getModData()
        modData.amount = data.amount
        modData.temperature = data.temperature
        modData.lastUpdate = data.lastUpdate
        TFC_Utils.noise("TFC Sync Data", tostring(id))
    end
end

function TABAS_TFCSystem.transmitData(x, y, z, dataKey, dataValue)
    local args = {
        x = x,
        y = y,
        z = z,
    }
    args[dataKey] = dataValue

    sendClientCommand(getSpecificPlayer(0), 'tfcCommands', 'dataUpdate', args)
    -- TFC_Utils.noise("TFC update", dataKey .. " => " .. data)
    -- gData.Registered[id][dataKey] = tfc_Base:getWaterData(dataKey)
    -- TFCSystemTransmit()
end

function TABAS_TFCSystem.registPendedRemove(x, y, z, facing)
    local gData = GetTFCSystemData()
    for k,v in pairs(gData.Registered) do
        if x == v.x and y == v.y and z == v.z then
            TABAS_TFCSystem.unregister(x, y, z)
        end
    end
    local args = {
        x = x,
        y = y,
        z = z,
        f = facing
    }
    sendClientCommand(getSpecificPlayer(0), 'tfcCommands', 'RegistPendedRemove', args)
end

function TABAS_TFCSystem.unregistPendedRemove(x, y, z)
    local args = {
        x = x,
        y = y,
        z = z,
    }
    sendClientCommand(getSpecificPlayer(0), 'tfcCommands', 'UnregistPendedRemove', args)
end

local function onLoadChunk(chunk)
    local gData = GetTFCSystemData()
    for k,v in pairs(gData.Registered) do
        if chunk:getGridSquare(v.x, v.y, v.z) then
            local tfc_Base = TABAS_Utils.getTfcBase(v.x, v.y, v.z, v.f)
            -- To sync data, simply call TFC_Base.
        end
    end
    for k,v in pairs(gData.PendedRemove) do
        if chunk:getGridSquare(v.x, v.y, v.z) then
            local tfc_Base = TABAS_Utils.getTfcBase(v.x, v.y, v.z, v.f)
            if tfc_Base then
                tfc_Base:remove()
            end
            TABAS_TFCSystem.unregistPendedRemove(v.x, v.y, v.z)
        end
    end
end
Events.LoadChunk.Add(onLoadChunk)

local function onWaterAmountChange(object, prevAmount)
    if not object or not TABAS_Utils.isTfcObject(object) then return end

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

    tfc_Base:updateTfc()
    -- TFC_Utils.noise("onWaterAmountChange", "Done!")
end
Events.OnWaterAmountChange.Add(onWaterAmountChange)

local function onObjectAboutToBeRemoved(_object)
    local tfc_Base = TABAS_Utils.getTfcBaseOnBathObject(_object)
    if not tfc_Base then return end
    if not tfc_Base:hasTfc() then return end
    tfc_Base:remove()
    TFC_Utils.noise("Object Removed", "Done!")
end
Events.OnObjectAboutToBeRemoved.Add(onObjectAboutToBeRemoved)


local function tfcSpecialTooltip(tooltip, x, y, z, facing)
    local id = TFC_Utils.getIdByCoords(x, y, z)
    local gData = GetTFCSystemData()
    local data = gData.Registered[id]
    if not data then return end

    local amount = data.amount
    if amount > 0 then
        amount = round(amount, 2)
    else
        amount = 0
    end
    local temperature = TABAS_Utils.formatedCelsiusOrFahrenheit(data.temperature, 2)
    local capacity = SandboxVars.TakeABathAndShower.TubWaterCapacity
    tooltip:DrawTextureScaled(tooltip:getTexture(), 0, 0, tooltip:getWidth(), tooltip:getHeight(), 0.75)
    tooltip:DrawTextCentre(tooltip:getFont(), getText("Fluid_Container_TubFluidContainer"), tooltip:getWidth() / 2, 5, 1, 1, 1, 1)
    tooltip:adjustWidth(120, getText("Fluid_Container_TubFluidContainer"))
    local font = tooltip:getFont()

    local layout = tooltip:beginLayout()

    local layoutItem = layout:addItem()
    layoutItem:setLabel(getText("IGUI_TABAS_BathtubInfo_Amount") .. ": ", 1, 1, 1, 1)
    layoutItem:setValue(amount .. " / " .. capacity .. "L", 1, 1, 1, 1)

    local layoutItem = layout:addItem()
    layoutItem:setLabel(getText("IGUI_TABAS_BathtubInfo_Temperature") .. ": ", 1, 1, 1, 1)
    layoutItem:setValue(temperature, 1, 1, 1, 1)

    local height = layout:render(5, 5 + getTextManager():getFontHeight(font), tooltip)
    tooltip:setHeight(height + 15)
	tooltip:endLayout(layout)
end

local function doSpecialTooltip(tooltip, square)
    local x, y, z = square:getX(), square:getY(), square:getZ()
	if not TABAS_TFCSystem.isRegistered(x, y, z) then return end

	tooltip:setWidth(100)
	tooltip:setMeasureOnly(true)
	tfcSpecialTooltip(tooltip, x, y, z)
	tooltip:setMeasureOnly(false)
	tfcSpecialTooltip(tooltip, x, y, z)
end

Events.DoSpecialTooltip.Add(doSpecialTooltip)


return TABAS_TFCSystem