local S = core.get_translator(core.get_current_modname())

local debuff_color = "#ff4500"

local function armor_protection(itemstring)
    local item = core.registered_items[itemstring]

    if item and item.armor_groups and item.armor_groups.fleshy then
        if item.armor_groups.fleshy > 0 then
            return S("Protection: +@1%", item.armor_groups.fleshy),
                   tt.COLOR_DEFAULT
        end
    end
end

local function armor_block(itemstring)
    local item = core.registered_items[itemstring]

    if item and item.groups and item.groups.armor_heal then
        if item.groups.armor_heal > 0 then
            return S("Block chance: +@1%", item.groups.armor_heal),
                   tt.COLOR_DEFAULT
        end
    end
end

local function armor_move_speed(itemstring)
    local item = core.registered_items[itemstring]

    if item and item.groups and item.groups.physics_speed then
        if item.groups.physics_speed > 0 then
            return S("Move speed: +@1%", item.groups.physics_speed * 100),
                   tt.COLOR_DEFAULT
        elseif item.groups.physics_speed < 0 then
            -- Don't add a '-' because that is part of the number already
            return S("Move speed: @1%", item.groups.physics_speed * 100),
                   debuff_color
        end
    end
end

local function mana_cost(itemstring)
    local tool = core.registered_tools[itemstring]
    local color = "#00ffff"

    if tool and tool._yams_tt_mana_cost then
        return S("Mana cost: @1", tool._yams_tt_mana_cost), color
    end
end

-- Swords and axes have suitable melee stats, while other tools that have
-- damage values should only be used as a last resort and wear out faster when
-- used that way
local function is_unreliable_melee_weapon(itemstring)
    local display_stats_anyway = false  -- For debugging

    if display_stats_anyway then
        return false
    end

    -- Hardcoded exception
    if itemstring == "anvil:hammer" then
        return true
    end

    local tool = core.registered_tools[itemstring]

    -- Does not have damage values so not considered a possible melee weapon
    if not tool or not tool.groups or not tool.tool_capabilities then
        return false
    end

    return tool.groups.pickaxe or tool.groups.shovel or
           tool.groups.sickle or tool.groups.scythe or tool.groups.hoe
end

local function unreliable_melee_weapon(itemstring)
    if is_unreliable_melee_weapon(itemstring) then
        return S("Less durable when used as a weapon"), debuff_color
    end
end

local function base_damage(itemstring)
    local tool = core.registered_tools[itemstring]

    if tool and not is_unreliable_melee_weapon(itemstring) then
        local tcaps = tool.tool_capabilities
        if tcaps and tcaps.damage_groups and tcaps.damage_groups.fleshy then
            return S("Base damage: @1", tcaps.damage_groups.fleshy),
                   tt.COLOR_DEFAULT
        elseif tool._yams_tt_damage then  -- For ranged weapons
            return S("Base damage: @1", tool._yams_tt_damage),
                   tt.COLOR_DEFAULT
        end
    end
end

local element_mapping = {
    yams_physical = S("Physical"),
    yams_magical = S("Magical"),
    yams_neutral = S("Neutral"),
    yams_fire = S("Fire"),
    yams_ice = S("Ice"),
    yams_electric = S("Electric"),
    yams_mese = S("Mese"),
    yams_light = S("Light"),
    yams_dark = S("Dark"),
}

local function weapon_element(itemstring)
    local tool = core.registered_tools[itemstring]
    local unreliable = is_unreliable_melee_weapon(itemstring)

    if tool and tool._yams_elements and not unreliable then
        local res = "Element: "

        -- Display whether it is physical or magical first
        if tool._yams_elements.yams_physical then
            res = res .. element_mapping["yams_physical"] .. " / "
        elseif tool._yams_elements.yams_magical then
            res = res .. element_mapping["yams_magical"] .. " / "
        end
        
        for element, _ in pairs(tool._yams_elements) do
            -- Assume only one additional element
            if element ~= "yams_physical" and element ~= "yams_magical" then
                res = res .. element_mapping[element]
                break
            end
        end
        
        return res
    end
