local function give_cheat_items(player)
  --- @diagnostic disable-next-line: missing-fields
  util.insert_safe(player, {
    ["electric-energy-interface"] = 10,
    ["infinity-chest"] = 10,
    ["infinity-pipe"] = 10,
    ["heat-interface"] = 10,
    ["substation"] = 10,
  })
end

local function set_tag(element, key, value)
  local tags = element.tags
  tags[key] = value
  element.tags = tags
end

local function set_window_content(content_flow, question)
  content_flow.label.caption = {"gui-sandbox." .. question}
  set_tag(content_flow.buttons_flow.no_button, "sandbox_question", question)
  set_tag(content_flow.buttons_flow.yes_button, "sandbox_question", question)
  content_flow.parent.parent.force_auto_center()
end

local function create_questionnaire_gui(player)
  local window = player.gui.screen.add{type = "frame", name = "sandbox_window", caption = {"gui-sandbox.title"}}
  local content_pane = window.add{type = "frame", name = "content_pane", style = "inside_shallow_frame_with_padding", direction = "vertical"}
  -- We can't change flow properties from the frame so we need a wrapper flow...
  local content_flow = content_pane.add{type = "flow", name = "content_flow", style = "two_module_spacing_vertical_flow", direction = "vertical"}
  content_flow.style.horizontal_align = "center"
  content_flow.add{type = "label", name = "label", style = "bold_label"}
  local buttons_flow = content_flow.add{type = "flow", name = "buttons_flow", style = "player_input_horizontal_flow"}
  buttons_flow.add{type = "button", name = "no_button", caption = {"gui.no"}, tags = {sandbox_answer = "no"}}
  local yes_button = buttons_flow.add{type = "button", name = "yes_button", caption = {"gui.yes"}, tags = {sandbox_answer = "yes"}}
  yes_button.focus()

  if player.input_method == defines.input_method.game_controller then
    player.opened = window
  end

  set_window_content(content_flow, "research-all-technologies")
end

local function on_player_created(e)
  local player = game.get_player(e.player_index)
  -- To appease LuaLS
  if not player then
    return
  end

  if not storage.asked_questionnaire then
    create_questionnaire_gui(player)
    storage.asked_questionnaire = true
    return
  end

  if storage.enabled_cheat_mode then
    player.cheat_mode = true
  end
  if storage.gave_cheat_items then
    give_cheat_items(player)
  end
end

local function on_gui_click(e)
  local tags = e.element.tags
  local question, answer = tags.sandbox_question, tags.sandbox_answer
  if not question or not answer then
    return
  end
  local player = game.get_player(e.player_index)
  -- To appease LuaLS
  if not player then
    return
  end
  if question == "research-all-technologies" then
    if answer == "yes" then
      player.force.research_all_technologies()
    end
    set_window_content(e.element.parent.parent, "enable-cheat-mode")
  elseif question == "enable-cheat-mode" then
    if answer == "yes" then
      for _, player in pairs(game.players) do
        player.cheat_mode = true
      end
      storage.enabled_cheat_mode = true
    end
    set_window_content(e.element.parent.parent, "give-cheat-items")
  elseif question == "give-cheat-items" then
    if answer == "yes" then
      for _, player in pairs(game.players) do
        give_cheat_items(player)
      end
      storage.gave_cheat_items = true
    end
    set_window_content(e.element.parent.parent, "enable-always-day")
  elseif question == "enable-always-day" then
    if answer == "yes" then
      for _, surface in pairs(game.surfaces) do
        surface.always_day = true
      end
      storage.set_always_day = true
    end
    player.gui.screen.sandbox_window.destroy()
  end
end

local function on_gui_closed(e)
  if not e.element or e.element.name ~= "sandbox_window" then
    return
  end

  local player = game.get_player(e.player_index)
  if not player then return end -- To appease LuaLS

  if player.input_method == defines.input_method.game_controller then
    player.opened = e.element
  end
end

local function on_player_input_method_changed(e)
  local player = game.get_player(e.player_index)
  -- To appease LuaLS
  if not player then
    return
  end

  local sandbox_window = player.gui.screen.sandbox_window
  if not sandbox_window then
    return
  end

  if player.input_method == defines.input_method.game_controller then
    player.opened = sandbox_window
  elseif player.opened == sandbox_window then
    player.opened = nil
  end
end

local function on_surface_created(e)
  if storage.set_always_day then
    game.get_surface(e.surface_index).always_day = true
  end
end

local sandbox_gui = {}

sandbox_gui.events = {
  [defines.events.on_player_created] = on_player_created,
  [defines.events.on_gui_click] = on_gui_click,
  [defines.events.on_gui_closed] = on_gui_closed,
  [defines.events.on_player_input_method_changed] = on_player_input_method_changed,
  [defines.events.on_surface_created] = on_surface_created,
}

return sandbox_gui
