local S = core.get_translator("block_league")
local FS = function(...) return core.formspec_escape(S(...)) end

local function get_formspec() end
local function get_weapon_details() end
local function calc_button() end
local function get_variant() end
local function equip() end


-- `curr_elem` è sempre l'elemento originale, le varianti son salvate in `curr_var`.
-- `curr_elem` è spogliato da `block_league:`, `curr_var` no. -- TODO: capire se possibile spogliare entrambi (o mettere prefisso a entrambi) per evitare confusione
-- `curr_var` equivale alla base se non c'è una variante selezionata.
-- `curr_equipped` serve per non chiamare ogni volta la funzione per ottenere le armi
-- e viene aggiornata quando l'equipaggiamento cambia
local p_equipping = {}      -- KEY: p_name; VALUE: {is_equipping = true/nil, (string) section, (string) curr_elem, (string) curr_var, (table) curr_equipped}



function block_league.show_profile(p_name)
  p_equipping[p_name] = {curr_elem = "", curr_equipped = table.key_value_swap(block_league.get_equipped_weapons(p_name)), section = ""}
  core.show_formspec(p_name, "block_league:profile", get_formspec(p_name))
end





----------------------------------------------
---------------FUNZIONI LOCALI----------------
----------------------------------------------

function get_formspec(p_name)
  local p_props   = core.get_player_by_name(p_name):get_properties()
  local p_weaps   = block_league.get_equipped_weapons(p_name)
  local p_skill   = block_league.get_equipped_skill(p_name)
  local skill_def = skills.get_def(p_skill)
  local info_section = {}
  local p_data = p_equipping[p_name]
  local elem = p_data.curr_elem
  local bl_curr_elem = "block_league:" .. elem

  -- calcolo contenuto da metter sulla destra
  if elem == "" then
    info_section = { "hypertext[0.3,1;4.48,7;elem_desc;<global size=15 halign=center valign=middle><i>" .. FS("Welcome to your Block League profile!") .. "\n"
      .. FS("Here you can change your equipment and learn about weapons and skills: select one from the panel on the left to know more about it") .. "\n\n"
      .. FS("More customisations will be possible in the future@1 (donations help)", "<action name=donate url=https://liberapay.com/Zughy><style color=#7a9090>") .. "</style></i>]"
    }

  else
    local upper, switch, body, button
    local weap = core.registered_items[bl_curr_elem]
    local skill = skills.get_def(bl_curr_elem)

    -- se è un'arma..
    if weap then
      weap = core.registered_items[p_data.curr_var] -- non posso prenderlo subito perché curr_var non cambia sempre, al contrario di bl_curr_elem

      local is_unlocked = block_league.has_variant(p_name, bl_curr_elem, p_data.curr_var)
      local locked_patina =  is_unlocked and "" or "^[multiply:#888888"
      local locked_txt = is_unlocked and "" or
          "hypertext[1.5,2.2;2.1,0.6;locked_txt;<global halign=center valign=middle><style color=#f66c77><b>" .. FS("Locked") .. "</b></style>]"
          .. "tooltip[locked_txt;" .. (weap._hint or "") .. "]"
      local preview

      if weap.mesh then
        local txtrs = table.concat(weap.tiles, locked_patina .. ",") .. locked_patina
        preview = weap.mesh and "model[0.8,1.5;3.5,2.2;weap_model;" .. weap.mesh .. ";" .. txtrs .. ";0,140;false;true]" .. locked_txt
      else
        preview = "image[2,1.7;1.5,1.5;" .. weap.wield_image .. locked_patina .. "]" .. locked_txt
      end

      local xp_info = ""
      local max_lv_col = ""

      if block_league.is_weapon_exp_enabled(bl_curr_elem) then
        local w_lv = block_league.get_weapon_lv(p_name, bl_curr_elem)
        local is_max_lv = w_lv == block_league.get_weapons_max_lv()
        local filled_xp_length, xp_txt, bar_col, padlock, padlock_tooltip

        if is_max_lv then
          filled_xp_length = 3.1
          xp_txt = S("MAX")
          bar_col = "#ffe446ff"
          padlock = "bl_gui_max.png"
          padlock_tooltip = ""
          max_lv_col = "<style color=#ffe446>"

        else
          local xp_curr = block_league.get_xp(p_name, bl_curr_elem)
          local xp_max = w_lv == 0 and 500 or 1000

          xp_txt = xp_curr .. "/" .. xp_max
          filled_xp_length = 3.1 * (xp_curr / xp_max)
          bar_col = "#57d0edff"

          if xp_curr == xp_max then
            padlock = "bl_gui_padlock_on.png"
            padlock_tooltip = block_league.get_licence_description(bl_curr_elem, w_lv+1)
          else
            padlock = "bl_gui_padlock.png^[hsl:0:0:-50"
            padlock_tooltip = FS("Fill out the bar first")
          end
        end

        xp_info = {
          "hypertext[0.4,3.54;0.7,0.7;elem_desc;<global size=14 valign=middle><i>Lv" .. w_lv .. "</i>]",
          "box[1,3.78;3.1,0.18;#313647ff]",
          "box[1,3.78;" .. filled_xp_length .. ",0.18;" .. bar_col .. "]",
          "tooltip[1,3.78;3.1,0.18;" .. xp_txt .. "]",
          "image[4.29,3.63;0.3,0.38;" .. padlock .. "]",
          "tooltip[4.29,3.63;0.3,0.38;" .. padlock_tooltip .. "]",
        }

        xp_info = table.concat(xp_info, "")
      end

      local var_name = weap._variant_name or ""
      local is_equipped = block_league.has_weapon_equipped(p_name, p_data.curr_var, true)
      local is_var_equipped = block_league.has_weapon_equipped(p_name, p_data.curr_var)

      upper = {
        "hypertext[0,0.35;5.08,0.8;elem_name;<global size=24 valign=middle halign=center><b>" .. max_lv_col .. core.formspec_escape(weap.description) .. "</b>]",
        "hypertext[0,0.7;5.08,0.9;elem_name;<global size=14 valign=middle halign=center><i><style color=#d5dfdf>" .. core.formspec_escape(var_name) .. "</i>]",
        preview,
        xp_info,
        "hypertext[0.3,4.1;4.48,0.9;elem_desc;<global size=15 halign=center valign=middle><style color=#abc0c0><i>" .. core.formspec_escape(weap._profile_description) .. "</i>]"
      }

      body = get_weapon_details(weap)
      button = calc_button(p_name, p_data, is_unlocked, is_equipped, is_var_equipped)
      switch = {
        "image_button[0.28,2.2;0.3,0.4;bl_gui_profile_arrow_left.png;skin_left;]",
        "image_button[4.25,2.2;0.3,0.4;bl_gui_profile_arrow_right.png;skin_right;]"
      }

    -- se è un'abilità..
    elseif skill then
      upper = {
        "hypertext[0,0.35;5.08,0.8;elem_name;<global size=24 valign=middle halign=center><b>" .. core.formspec_escape(skill.name) .. "</b>]",
        "image[2,1.7;1.5,1.5;bl_skill_" .. elem .. ".png]",
        "hypertext[0.3,4.1;4.48,4.3;elem_desc;<global size=15 halign=center><style color=#abc0c0><i>" .. core.formspec_escape(skill._profile_description) .. "</i>]"
      }
      switch = {}
      body = ""

      if bl_curr_elem ~= p_skill then
        button = "image_button[1.45,7.9;2.2,0.8;bl_gui_profile_button_equip.png;equip;" .. FS("EQUIP") .. "]"
      end
    end

    upper = table.concat(upper, "")
    switch = table.concat(switch,"")

    info_section = {
      upper,
      switch,
      "container[0.4,5.2]",
      body,
      "container_end[]",
      button
    }
  end

  local right_elem = table.concat(info_section, "")
  local curr_achvmt_amnt = #achvmt_lib.get_player_achievements(p_name, {section = "block_league"})
  local all_achvmt_amnt = achvmt_lib.get_amount({section = "block_league"})
  local p_lv = block_league.get_player_level(p_name)
  local lv_img = "bl_level_" .. p_lv .. ".png"

  -- corpo
  local formspec = {
    "formspec_version[4]",
    "size[19,9,true]",
    "no_prepend[]",
    "background[0,0;19,9;bl_gui_profile_bg.png]",
    "bgcolor[;true]",
    "style_type[item_image_button;border=false]",
    "style_type[image_button;border=false]",
    "style[equip,change,equip_locked,change_locked;font=bold]",
    "style[equip_locked,change_locked;textcolor=#666666]",
    "style[equip:hovered;fgimg=bl_gui_profile_button_equip_on.png]",
    "style[change:hovered;fgimg=bl_gui_profile_button_change_on.png]",
    "style[weap,wslot,sslot;font=mono;textcolor=#00000000]",
    "listcolors[#ffffff;#ffffff;#ffffff;#3153b7;#ffffff]",

    -- parte sinistra
    "model[0.08,0.8;5.08,3.6;chara;" .. p_props.mesh .. ";" .. table.concat(p_props.textures, ",") .. ";0,-150;false;true]",
    "container[0.49,5]",
    "image[0,0;1.05,1.05;bl_gui_profile_button_weap.png]]",
    "image[1.1,0;1.05,1.05;bl_gui_profile_button_weap.png]",
    "image[2.2,0;1.05,1.05;bl_gui_profile_button_weap.png]",
    "image[3.3,0;1.05,1.05;bl_gui_profile_button_skill.png]",
    "image_button[0.1,0.11;0.85,0.85;" .. (p_weaps[1] and core.registered_nodes[p_weaps[1]].inventory_image or "blank.png") .. ";weap;1]",
    "image_button[1.2,0.11;0.85,0.85;" .. (p_weaps[2] and core.registered_nodes[p_weaps[2]].inventory_image or "blank.png") .. ";weap;2]",
    "image_button[2.3,0.11;0.85,0.85;" .. (p_weaps[3] and core.registered_nodes[p_weaps[3]].inventory_image or "blank.png") .. ";weap;3]",
    "image_button[3.4,0.11;0.85,0.85;" .. skill_def.icon .. ";skill;]",
    "tooltip[skill;" .. skill_def.name .. "]",
    "container[0.05,1.55]",
    "image[0,0;0.8,0.8;" ..  lv_img .. "]",
    "tooltip[0,0;0.8,0.8;" .. S("Lv @1", p_lv) .. "]",
    "hypertext[0.9,0;3.25,0.8;pname_txt;<global size=24 valign=middle><b>" .. p_name .. "</b>]",
    "image[0.05,1;0.22,0.22;bl_gui_profile_infobox_trophies.png]",
    "image[0.05,1.8;0.22,0.3;bl_gui_profile_infobox_money.png]",
    "hypertext[0.4,0.94;3.35,0.4;pname_txt;<global size=14 valign=middle><b>" .. curr_achvmt_amnt .. "/" .. all_achvmt_amnt .. "</b>]",
    "hypertext[0.4,1.78;3.35,0.4;pname_txt;<global size=14 valign=middle><b>---</b>]",
    "container_end[]",
    "container_end[]",

    -- parte centrale
    "container[5.85,0.35]",
    "hypertext[0,0;3.35,0.9;weap_txt;<global size=24 valign=middle><style color=#5be7b1><b>" .. FS("Weapons") .. "</b>]",
    "image[0,1;1.05,1.05;bl_gui_profile_inv_weapon_unlocked.png]",
    "image[1.25,1;1.05,1.05;bl_gui_profile_inv_weapon_unlocked.png]",
    "image[2.5,1;1.05,1.05;bl_gui_profile_inv_weapon_unlocked.png]",
    "image[3.75,1;1.05,1.05;bl_gui_profile_inv_weapon_unlocked.png]",
    "image[5,1;1.05,1.05;bl_gui_profile_inv_weapon_unlocked.png]",
    "image[6.25,1;1.05,1.05;bl_gui_profile_inv_weapon_unlocked.png]",
    "image_button[0.1,1.11;0.85,0.85;bl_smg.png;wslot;smg]",
    "image_button[1.35,1.11;0.85,0.85;bl_sword.png;wslot;sword]",
    "image_button[2.6,1.11;0.85,0.85;bl_pixelgun.png;wslot;pixelgun]",
    "image_button[3.85,1.11;0.85,0.85;bl_peacifier.png;wslot;peacifier]",
    "image_button[5.10,1.11;0.85,0.85;bl_sentrygun.png;wslot;sentry_gun]",
    "image_button[6.35.10,1.11;0.85,0.85;bl_bomb.png;wslot;bomb]",
    "container[0,4.5]",
    "hypertext[0,0;3.35,0.9;weap_txt;<global size=24 valign=middle><style color=#5be7b1><b>" .. FS("Skills") .. "</b>]",
    "image[0,1;1.05,1.05;bl_gui_profile_inv_skill_unlocked.png]",
    "image[1.25,1;1.05,1.05;bl_gui_profile_inv_skill_unlocked.png]",
    "image[2.5,1;1.05,1.05;bl_gui_profile_inv_skill_locked.png]",
    "image_button[0.1,1.11;0.85,0.85;bl_skill_hp.png;sslot;hp]",
    "image_button[1.35,1.11;0.85,0.85;bl_skill_sp.png;sslot;sp]",
    "image_button[2.6,1.11;0.85,0.85;bl_skill_invisibility.png;sslot;invisibility]",
    --"image[2.6,1.11;0.85,0.85;bl_skill_invisibility.png]" ..
    --"hypertext[2.53,1.05;0.95,0.95;soon_tm;<global size=13 halign=center valign=middle><style color=#abc0c0><b>" .. S("Soon") .. "</b>]"

    "container_end[]",
    "container_end[]",

    -- parte destra
    "container[13.88,0]",
    "image_button[5.2,0;0.8,0.8;bl_gui_profile_close.png;close;;true;false;]",
    right_elem,
    "container_end[]"
  }

  return table.concat(formspec, "")