end

local function knockback_display(itemstring)
    local tool = core.registered_tools[itemstring]
    local unreliable = is_unreliable_melee_weapon(itemstring)

    if tool and tool._yams_knockback and not unreliable then
        local descriptor = "None"

        if tool._yams_knockback >= 8.25 then
            descriptor = "Very Strong"
        elseif tool._yams_knockback >= 6.75 then
            descriptor = "Strong"
        elseif tool._yams_knockback >= 5.25 then
            descriptor = "Average"
        elseif tool._yams_knockback >= 3.75 then
            descriptor = "Weak"
        else
            descriptor = "Very Weak"
        end

        return S("Knockback: @1 (@2)", tool._yams_knockback, descriptor),
               tt.COLOR_DEFAULT
	end
end

local function ammo_type(itemstring)
    local tool = core.registered_tools[itemstring]
    if tool and tool._yams_tt_ammo_type then
        local ammo_def = core.registered_items[tool._yams_tt_ammo_type]
        assert(ammo_def ~= nil)
        local ammo_desc = ammo_def._tt_original_description or
                          ammo_def.description

        return S("Ammo needed: @1", ammo_desc)
    end
end

local function repair_with(itemstring)
    local tool = core.registered_tools[itemstring]
    if tool and tool._yams_tt_repair_with then
        local item_def = core.registered_items[tool._yams_tt_repair_with]
        assert(item_def ~= nil)
        local item_desc = item_def._tt_original_description or
                          item_def.description

        return S("Repair with: @1", item_desc)
    end
end

local function primary_and_secondary_stat(itemstring)
    local tool = core.registered_tools[itemstring]
    local unreliable = is_unreliable_melee_weapon(itemstring)

    if tool and tool._yams_stat_factors and not unreliable then
        local sf = tool._yams_stat_factors
        local result = ""

        local primary_str = "Primary Stat: "
        if sf.primary == "str" then
            primary_str = S(primary_str .. "Strength (@1%)", sf.str * 100)
        elseif sf.primary == "dex" then
            primary_str = S(primary_str .. "Dexterity (@1%)", sf.dex * 100)
        elseif sf.primary == "int" then
            primary_str = S(primary_str .. "Intelligence (@1%)", sf.int * 100)
        else
            assert(false, "Primary stat is not valid for " .. itemstring)
        end

        result = result .. primary_str
        if sf.secondary then
            local second_str = "Secondary Stat: "
            if sf.secondary == "str" then
                second_str = S(second_str .. "Strength (@1%)", sf.str * 100)
            elseif sf.secondary == "dex" then
                second_str = S(second_str .. "Dexterity (@1%)", sf.dex * 100)
            elseif sf.secondary == "int" then
                second_str = S(second_str .. "Intelligence (@1%)", sf.int * 100)
            else
                assert(false, "Secondary stat is not valid for " .. itemstring)
            end

            result = result .. "\n" .. second_str
        end

        return result, "#ffff00"
    end
end

tt.register_snippet(armor_protection)
tt.register_snippet(armor_block)
tt.register_snippet(armor_move_speed)
tt.register_snippet(mana_cost)
tt.register_snippet(unreliable_melee_weapon)
tt.register_snippet(base_damage)
tt.register_snippet(weapon_element)
tt.register_snippet(knockback_display)
tt.register_snippet(ammo_type)
tt.register_snippet(repair_with)
tt.register_snippet(primary_and_secondary_stat)

core.override_item("default:chest", {
    _tt_help = S("Two chests can be joined together") .. "\n" ..
               S("Sneak + Place while pointing at a side"),
})

core.override_item("default:book", {
    _tt_help = S("Write anything inside") .. "\n" ..
               S("Written books can be modified by their authors"),
})

core.override_item("default:bookshelf", {
    _tt_help = S("Contains 16 inventory slots for books"),
})

core.override_item("default:furnace", {
    _tt_help = S("Cooks and smelts items"),
})

local bed_tt = S("Sleep during the night to pass the time") .. "\n" ..
               S("If you die, you respawn at the last bed you slept in")

