local MT = minetest
local vMod = vm_lighting_wand
local players = {}

math.randomseed(os.time())
local get_random = function()
  return math.random(math.random(1000, 14999), math.random(15000, 999999))
end

local get_formname = function(player)
  return vMod.tool .. ":" .. vMod.get_gui_player(player)
end

local bar = {
  bg = vMod.modname .. "_bar_bg.png^[lowpart:",
  yellow = vMod.modname .. "_bar_yellow.png",
  green = vMod.modname .. "_bar_green.png"
}
local progress_bar = function(fsb, x, y, w, h, percent, text, color)
  fsb:image(fsb:slot(x), fsb:slot(y), w, h, bar.bg .. (percent) .. ":" .. bar[color])
  fsb:tooltip(fsb:slot(x), fsb:slot(y), w, h, text .. "\n\n" .. MT.colorize("goldenrod", percent .. "%"))
end

local add_stat = function(fsb, x, y, name, value, info)
  info = info and " " .. MT.colorize("darkslategrey", info) or ""
  fsb:label(fsb:slot(x) + fsb.padding, fsb:slot(y) + fsb.padding, MT.colorize("grey", name))
  fsb:label(fsb:slot(x + 1.5), fsb:slot(y) + fsb.padding, MT.colorize("darkcyan", value) .. info)
end

local function commas(n) -- credit http://richard.warburton.it
  local left, num, right = string.match(n, "^([^%d]*%d)(%d*)(.-)$")
  return left .. (num:reverse():gsub("(%d%d%d)", "%1,"):reverse()) .. right
end

-- Wands formspec
vMod.open_gui = function(player, id)
  --
  local fsb = vMod.fsbuilder:new({ height = 11.65, width = 10.5 })

  -- If a id was given then check it
  if not player or id and vMod.get_gui_player(player) ~= id then
    vMod.close_gui(player)
    return
  end

  local player_name = player:get_player_name()
  local detached_name = vMod.detached_name(player_name)

  -- now set a id to this player
  players[player_name] = get_random()

  local is_creative_mode = vMod.is_creative_mode(player)
  local level = vMod.get_level(player)
  local levels = vMod.get_all_levels()
  local power = vMod.get_power(player)
  local max_power = vMod.get_max_power()
  local next_level = levels[level.id + 1] and levels[level.id + 1].amount_start or max_power
  local max_percent = vMod.round((power / max_power) * 100, 2)
  local level_percent = vMod.round(((power - level.amount_start) / (next_level - level.amount_start)) * 100, 2)

  -- Title
  is_creative_mode = is_creative_mode and " :: " .. MT.colorize("deeppink", "creative mode") or ""
  fsb:label(fsb:slot(0.125), fsb:slot(0.15), MT.colorize("limegreen", "Lighting Wand") .. is_creative_mode)
  -- Level
  fsb:label(fsb:slot(0.25), fsb:slot(0.75), MT.colorize("goldenrod", level.name))
  -- Power
  add_stat(fsb, 0.25, 1.50, "Power", commas(tostring(power)))
  -- Range
  add_stat(fsb, 0.25, 2.00, "Range", level.max_range)
  -- Efficiency
  add_stat(fsb, 0.25, 2.50, "Efficiency", (level.fuel_efficiency * 100) .. "%")
  -- Cost per use
  add_stat(fsb, 0.25, 3.00, "Cost", level.cost_per_use, "per use")
  -- Cost per node
  add_stat(fsb, 0.25, 3.50, "", level.cost_per_node, "per node travelled")

  -- Show power % needed to level up/max
  progress_bar(fsb, 7.1, 0.5, 0.3, 4.75, level_percent, "Level Progress", "yellow")
  -- Show max power % bar
  progress_bar(fsb, 7.7, 0.5, 0.3, 4.75, max_percent, "Total Power", "green")

  fsb:button(
    fsb:slot(5.6),
    fsb:slot(0.5),
    1,
    1,
    "toggle_sound",
    vMod.get_player_effects(player).sound == "true" and "on" or "off"
  )
  fsb:tooltip(fsb:slot(5.6), fsb:slot(0.5), 1, 1, "Toggle Sound")

  fsb:button(
    fsb:slot(5.6),
    fsb:slot(1.5),
    1,
    1,
    "toggle_particles",
    vMod.get_player_effects(player).particles == "true" and "on" or "off"
  )
  fsb:tooltip(fsb:slot(5.6), fsb:slot(1.5), 1, 1, "Toggle particles")

  -- detached fuel slot
  fsb:list("detached:" .. detached_name, vMod.detached_list, fsb:slot(5.6), fsb:slot(3), 1, 1)
  -- slot tooltip
  fsb:tooltip(fsb:slot(5.6), fsb:slot(3), 1, 1, "Fuel Input")
  -- Players inventory
  fsb:get_player_list(fsb.padding, 4.75)

  fsb:listring("current_player", "main")
  fsb:listring("detached:" .. detached_name, vMod.detached_list)

  --Show the formspec
  MT.show_formspec(player_name, get_formname(player), fsb:get_form_string())
end

vMod.get_gui_player = function(player)
  if not player then
    return nil
  end
  return players[player:get_player_name()] or nil
end

vMod.close_gui = function(player)
  if not player then
    return
  end
  local player_name = player:get_player_name()
  MT.close_formspec(player_name, get_formname(player))
  players[player_name] = nil
  return
end

MT.register_on_leaveplayer(
  function(player)
    players[player:get_player_name()] = nil
  end
)

local string_starts = function(s, prefix)
  return string.sub(s, 1, string.len(prefix)) == prefix
end

MT.register_on_player_receive_fields(
  function(player, formname, fields)
    -- nothing intresting skip it
    if not player or not string_starts(formname, vMod.tool) then
      return
    end

    -- its just a quit?
    if fields.quit ~= nil then
      vMod.close_gui(player)
      return
    end

    -- Take a closer look and ensure the formname matches the expected name
    if get_formname(player) ~= formname then
      vMod.close_gui(player)
      return
    end

    local effects = vMod.get_player_effects(player)
    if fields.toggle_sound ~= nil then
      local sound = effects.sound == "true" and "false" or "true"
      vMod.set_player_effects(player, "sound", sound)
    end
    if fields.toggle_particles ~= nil then
      local particles = effects.particles == "true" and "false" or "true"
      vMod.set_player_effects(player, "particles", particles)
    end
    vMod.open_gui(player, vMod.get_gui_player(player))
  end
)