end



function get_weapon_details(weap)
  local action_y = 0
  local action1, action1_hold, action1_air, action2, action2_hold, action2_air

  -- azioni varie
  if weap.action1 then
    action1 = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_lmb.png]" ..
              "hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=14 valign=middle><i>" .. weap.action1._description .. "</i>]"
    action_y = action_y + 0.8
  end

  if weap.action1_hold then
    action1_hold = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_lmb_hold.png]" ..
              "hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=14 valign=middle><i>" .. weap.action1_hold._description .. "</i>]"
    action_y = action_y + 0.8
  end

  if weap.action1_air then
    action1_air = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_lmb_air.png]" ..
              "hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=14 valign=middle><i>" .. weap.action1_air._description .. "</i>]"
    action_y = action_y + 0.8
  end

  if weap.action2 then
    action2 = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_rmb.png]" ..
              "hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=14 valign=middle><i>" .. weap.action2._description .. "</i>]"
    action_y = action_y + 0.8
  end

  if weap.action2_hold then
    action2_hold = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_rmb_hold.png]" ..
              "hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=14 valign=middle><i>" .. weap.action2_hold._description .. "</i>]"
    action_y = action_y + 0.8
  end

  if weap.action2_air then
    action1_air = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_rmb_air.png]" ..
              "hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=14 valign=middle><i>" .. weap.action2_air._description .. "</i>]"
    action_y = action_y + 0.8
  end

  local ammo = ""

  if weap.weapon_type ~= "melee" and weap.magazine then
    local max_ammo = weap.limited_magazine and 0 or "--"
    local reload_time = weap.reload_time == -1 and "---" or weap.reload_time

    ammo = table.concat({
      "image[0,1.6;0.4,0.4;bl_gui_profile_weapon_magazine.png]",
      "image[3,1.6;0.4,0.4;bl_gui_profile_weapon_reload.png]",
      "hypertext[0.6,1.53;1.1,0.6;elem_desc;<global size=16 valign=middle><i>" .. weap.magazine .. "  / " .. max_ammo .. "</i>]",
      "hypertext[3.6,1.53;1,0.6;elem_desc;<global size=16 valign=middle><i>" .. reload_time .. "</i>]"
    })
  end

  local attributes = table.concat({
    action1       or "",
    action1_hold  or "",
    action1_air   or "",
    action2       or "",
    action2_hold  or "",
    action2_air   or "",
    ammo
  }, "")

  return attributes