if core.get_modpath("beds") then
    core.override_item("beds:bed_bottom", {
        _tt_help = bed_tt,
    })
    core.override_item("beds:fancy_bed_bottom", {
        _tt_help = bed_tt,
    })
end

if core.get_modpath("boats") then
    core.override_item("boats:boat", {
        _tt_help = S("Vehicle for traversing water") .. "\n" ..
                   S("Board and unboard with the Place button") .. "\n" ..
                   S("Punch the boat to pick it up") .. "\n" ..
                   S("Forward + Backward enables cruise mode") .. "\n" ..
                   S("Slow down to disable cruise mode")
    })
end

if core.get_modpath("bucket") then
    core.override_item("bucket:bucket_empty", {
        _tt_help = S("Holds liquids")
    })
end

if core.get_modpath("carts") then
    core.override_item("carts:cart", {
        description = S("Cart"),
        _tt_help = S("Vehicle for riding rails") .. "\n" ..
                   S("Board and unboard with the Place button") .. "\n" ..
                   S("Punch the cart to move it") .. "\n" ..
                   S("Sneak + Punch to pick up the cart")
    })
end

if core.get_modpath("fire") then
    core.override_item("fire:flint_and_steel", {
        _tt_help = S("Ignites flammable blocks and items"),
    })
end

if core.registered_items["tnt:tnt"] then
    core.override_item("tnt:tnt", {
        _tt_help = S("Explodes shortly after being ignited")
    })
end

if core.get_modpath("vessels") then
    core.override_item("vessels:shelf", {
        _tt_help = S("Contains 16 inventory slots for bottles")
    })
end

local empty_tank_items = {
    "airtanks:empty_bronze_tank",
    "airtanks:empty_bronze_tank_2",
    "airtanks:empty_bronze_tank_3",
    "airtanks:empty_copper_tank",
    "airtanks:empty_copper_tank_2",
    "airtanks:empty_copper_tank_3",
    "airtanks:empty_steel_tank",
    "airtanks:empty_steel_tank_2",
    "airtanks:empty_steel_tank_3",
}

local tank_items = {
    "airtanks:bronze_tank",
    "airtanks:bronze_tank_2",
    "airtanks:bronze_tank_3",
    "airtanks:copper_tank",
    "airtanks:copper_tank_2",
    "airtanks:copper_tank_3",
    "airtanks:steel_tank",
    "airtanks:steel_tank_2",
    "airtanks:steel_tank_3",
}

if core.get_modpath("airtanks") then
    core.override_item("airtanks:breathing_tube", {
        _tt_help = S("Draws air from air tanks automatically") .. "\n" ..
                   S("Equip this in the hotbar") .. "\n" ..
                   S("Air tanks must also be in the hotbar"),
    })

    core.override_item("airtanks:compressor", {
        _tt_help = S("Refills air tanks using fuel"),
    })

    for _, item in pairs(empty_tank_items) do
        core.override_item(item, {
            _tt_help = S("Needs to be filled with air"),
        })
    end

    for _, item in pairs(tank_items) do
        core.override_item(item, {
            _tt_help = S("Restores 5 breath when used"),
        })
    end
end

if core.registered_items["hangglider:hangglider"] then
    core.override_item("hangglider:hangglider", {
        _tt_help = S("Allows gliding through the air") .. "\n" ..
                   S("Repair using wool or pieces of paper") .. "\n" ..
                   S("Can be dyed")
    })
end

if core.get_modpath("hopper") then
    core.override_item("hopper:hopper", {
        _tt_help = S("Transfers items from one block to another") .. "\n" ..
                   S("See the help page for more details")
    })

    core.override_item("hopper:hopper_side", {
        _tt_help = S("Transfers items from one block to another") .. "\n" ..
                   S("See the help page for more details")
    })

    core.override_item("hopper:chute", {
        _tt_help = S("Extends the range of a hopper") .. "\n" ..
                   S("Connect to a hopper's narrow tube") .. "\n" ..
                   S("See the help page for more details")
    })

    core.override_item("hopper:sorter", {
        _tt_help = S("Filters items received from hoppers") .. "\n" ..
                   S("See the help page for more details")
    })
