local mod_storage = minetest.get_mod_storage()
local S = minetest.get_translator("toolranks")

toolranks = {}

toolranks.colors = {
  grey = minetest.get_color_escape_sequence("#9d9d9d"),
  green = minetest.get_color_escape_sequence("#1eff00"),
  gold = minetest.get_color_escape_sequence("#ffdf00"),
  white = minetest.get_color_escape_sequence("#ffffff")
}

local max_speed = tonumber(minetest.settings:get("toolranks_speed_multiplier")) or 2.0
local max_use = tonumber(minetest.settings:get("toolranks_use_multiplier")) or 2.0
local max_level = tonumber(minetest.settings:get("toolranks_levels")) or 10
local level_digs = tonumber(minetest.settings:get("toolranks_level_digs")) or 500
local level_multiplier = 1 / max_level

function toolranks.get_tool_type(description)
  if not description then
    return "tool"
  else
    local d = string.lower(description)
    if string.find(d, "pickaxe") then
      return "pickaxe"
    elseif string.find(d, "axe") then
      return "axe"
    elseif string.find(d, "shovel") then
      return "shovel"
    elseif string.find(d, "hoe") then
      return "hoe"
    elseif string.find(d, "sword") then
      return "sword"
    else
      return "tool"
    end
  end
end

function toolranks.get_level(uses)
  if type(uses) == "number" and uses > 0 then
    return math.min(max_level, math.floor(uses / level_digs))
  end
  return 0
end

function toolranks.create_description(name, uses)
  local description = name
  local tooltype = toolranks.get_tool_type(description)
  local newdesc = S(
    "@1@2\n@3Level @4 @5\n@6@Node dug: @7",
    toolranks.colors.green,
    description,
    toolranks.colors.gold,
    toolranks.get_level(uses),
    S(tooltype),
    toolranks.colors.grey,
    (type(uses) == "number" and uses or 0)
  )
  return newdesc
end

function toolranks.new_afteruse(itemstack, user, node, digparams)
  local itemmeta = itemstack:get_meta()
  local itemdef = itemstack:get_definition()
  local itemdesc = itemdef.original_description
  local dugnodes = tonumber(itemmeta:get_string("dug")) or 0
  local lastlevel = tonumber(itemmeta:get_string("lastlevel")) or 0
  local most_digs = mod_storage:get_int("most_digs") or 0
  local most_digs_user = mod_storage:get_string("most_digs_user") or 0

  if digparams.wear > 0 then -- Only count nodes that spend the tool
    dugnodes = dugnodes + 1
    itemmeta:set_string("dug", dugnodes)
  end

  if dugnodes > most_digs then
    if most_digs_user ~= user:get_player_name() then -- Avoid spam.
      minetest.chat_send_all(S(
        "Most used tool is now a @1@2@3 owned by @4 with @5 uses.",
        toolranks.colors.green,
        itemdesc,
        toolranks.colors.white,
        user:get_player_name(),
        dugnodes
      ))
    end
    mod_storage:set_int("most_digs", dugnodes)
    mod_storage:set_string("most_digs_user", user:get_player_name())
  end

  if itemstack:get_wear() > 60136 then
    minetest.chat_send_player(user:get_player_name(), S("Your tool is about to break!"))
    minetest.sound_play("default_tool_breaks", {
      to_player = user:get_player_name(),
      gain = 2.0,
    })
  end

  local level = toolranks.get_level(dugnodes)
  if lastlevel < level then
    local levelup_text = S(
      "Your @1@2@3 just leveled up!",
      toolranks.colors.green,
      itemdesc,
      toolranks.colors.white
    )
    minetest.chat_send_player(user:get_player_name(), levelup_text)
    minetest.sound_play("toolranks_levelup", {
      to_player = user:get_player_name(),
      gain = 2.0,
    })

    local speed_multiplier = 1 + (level * level_multiplier * (max_speed - 1))
    local use_multiplier = 1 + (level * level_multiplier * (max_use - 1))
    local caps = table.copy(itemdef.tool_capabilities)

    caps.full_punch_interval = caps.full_punch_interval and (caps.full_punch_interval / speed_multiplier)
    caps.punch_attack_uses = caps.punch_attack_uses and (caps.punch_attack_uses * use_multiplier)

    for _,c in pairs(caps.groupcaps) do
      c.uses = c.uses * use_multiplier
      for i,t in ipairs(c.times) do
        c.times[i] = t / speed_multiplier
      end
    end
    itemmeta:set_tool_capabilities(caps)
  end

  itemmeta:set_string("lastlevel", level)
  itemmeta:set_string("description", toolranks.create_description(itemdesc, dugnodes))
  itemstack:add_wear(digparams.wear)
  return itemstack
end

-- Helper function
function toolranks.add_tool(name)
  local desc = ItemStack(name):get_definition().description
  minetest.override_item(name, {
    original_description = desc,
    description = toolranks.create_description(desc),
    after_use = toolranks.new_afteruse
  })
end

-- Sword
toolranks.add_tool("default:sword_wood")
toolranks.add_tool("default:sword_stone")
toolranks.add_tool("default:sword_steel")
toolranks.add_tool("default:sword_bronze")
toolranks.add_tool("default:sword_mese")
toolranks.add_tool("default:sword_diamond")

-- Pickaxe
toolranks.add_tool("default:pick_wood")
toolranks.add_tool("default:pick_stone")
toolranks.add_tool("default:pick_steel")
toolranks.add_tool("default:pick_bronze")
toolranks.add_tool("default:pick_mese")
toolranks.add_tool("default:pick_diamond")

-- Axe
toolranks.add_tool("default:axe_wood")
toolranks.add_tool("default:axe_stone")
toolranks.add_tool("default:axe_steel")
toolranks.add_tool("default:axe_bronze")
toolranks.add_tool("default:axe_mese")
toolranks.add_tool("default:axe_diamond")

-- Shovel
toolranks.add_tool("default:shovel_wood")
toolranks.add_tool("default:shovel_stone")
toolranks.add_tool("default:shovel_steel")
toolranks.add_tool("default:shovel_bronze")
toolranks.add_tool("default:shovel_mese")
toolranks.add_tool("default:shovel_diamond")