end



-- TODO da estendere ad abilità in futuro
function calc_button(p_name, p_data, is_unlocked, is_equipped, is_equipped_variant)
  local button = ""

  if p_data.is_equipping then
    button =  "image[-13.88,0;19,9;bl_gui_profile_bg_mask.png^[opacity:160]" ..
              "hypertext[0.3,7.9;4.48,0.9;equip_desc;<global size=14 halign=center><style color=#abc0c0>" .. FS("Choose the slot where to equip the weapon") .. "]"
  else
    if is_unlocked then
      if not is_equipped or is_equipped_variant then
        button = "image_button[1.45,7.9;2.2,0.8;bl_gui_profile_button_equip.png;equip;" .. FS("EQUIP") .. "]"
      else
        button = "image_button[1.45,7.9;2.2,0.8;bl_gui_profile_button_change.png;change;" .. FS("CHANGE") .. "]"
      end
    else
      button = "image_button[1.45,7.9;2.2,0.8;bl_gui_profile_button_equip.png^[multiply:#777777;equip_locked;" .. FS("EQUIP") .. "]"
    end
  end

  -- TODO per quando si potranno rimuovere armi, aggiungere anche tasto UNEQUIP di fianco
  --[[if block_league.has_weapon_equipped(p_name, bl_curr_elem) then
    button = "image_button[1.45,7.9;2.2,0.8;bl_gui_profile_button_unequip.png;unequip;" .. FS("UNEQUIP") .. "]"
  else
    button = "image_button[1.45,7.9;2.2,0.8;bl_gui_profile_button_equip.png;equip;" .. FS("EQUIP") .. "]"
  end]]

  return button
