// Copyright 2017-2023, Nicholas Sharp and the Polyscope contributors. https://polyscope.run

#pragma once

#include <functional>
#include <string>
#include <tuple>
#include <vector>

#include "imgui.h"

#include "polyscope/scaled_value.h"
#include "polyscope/types.h"


namespace polyscope {
namespace options {

// A general name to use when referring to the program in window headings.
extern std::string programName;

// How much should polyscope print to std::out?
// 0 --> none
// 1 --> some
// > 1 --> a lot
extern int verbosity;

// A string to prefex all messages printed to stdout
extern std::string printPrefix;

// Should errors throw exceptions, or just display? (default false)
extern bool errorsThrowExceptions;

// Allow initialization to create headless backends when selecting a backend automatically
// (they can still created explicitly by name) (default: false)
extern bool allowHeadlessBackends;

// Don't let the main loop run at more than this speed. (-1 disables) (default: 60)
extern int maxFPS;

// If enable or disable swap synchronization (limits render ray to display refresh rate). (default: true)
// NOTE: some platforms may ignore the setting.
extern bool enableVSync;

// When using the alternate `frameTick()` control flow instead of `show()`, how should framerate-limiting maxFPS/vsync
// features be respected? (which might caues the program to block on the call to frameTick()). (default:
// LimitFPSMode::SkipFramesToHitTarget)
extern LimitFPSMode frameTickLimitFPSMode;

// Read preferences (window size, etc) from startup file, write to same file on exit (default: true)
extern bool usePrefsFile;

// Should we redraw every frame, even if not requested? (default: false)
extern bool alwaysRedraw;

// Should we center/scale every structure after it is loaded up (default: false)
extern bool autocenterStructures;
extern bool autoscaleStructures;

// If true, Polyscope will automatically compute state::boundingBox and state::lengthScale parameters according to the
// registered structures, and update them whenever structures are added chagned. If false, the bounding box and length
// scale are left unchanged. If set to false before the first structure is registered, the user is required to set the
// bounding box and length scale manually. (default: true)
extern bool automaticallyComputeSceneExtents;

// If true, the user callback will be invoked for nested calls to polyscope::show(), otherwise not (default: false)
extern bool invokeUserCallbackForNestedShow;

// If true, focus the Polyscope window when shown (default: false)
extern bool giveFocusOnShow;

// If true, hide the polyscope window when a show() command finishes (default: true)
extern bool hideWindowAfterShow;

// Give warnings for inf/nan values
extern bool warnForInvalidValues;

// Show warnings/errors in popup modal dialogs
extern bool displayMessagePopups;

// === Scene options

// Behavior of the ground plane
extern GroundPlaneMode groundPlaneMode;
extern GroundPlaneHeightMode groundPlaneHeightMode;
extern bool groundPlaneEnabled; // deprecated, but kept and respected for compatability. use groundPlaneMode.
extern ScaledValue<float> groundPlaneHeightFactor;
extern float groundPlaneHeight;
extern int shadowBlurIters;
extern float shadowDarkness;

extern bool screenshotTransparency;     // controls whether screenshots taken by clicking the GUI button have a
                                        // transparent background
extern bool screenshotWithImGuiUI;      // controls whether screenshots taken by clicking the GUI button have a
                                        // transparent background
extern std::string screenshotExtension; // sets the extension used for automatically-numbered screenshots (e.g. by
                                        // clicking the GUI button)

// === Rendering parameters

// SSAA scaling in pixel multiples
extern int ssaaFactor;

// DPI scaling to scale the UI on high-resolutoin screens
extern float uiScale;

// Transparency settings for the renderer
extern TransparencyMode transparencyMode;
extern int transparencyRenderPasses;

// === Advanced ImGui configuration

// If false, Polyscope will not create any ImGui UIs at all, but will still set up ImGui and invoke its render steps
// each frame. The allows advanced users to create their own UIs totally from scratch and circumvent the standard
// Polyscope UIs. (default: true)
extern bool buildGui;

// Draw the user gui panel on the right side, if false will be drawn on the left
// (default: true)
extern bool userGuiIsOnRightSide;

// Build the built-in gui panels (polyscope & structure menus on the left, selection menu on the right)
// The difference between this vs. buildGui is whether or not the user gui panel is drawn, this setting does _not_
// effect the user gui panel. (default: true)
extern bool buildDefaultGuiPanels;

// The width of the user GUI panel which is usually on the right side (default: 500)
extern int rightGuiPaneWidth;

// If false, Polyscope will not render the scene into the draw buffer
// (this is useful if you are doing custom rendering and filling the draw buffer yourself)
extern bool renderScene;

// Should the user call back start out with an imgui window context open (default: true)
extern bool openImGuiWindowForUserCallback;

// Controls whether Polyscope's usual panning/rotating/etc view motions are trigged by the mouse.
// Set this to false to temporarily disable scene camera movement if the mouse is being used for another
// purpose in a custom interaction.
// (default: true)
extern bool doDefaultMouseInteraction;

// A callback function which will be invoked when an ImGui context is created (which may happen several times as
// Polyscope runs). By default, this is set to invoke `configureImGuiStyle()` from Polyscope's imgui_config.cpp, but you
// may assign your own function to create custom styles. If this callback is null, the default ImGui style will be used.
extern std::function<void()> configureImGuiStyleCallback;

// A callback function which will be invoked exactly once during initialization to add fonts to a font atlas for ImGui
// to use. The callback should return two pointers: a regular font and a mono font. By default, this is set to invoke
// loadBaseFonts() from Polyscope's imgui_config.cpp, but you may assign your own function to create custom styles. If
// this callback is null, default fonts will be used.
extern std::function<std::tuple<ImFont*, ImFont*>(ImFontAtlas*)> prepareImGuiFontsCallback;

// === Backend and low-level options

// When using the EGL backend, which device to try to initialize with
// (default is -1 which means try all of them)
extern int eglDeviceIndex;

// === Debug options

// Enables optional error checks in the rendering system
extern bool enableRenderErrorChecks;

// Render the pick buffer to screen rather than the regular scene
extern bool debugDrawPickBuffer;

} // namespace options
} // namespace polyscope