end

local function orienteering_items(itemstring)
    if string.split(itemstring, ":")[1] == "orienteering" then
        local res = S("Equip by placing it in the hotbar")

        if itemstring == "orienteering:gps" or
                itemstring == "orienteering:quadcorder" or
                itemstring == "orienteering:watch" then
            local time_text = S("Use to toggle between 12 and 24-hour time")
            res = res .. "\n" .. time_text
        end

        return res, tt.COLOR_DEFAULT
    end
end

tt.register_snippet(orienteering_items)

if core.get_modpath("ropes") then
    -- Default values are yams defaults, not the mod's
    local rope_len = core.settings:get("ropes_rope_length")
    rope_len = rope_len and tonumber(rope_len) or 100

    local copper_max = core.settings:get("ropes_copper_rope_box_max_multiple")
    copper_max = copper_max and tonumber(copper_max) or 2

    for i=1, copper_max do
        local itemstring = "ropes:copper" .. tostring(i) .. "rope_block"
        local box_len = tostring(i * rope_len)

        core.override_item(itemstring, {
            _tt_help = S("Lowers a rope once placed") .. "\n" ..
                       S("Rope extends up to @1 meters", box_len)
        })
    end

    local steel_max = core.settings:get("ropes_steel_rope_box_max_multiple")
    steel_max = steel_max and tonumber(steel_max) or 5

    for i=1, steel_max do
        local itemstring = "ropes:steel" .. tostring(i) .. "rope_block"
        local box_len = tostring(i * rope_len)

        core.override_item(itemstring, {
            _tt_help = S("Lowers a rope once placed") .. "\n" ..
                       S("Rope extends up to @1 meters", box_len)
        })
    end

    local ladder_len = core.settings:get("ropes_rope_ladder_length")
    ladder_len = ladder_len and tonumber(ladder_len) or 100

    core.override_item("ropes:ropeladder_top", {
        _tt_help = S("Extends downwards once placed") .. "\n" ..
                   S("Ladder extends up to @1 meters", ladder_len)
    })

    core.override_item("ropes:wood_bridge", {
        _tt_help = S("Allows bridging gaps more easily") .. "\n" ..
                   S("Stack this on top of a bridge's end to extend it")
    })
end

if core.registered_items["screwdriver2:screwdriver"] then
    core.override_item("screwdriver2:screwdriver", {
        description = S("Screwdriver"),
        _tt_help = S("Rotates certain blocks") .. "\n" ..
                   S("Punch/dig to push the block's edge") .. "\n" ..
                   S("Place/use to rotate the block's face") .. "\n" ..
                   S("See the help page for more details")
    })
end

if core.registered_items["tph_spyglass:spyglass"] then
    core.override_item("tph_spyglass:spyglass", {
        _tt_help = S("Press the Place button to zoom in and out"),
    })
end

if core.get_modpath("wooden_bucket") then
    core.override_item("wooden_bucket:bucket_wood_empty", {
        _tt_help = S("Holds non-flammable liquids"),
    })
end