end



function get_variant(p_data, bl_curr_elem)
  for ww_name, _ in pairs(p_data.curr_equipped) do
    local wweap = core.registered_items[ww_name]

    if wweap._variant_of and wweap._variant_of == bl_curr_elem then
      return ww_name
    end
  end

  return bl_curr_elem
end



function equip(type, p_name, p_data, elem_technical, slot)
  if type == "weapon" then
    block_league.equip_weapon(p_name, elem_technical, slot)
    p_data.curr_equipped = table.key_value_swap(block_league.get_equipped_weapons(p_name))
  else
    block_league.equip_skill(p_name, elem_technical)
  end

  audio_lib.play_sound("bl_gui_equip_confirm", {to_player = p_name})
end





----------------------------------------------
---------------GESTIONE CAMPI-----------------
----------------------------------------------

core.register_on_player_receive_fields(function(player, formname, fields)
  if formname ~= "block_league:profile" then return end

  local p_name = player:get_player_name()
  local p_data = p_equipping[p_name]
  local is_equipping = p_data.is_equipping

  if fields.quit and not is_equipping then return end -- non chiudere se sto equipaggiando e premo Esc

  local bl_curr_elem = "block_league:" .. p_data.curr_elem
  local elem_technical = p_data.curr_var or bl_curr_elem -- al contrario di `curr_elem`, questo prende eventuale variante. TODO: vedere quando inserite abilità se ha senso

  if fields.close then
    core.close_formspec(p_name, "block_league:profile")
    p_data = nil
    return
  end

  -- sezione (non cambiare se clicco sulla casella di un'arma)
  if fields.info or fields.sslot then
    p_data.section = "info"
  elseif fields.skins then
    p_data.section = "skins"
  end

  if is_equipping and not fields.weap then
    p_data.is_equipping = nil
  end

  if fields.weap then
    local slot = tonumber(fields.weap)

    if not type(slot) == "number" or slot < 1 or slot > 3 then return end -- sanity check

    if is_equipping then
      if not weapons_lib.is_weapon(elem_technical) or not block_league.has_weapon(p_name, bl_curr_elem) then return end

      equip("weapon", p_name, p_data, elem_technical, slot)
      p_data.is_equipping = nil

    else
      local p_w_name = block_league.get_equipped_weapons(p_name)[slot]

      if not p_w_name then
        p_data.curr_elem = ""
      else
        local p_weap = core.registered_items[p_w_name]

        -- prendi l'originale x curr_elem
        if p_weap._variant_of then
          p_w_name = p_weap._variant_of
        end

        local curr_elem = string.sub(p_w_name, 14, -1)

        p_data.curr_elem = curr_elem
        p_data.curr_var = get_variant(p_data, "block_league:" .. curr_elem)
      end
    end

  elseif fields.skill then
    p_data.curr_elem = string.sub(block_league.get_equipped_skill(p_name), 14, -1)
    p_data.curr_var = block_league.get_equipped_skill(p_name)
  elseif fields.wslot then
    local new_elem_technical = "block_league:" .. fields.wslot

    p_data.curr_elem = fields.wslot
    p_data.curr_var = get_variant(p_data, new_elem_technical)

  elseif fields.sslot then
    p_data.curr_elem = fields.sslot
    p_data.curr_var = "block_league:" .. fields.sslot

  elseif fields.skin_left or fields.skin_right then
    local weap = core.registered_items[elem_technical]

    -- se è una variante, prendi l'originale
    if weap._variant_of then
      weap = core.registered_items[weap._variant_of]
    end

    local variants = weap._variants
    local variants_amnt = 0

    if core.check_player_privs(p_name, "blockleague_admin") then
      variants_amnt = #variants
    else
      for _, var_name in ipairs(variants) do
        if not core.registered_items[var_name]._staff_only then
          variants_amnt = variants_amnt +1
        end
      end
    end

    local mv_amount = fields.skin_left and -1 or 1
    local id

    if bl_curr_elem == p_data.curr_var then
      id = 0
    else
      for v_id, var_name in ipairs(variants) do
        if var_name == p_data.curr_var then
          id = v_id
          break
        end
      end
    end

    local new_id = id + mv_amount

    if new_id < 0 then
      new_id = variants_amnt
    elseif new_id > variants_amnt then
      new_id = 0
    end

    p_data.curr_var = variants[new_id] or bl_curr_elem

    core.show_formspec(p_name, "block_league:profile", get_formspec(p_name))

  elseif fields.change then
    local weap = core.registered_items[elem_technical]

    if weap then
      if not block_league.has_variant(p_name, weap._variant_of or bl_curr_elem, elem_technical) then return end -- validazione

      for slot, ww_name in ipairs(block_league.get_equipped_weapons(p_name)) do
        ww_name = core.registered_items[ww_name]._variant_of or ww_name
        if ww_name == bl_curr_elem then
          equip("weapon", p_name, p_data, p_data.curr_var or bl_curr_elem, slot)
          break
        end
      end

    else
      -- TODO per quando abilità avranno varianti
    end

  elseif fields.equip then
    local weap = core.registered_items[elem_technical]

    if weap then
      if block_league.has_weapon(p_name, weap._variant_of or bl_curr_elem) then
        p_data.is_equipping = true
      end

    else
      equip("skill", p_name, p_data, elem_technical)
    end
  end

  core.show_formspec(p_name, "block_league:profile", get_formspec(p_name))
end)