local S = core.get_translator("block_league")

local equip = {}              -- KEY: p_name; VALUE { weapons = { 1 = w_name, 2 = w_name, 3 = w_name }, skill = s_name }
local unlocked_weapons = {}   -- KEY: p_name; VALUE: { w_name = { var_name1 = true, var_name2 = true } }
local unlocked_skills = {}    -- TODO in futuro come ^

local DEFAULT_WEAPONS = {
  ['block_league:smg'] = {},
  ['block_league:sword'] = {},
  ['block_league:pixelgun'] = {},
  ['block_league:peacifier'] = {},
  ['block_league:sentry_gun'] = {},
  ['block_league:bomb'] = {},
}

-- le tratto in maniera diversa perché tengo traccia dalla mod `skills`
local DEFAULT_SKILLS = {
  "block_league:hp",
  "block_league:sp",
  "block_league:invisibility",
}



-- non esporre
function block_league.load_equip(p_name, curr_equip, weapons)
  equip[p_name] = curr_equip
  unlocked_weapons[p_name] = weapons
end



-- non esporre
function block_league.unload_equip(p_name)
  equip[p_name] = nil
  unlocked_weapons[p_name] = nil
end



-- non esporre
function block_league.unlock_default_weapons(p_name)
  if unlocked_weapons[p_name] then return end

  equip[p_name] = {}
  unlocked_weapons[p_name] = table.copy(DEFAULT_WEAPONS)

  return table.copy(unlocked_weapons[p_name])
end



-- non esporre
function block_league.unlock_default_skills(p_name)
  for _, sk_name in ipairs(DEFAULT_SKILLS) do
    p_name:unlock_skill(sk_name)
    p_name:get_skill(sk_name):disable()
  end
end





----------------------------------------------
---------------------CORE---------------------
----------------------------------------------

function block_league.equip_weapon(p_name, w_name, slot)
  local p_weaps = equip[p_name].weapons
  local w2_name = p_weaps[slot]

  if not weapons_lib.is_weapon(w_name) or w_name == w2_name then return end

  local weap = core.registered_items[w_name]

  -- se non ha l'arma/variante, annulla
  if (not weap._variant_of and not block_league.has_weapon(p_name, w_name))
     or (weap._variant_of and not block_league.has_variant(p_name, weap._variant_of, w_name)) then return end

  local w_name_orig = weap._variant_of or w_name
  local w_prev_slot

  for i, ww_name in pairs(p_weaps) do
    local ww_name_orig = core.registered_items[ww_name]._variant_of or ww_name
    if w_name_orig == ww_name_orig then
      w_prev_slot = i
    end
  end

  equip[p_name].weapons[slot] = w_name

  if slot ~= w_prev_slot then
    if w2_name and w_prev_slot then
      p_weaps[w_prev_slot] = w2_name
    elseif w_prev_slot then
      p_weaps[w_prev_slot] = nil
    end
  end

  block_league.update_storage(p_name, "equip_w", p_weaps)
end



function block_league.equip_skill(p_name, s_name)
  if not skills.does_skill_exist(s_name) or s_name == equip[p_name].skill then return end

  equip[p_name].skill = s_name
  block_league.update_storage(p_name, "equip_s", s_name)
end



function block_league.unequip(p_name, w_name)
  local p_weaps = equip[p_name].weapons

  for i, ww_name in pairs(p_weaps) do
    if w_name == ww_name then
      p_weaps[i] = nil
      block_league.update_storage(p_name, "equip_w", p_weaps)
      return
    end
  end
end



-- TODO idem per abilità
function block_league.unlock_weapon(p_name, w_name)
  if not weapons_lib.is_weapon(w_name) then
    return false, S("@1 is not a weapon!", w_name)
  end

  block_league.try_to_load_player(p_name)
  local p_unlocked = unlocked_weapons[p_name]
  local w_desc = core.registered_items[w_name].description

  if not p_unlocked then
    return false, S("There is no player in memory called @1!", p_name)
  end

  if p_unlocked[w_name] then
    return false, S("Player @1 has already got weapon @2!", p_name, w_desc)
  end

  p_unlocked[w_name] = {}
  block_league.update_storage(p_name, "weapon", w_name)

  return true, S("Weapon @1 successfully unlocked for @2", core.registered_items[w_name].description, p_name)
end



function block_league.unlock_weapon_variant(p_name, w_name, var_name)
  if not weapons_lib.is_weapon(w_name) then
    return false, S("@1 is not a weapon!", w_name)
  end

  local w_desc = core.registered_items[w_name].description
  local original = core.registered_items[var_name]

  if not original or not original._variant_of == w_name then
    return false, S("There's no variant of weapon \"@1\" called \"@2\"!", w_desc, var_name)
  end

  block_league.try_to_load_player(p_name)
  local p_unlocked = unlocked_weapons[p_name]

  if not p_unlocked then
    return false, S("There is no player in memory called @1!", p_name)
  end

  if not p_unlocked[w_name] then
    return false, S("Player @1 hasn't got weapon @2!", p_name, w_desc)
  end

  local var_desc = core.registered_items[var_name].description

  if p_unlocked[w_name][var_name] then
    return false, S("Player @1 has already got variant \"@2\" of weapon \"@3\"!", p_name, var_desc, w_desc)
  end

  p_unlocked[w_name][var_name] = true
  block_league.update_storage(p_name, "weapon_var", w_name .. "@" .. var_name)

  return true, S("Variant \"@1\" of weapon \"@2\" successfully unlocked for @3", var_desc, w_desc, p_name)