-- YAMS-TODO: use the 'eatable' group to obtain values but make sure that they
-- match the value passed to 'core.item_eat'
-- YAMS-TODO: double-check this list
local satiation_values = {
    ["default:apple"] = 2,
    ["default:blueberries"] = 2,
    ["ebiomes:acorns_cooked"] = 4,
    ["ebiomes:blackcurrants"] = 2,
    ["ebiomes:cranberries"] = 2,
    ["ebiomes:cowberries"] = 2,
    ["ebiomes:gooseberries"] = 2,
    ["ebiomes:redcurrants"] = 2,
    ["ebiomes:chestnuts_roasted"] = 4,
    ["ebiomes:olives"] = 2,
    ["ebiomes:peas_cooked"] = 5,
    ["ebiomes:pear"] = 2,
    ["ebiomes:quince"] = 1,
    ["ebiomes:dried_quince_pieces"] = 4,
    ["ebiomes:tamarind_pulp"] = 2,
    ["farming:carrot"] = 2,
    ["farming:carrot_juice"] = 2,
    ["farming:chili_pepper"] = 2,
    ["farming:chili_bowl"] = 10,
    ["farming:cookie"] = 2,
    ["farming:lettuce"] = 2,
    ["farming:melon_slice"] = 2,
    ["farming:mint_tea"] = 2,
    ["ethereal:strawberry"] = 2,
    ["farming:tomato"] = 2,
    ["farming:tomato_soup"] = 5,
    ["farming:bread"] = 8,
    ["farming:burger"] = 16,
    ["farming:donut_chocolate"] = 6,
    ["farming:mochi"] = 6,
    ["farming:salad"] = 10,
    ["farming:smoothie_berry"] = 6,
    ["flowers:mushroom_red"] = -5,
    ["flowers:mushroom_brown"] = 1,
    ["mobs:cheese"] = 4,
    ["mobs:glass_milk"] = 2,
    ["mobs:chicken_raw"] = 2,
    ["mobs:chicken_cooked"] = 6,
    ["mobs:chicken_egg_fried"] = 2,
    ["mobs:meat_raw"] = 3,
    ["mobs:meat"] = 8,
    ["mobs:mutton_raw"] = 2,
    ["mobs:mutton_cooked"] = 6,
    ["mobs:pork_raw"] = 4,
    ["mobs:pork_cooked"] = 8,
    ["mobs:rabbit_raw"] = 3,
    ["mobs:rabbit_cooked"] = 5,
    ["mobs:rat_cooked"] = 3,
    ["tmw_slimes:algae_goo"] = 2,
    ["tmw_slimes:alien_goo"] = -5,
    ["tmw_slimes:cloud_goo"] = 0,
    ["tmw_slimes:dark_goo"] = -5,
    ["tmw_slimes:jungle_goo"] = 3,
    ["tmw_slimes:lava_goo"] = -5,
    ["tmw_slimes:ocean_goo"] = 1,
    ["tmw_slimes:poisonous_goo"] = -5,
    ["tmw_slimes:savanna_goo"] = 1,
    ["yams_farming:coffee_cup_hot"] = 4,
    ["yams_farming:chocolate"] = 4,
    ["yams_farming:donut_strawberry"] = 6,
    ["yams_farming:fries"] = 6,
    ["yams_farming:baked_potato"] = 6,
    ["yams_farming:potato"] = 2,
    ["yams_farming:poisonous_potato"] = -6,
    ["farming:pumpkin_slice"] = 2,
    ["farming:pumpkin_pie"] = 6,
}

local function food_satiation(itemstring)
    local val = satiation_values[itemstring]
    local color = "#ff8300"

    if val then
        if val >= 0 then
            return S("Satiation: +@1", val), color
        else
            return S("Satiation: @1", val), debuff_color
        end
    end
end

tt.register_snippet(food_satiation)

local function food_mana(itemstring)
    local def = core.registered_items[itemstring]
    if def and def._yams_mana_restore then
        local color = "#00ffff"
        local pct = def._yams_mana_restore * 100

        return S("Mana restored: @1%", pct), color
    end
end

tt.register_snippet(food_mana)

local function food_effects(itemstring)
    local def = core.registered_items[itemstring]
    if def and def._yams_tt_effect_descs then
        local res = ""
        for _, effect in pairs(def._yams_tt_effect_descs) do
            if res ~= "" then
                res = res .. "\n"
            end

            res = res .. S("[Effect] @1", effect.name) .. "\n"
            res = res .. effect.desc
        end
        return res, "#ffff00"
    end
end

tt.register_snippet(food_effects)

local function generic_seed_tooltip(itemstring)
    local def = core.registered_items[itemstring]
    if def and def.groups and def.groups.seed and not def._tt_help then
        return S("Plant on wet soil"), tt.COLOR_DEFAULT
    end
end

tt.register_snippet(generic_seed_tooltip)
