local S = minetest.get_translator("block_league")

local SPEED_LOW = block_league.SPEED * block_league.SHOOT_SPEED_MULTIPLIER



function block_league.util_weapon_use_check(player)
  local p_name = player:get_player_name()
  if not arena_lib.is_player_playing(p_name, "block_league") then return true end

  local arena = arena_lib.get_arena_by_player(p_name)

  if arena.weapons_disabled or player:get_meta():get_int("bl_death_delay") == 1 then
    return end

  block_league.remove_immunity(player)
  return true
end



function block_league.util_on_can_alter_speed(p_name)
  if not arena_lib.is_player_playing(p_name, "block_league") then return true end

  local arena = arena_lib.get_arena_by_player(p_name)
  return arena.players[p_name].stamina > 0
end



function block_league.util_update_mag_hud(p_name, w_name)
  if not arena_lib.is_player_playing(p_name, "block_league") then return end

  local arena = arena_lib.get_arena_by_player(p_name)
  block_league.HUD_weapons_update(arena, p_name, w_name)
end



function block_league.util_on_hit(hitter, target, weapon, action, hit_point, damage, knockback)
  local p_name = hitter:get_player_name()
  local is_target_player = target:is_player()
  local t_name = is_target_player and target:get_player_name() or target:get_luaentity().name

  if not arena_lib.is_player_playing(p_name, "block_league")
     or (is_target_player and (not arena_lib.is_player_playing(t_name, "block_league")
     or target:get_meta():get_int("bl_immunity") == 1))
    then return 0 end

  local arena = arena_lib.get_arena_by_player(p_name)
  local self_hit = p_name == t_name

  if arena_lib.is_player_in_same_team(arena, p_name, t_name) and not self_hit then return 0 end -- TODO: in futuro per bomba usa proprietà personalizzata arma tipo _can_dmg_team

  local is_critical = hit_point and hit_point.y - target:get_pos().y > 1.275 -- TODO: la spada non lo passa

  if is_critical then
    damage = damage * 1.5
    block_league.HUD_critical_show(p_name)
    audio_lib.play_sound("bl_voice_critical", {to_player = p_name})
  end

  if self_hit then
    damage = damage / 2
  end

  if is_target_player then
    local dmg_table = arena.players[t_name].dmg_received

    dmg_table[p_name] = {
      timestamp = arena.current_time,
      dmg = arena.current_time > dmg_table[p_name].timestamp - 5 and dmg_table[p_name].dmg + damage or damage,
      weapon = weapon.name
    }
  end

  return damage, knockback
end



function block_league.util_on_after_hit(hitter, weapon, objects_hit, total_damage)
  local p_name = hitter:get_player_name()
  if not arena_lib.is_player_playing(p_name, "block_league") then return end

  local arena = arena_lib.get_arena_by_player(p_name)

  if arena.mode == 0 then return end  -- nessun prestigio nel tutorial

  -- aggiorno danno totale inflitto ed eventualmente aumento i punti
  local p_data = arena.players[p_name]
  local prev_dmg_dealt = p_data.dmg_dealt
  local dmg_dealt = prev_dmg_dealt + total_damage
  local dmg_points = math.floor(dmg_dealt/10) - math.floor(prev_dmg_dealt/10)

  if dmg_points > 0 then
    p_data.points = p_data.points + dmg_points
    block_league.HUD_infopanel_update_points(arena, p_data.teamID)
    block_league.HUD_spectate_update(arena, p_name, "points")
  end

  p_data.dmg_dealt = dmg_dealt

  local killed_players = 0

  for _, t_data in pairs(objects_hit) do
    if t_data.type == "player" and t_data.ref:get_hp() <= 0 then
      block_league.kill(arena, weapon, hitter, t_data.ref)
      killed_players = killed_players + 1
    else
      -- TEMP check, see https://github.com/minetest/minetest/issues/13297
      if not t_data.type == "entity" or t_data.ref:get_luaentity() then
        -- non riprodurre suono se colpisci unə compagnə di squadra
        if not t_data.type == "player" or not arena_lib.is_player_in_same_team(arena, p_name, t_data.ref:get_player_name()) then
          arena_lib.sound_play(p_name, "bl_hit")
        else
          arena_lib.sound_play(p_name, "bl_hit_deny")
        end
      end
    end
  end

  -- medaglie
  --
  -- eventuale medaglia doppia/tripla uccisione
  if killed_players > 1 then
    if killed_players == 2 then
      block_league.show_medal(p_name, "bl_medal_doublekill.png")
    elseif killed_players >= 3 then
      block_league.show_medal(p_name, "bl_medal_triplekill.png")
    end

    arena_lib.send_message_in_arena(arena, "both",minetest.colorize("#d7ded7", S("@1 has killed @2 players in a row!", minetest.colorize("#eea160", p_name), killed_players)))
  end

  -- prestigi
  --
  -- niente prestigi se non ci sono almeno 6 persone
  if arena.players_amount < 6 then return end

  --TODO
  --[[
    if killed_players >= 2 and weapon.name == "block_league:pixelgun" then
      achvmt_lib.award("block_league:quellochesarà", p_name)
    end
  ]]
end



function block_league.util_on_end_melee(p_name, w_name)
  if not arena_lib.is_player_playing(p_name, "block_league") then return end

  local arena = arena_lib.get_arena_by_player(p_name)
  block_league.HUD_weapons_update(arena, p_name, w_name, true)
end



function block_league.util_on_recovery_end(player, weapon, action)
  local p_name = player:get_player_name()
  if not arena_lib.is_player_playing(p_name, "block_league") then return end

  local arena = arena_lib.get_arena_by_player(p_name)

  if weapon.weapon_type == "melee" then
    block_league.HUD_weapons_update(arena, p_name, weapon.name, false)
  end

  if action.physics_override then
    if player:get_physics_override().speed == block_league.SPEED and
       arena.players[p_name].stamina <= 0 then
      player:set_physics_override({speed = SPEED_LOW})
    end
  end
end



function block_league.util_on_reload(p_name, w_name)
  if not arena_lib.is_player_playing(p_name, "block_league") then return end

  local arena = arena_lib.get_arena_by_player(p_name)
  block_league.HUD_weapons_update(arena, p_name, w_name, true)
end



function block_league.util_on_reload_end(p_name, w_name)
  if not arena_lib.is_player_playing(p_name, "block_league") then return end

  local arena = arena_lib.get_arena_by_player(p_name)
  block_league.HUD_weapons_update(arena, p_name, w_name, false)
end