end



function block_league.remove_weapon(p_name, w_name)
  if not weapons_lib.is_weapon(w_name) then
    return false, S("@1 is not a weapon!", w_name)
  end

  block_league.try_to_load_player(p_name)
  local p_unlocked = unlocked_weapons[p_name]
  local w_desc = core.registered_items[w_name].description

  if not p_unlocked then
    return false, S("There is no player in memory called @1!", p_name)
  end

  if not p_unlocked[w_name] then
    return false, S("Player @1 hasn't got weapon @2!", p_name, w_desc)
  end

  p_unlocked[w_name] = nil
  block_league.update_storage(p_name, "weapon", w_name, true)

  return true, S("Weapon @1 successfully removed from @2", w_desc, p_name)
end



function block_league.remove_weapon_variant(p_name, w_name, var_name)
  if not weapons_lib.is_weapon(w_name) then
    return false, S("@1 is not a weapon!", w_name)
  end

  local w_desc = core.registered_items[w_name].description
  local original = core.registered_items[var_name]

  if not original or not original._variant_of == w_name then
    return false, S("There's no variant of weapon \"@1\" called \"@2\"!", w_desc, var_name)
  end

  block_league.try_to_load_player(p_name)
  local p_unlocked = unlocked_weapons[p_name]

  if not p_unlocked then
    return false, S("There is no player in memory called @1!", p_name)
  end

  if not p_unlocked[w_name] then
    return false, S("Player @1 hasn't got weapon @2!", p_name, w_desc)
  end

  local var_desc = core.registered_items[var_name].description

  if not p_unlocked[w_name][var_name] then
    return false, S("Player @1 hasn't got variant \"@2\" of weapon \"@3\"!", p_name, var_desc, w_desc)
  end

  p_unlocked[w_name][var_name] = nil
  block_league.update_storage(p_name, "weapon_var", w_name .. "@" .. var_name, true)

  return true, S("Variant \"@1\" of weapon \"@2\" successfully removed from @3", var_desc, w_desc, p_name)
end





----------------------------------------------
--------------------UTILS---------------------
----------------------------------------------

function block_league.has_weapon_equipped(p_name, w_name, check_for_variants)
  if not equip[p_name] then return end

  if not check_for_variants then
    for _, ww_name in pairs(equip[p_name].weapons) do
      if w_name == ww_name then
        return true
      end
    end

  else
    local weap = core.registered_items[w_name]
    local orig_name = weap._variant_of or w_name

    for _, ww_name in pairs(equip[p_name].weapons) do
      local wweap = core.registered_items[ww_name]
      local orig_name2 = wweap._variant_of or ww_name

      if orig_name == orig_name2 then
        return true
      end
    end
  end
end



function block_league.has_weapon(p_name, w_name)
  block_league.try_to_load_player(p_name)
  return unlocked_weapons[p_name] and unlocked_weapons[p_name][w_name]
end



function block_league.has_variant(p_name, w_name, var_name)
  block_league.try_to_load_player(p_name)

  if not unlocked_weapons[p_name] or not unlocked_weapons[p_name][w_name] then return end

  return w_name == var_name and true or unlocked_weapons[p_name][w_name][var_name]
end





----------------------------------------------
-----------------GETTERS----------------------
----------------------------------------------

function block_league.get_original_weapon(w_name)
  return core.registered_items[w_name]._variant_of or w_name
end



function block_league.get_equipped_weapons(p_name, originals_only)
  block_league.try_to_load_player(p_name)

  if not originals_only then
    return equip[p_name].weapons

  else
    local weaps = {}
    for i, w_name in ipairs(equip[p_name].weapons) do
      weaps[i] = block_league.get_original_weapon(w_name)
    end

    return weaps
  end
end



function block_league.get_equipped_skill(p_name)
  return equip[p_name].skill
end



-- TODO: get_unlocked_skills
function block_league.get_unlocked_weapons(p_name)
  block_league.try_to_load_player(p_name)
  local p_unlocked = unlocked_weapons[p_name]

  if not p_unlocked then return end

  local unlocked_weaps = {}

  for w_name, _ in pairs(p_unlocked) do
    unlocked_weapons[#unlocked_weapons+1] = w_name
  end

  return unlocked_weaps
end



function block_league.get_unlocked_weapon_variants(p_name, w_name)
  if not weapons_lib.is_weapon(w_name) then return end

  block_league.try_to_load_player(p_name)
  local p_unlocked = unlocked_weapons[p_name]

  if not p_unlocked or not p_unlocked[w_name] then return end

  return table.copy(p_unlocked[w_name])
end
