// SPDX-License-Identifier: Unlicense

#ifndef CONFIGURATION_H
#define CONFIGURATION_H

// Discover current platform
#ifdef _WIN32
#define PLATFORM_WINDOWS
#endif // _WIN32

#if defined(__linux) && !defined(__ANDROID__)
#define PLATFORM_LINUX
#endif // __linux && !__ANDROID__

#if defined(__ANDROID__) && !defined(PLATFORM_PICO_4) && !defined(PLATFORM_QUEST_3)
#define PLATFORM_ANDROID_SDL
#endif // __ANDROID__

#ifdef __EMSCRIPTEN__
#define PLATFORM_EMSCRIPTEN
#endif // __EMSCRIPTEN__

// Global Features
#ifndef NDEBUG
#if defined(PLATFORM_WINDOWS) || defined(PLATFORM_LINUX)
#define SHR3D_STARTUP_TESTS // run test.cpp before starting the application
#endif // PLATFORM_WINDOWS || PLATFORM_LINUX
#define SHR3D_OPENGL_ERROR_CHECK
#endif // NDEBUG

// Enable features for each platform
#ifdef PLATFORM_WINDOWS
#ifndef SHAREWARE
#define SHR3D_AUDIO_ASIO
#define SHR3D_AUDIO_ASIO_SECOND_DEVICE_FOR_TUNER_DIVIDED
//#define SHR3D_AUDIO_JACK
//#define SHR3D_AUDIO_SDL
#define SHR3D_AUDIO_WASAPI
#define SHR3D_COLLECTION_WORKER_THREAD
#define SHR3D_COOP
#define SHR3D_CUSTOM_CURSOR
#define SHR3D_ENVIRONMENT_MILK
#define SHR3D_ENVIRONMENT_SKYBOX
#define SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
#define SHR3D_ENVIRONMENT_STAGE
//#define SHR3D_FONT_BITMAP
#define SHR3D_FONT_MSDF
#define SHR3D_GETOPT
#define SHR3D_GRAPHICS_MSAA
#define SHR3D_HUD_DEVELOPMENT
#define SHR3D_MIDI
//#define SHR3D_NOTE_CUTS
//#define SHR3D_OPENGL_ES_FORCE
//#define SHR3D_OPENGL_SPIR_V
//#define SHR3D_OPENGL_DRAW_NON_INDEXED
//#define SHR3D_OPENGL_DRAW_ZERO_BASED
#define SHR3D_PARTICLE
#define SHR3D_PSARC
#define SHR3D_PSARC_REVORB
#define SHR3D_RENDERER_DEVELOPMENT
#define SHR3D_MUSIC_STRETCHER
#define SHR3D_SHRED
#define SHR3D_SFX_CORE_AIRWINDOWS
#define SHR3D_SFX_CORE_EXTENSION_V2
#define SHR3D_SFX_CORE_HEXFIN
#define SHR3D_SFX_CORE_HEXFIN_DIVIDED
#define SHR3D_SFX_CORE_NEURALAMPMODELER
#define SHR3D_SFX_CORE_RAKARRACK // simple 
#define SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
#define SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON
#define SHR3D_SFX_CORE_RAKARRACK_REVERBTRON
//#define SHR3D_SFX_CORE_RAKARRACK_PRESETS
#define SHR3D_SFX_PLUGIN_CLAP
//#define SHR3D_SFX_PLUGIN_LV2
#define SHR3D_SFX_PLUGIN_VST
#define SHR3D_SFX_PLUGIN_VST_BENCHMARK
#define SHR3D_SFX_PLUGIN_VST3
#define SHR3D_SFX_PLUGIN_VST3_BENCHMARK
//#define SHR3D_SPOTIFY
#define SHR3D_RECORDER
//#define SHR3D_WINDOW_SDL
#define SHR3D_WINDOW_WIN32
#define SHR3D_OPENXR_PCVR
#define SHR3D_OPENXR_CONTROLLER_PICO4
#define SHR3D_OPENXR_CONTROLLER_QUEST3
#else // SHAREWARE
#define SHR3D_AUDIO_ASIO
#define SHR3D_AUDIO_WASAPI
#define SHR3D_COLLECTION_WORKER_THREAD
#define SHR3D_CUSTOM_CURSOR
#define SHR3D_FONT_BITMAP
#define SHR3D_GETOPT
#define SHR3D_GRAPHICS_MSAA
#define SHR3D_MIDI
#define SHR3D_PARTICLE
#define SHR3D_PSARC
#define SHR3D_SFX_PLUGIN_VST
//#define SHR3D_SFX_PLUGIN_VST3
#define SHR3D_WINDOW_WIN32
#endif // SHAREWARE
#endif // PLATFORM_WINDOWS

// Platform Linux. Linux desktop application
#ifdef PLATFORM_LINUX
#define SHR3D_AUDIO_JACK
//#define SHR3D_AUDIO_PIPEWIRE
#define SHR3D_AUDIO_SDL
#define SHR3D_BENCHMARK_FPS
#define SHR3D_COLLECTION_WORKER_THREAD
//#define SHR3D_ENVIRONMENT_MILK
#define SHR3D_FONT_MSDF
#define SHR3D_GETOPT
#define SHR3D_PARTICLE
#define SHR3D_PSARC
#define SHR3D_PSARC_REVORB
#define SHR3D_MUSIC_STRETCHER
#define SHR3D_SFX_CORE_AIRWINDOWS
#define SHR3D_SFX_CORE_EXTENSION_V2
#define SHR3D_SFX_CORE_NEURALAMPMODELER
#define SHR3D_SFX_CORE_HEXFIN
#define SHR3D_SFX_CORE_HEXFIN_DIVIDED
#define SHR3D_SFX_CORE_RAKARRACK
#define SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
#define SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON
#define SHR3D_SFX_CORE_RAKARRACK_REVERBTRON
#define SHR3D_SFX_PLUGIN_CLAP
#define SHR3D_SFX_PLUGIN_VST
#define SHR3D_SFX_PLUGIN_VST_BENCHMARK
#define SHR3D_SFX_PLUGIN_GUI_WINDOW
#define SHR3D_SHRED
#define SHR3D_WINDOW_SDL
//#define SHR3D_WINDOW_X11
//#define SHR3D_OPENGL_ES_FORCE
#endif // PLATFORM_LINUX

// Android Smartphone.
#ifdef PLATFORM_ANDROID_SDL
#define SHR3D_AUDIO_AAUDIO
//#define SHR3D_AUDIO_SDL
#define SHR3D_AUDIO_SUPERPOWERED
#define SHR3D_COLLECTION_WORKER_THREAD
#define SHR3D_FONT_MSDF
#define SHR3D_GRAPHICS_MSAA
//#define SHR3D_MIDI
//#define SHR3D_OPENGL_DRAW_ZERO_BASED
#define SHR3D_PARTICLE
#define SHR3D_PSARC
#define SHR3D_PSARC_REVORB
#define SHR3D_SFX_CORE_AIRWINDOWS
#define SHR3D_SFX_CORE_EXTENSION_V2
#define SHR3D_SFX_CORE_HEXFIN
#define SHR3D_SFX_CORE_HEXFIN_DIVIDED
#define SHR3D_SFX_CORE_RAKARRACK
#define SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
#define SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON
#define SHR3D_SFX_CORE_RAKARRACK_REVERBTRON
#define SHR3D_SFX_CORE_NEURALAMPMODELER
#define SHR3D_SHRED
//#define SHR3D_WINDOW_ANDROID
//#define SHR3D_WINDOW_SDL
#endif // PLATFORM_ANDROID_SDL

#ifdef PLATFORM_QUEST_3
#define SHR3D_AUDIO_AAUDIO
#define SHR3D_AUDIO_SUPERPOWERED
#define SHR3D_COLLECTION_WORKER_THREAD
#define SHR3D_ENVIRONMENT_SKYBOX
#define SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
#define SHR3D_ENVIRONMENT_STAGE
//#define SHR3D_FONT_BITMAP
#define SHR3D_FONT_MSDF
#define SHR3D_GRAPHICS_MSAA
#define SHR3D_MUSIC_STRETCHER
#define SHR3D_PARTICLE
#define SHR3D_PSARC
#define SHR3D_PSARC_REVORB
#define SHR3D_RECORDER
#define SHR3D_SFX_CORE_AIRWINDOWS
#define SHR3D_SFX_CORE_EXTENSION_V2
#define SHR3D_SFX_CORE_HEXFIN
#define SHR3D_SFX_CORE_HEXFIN_DIVIDED
#define SHR3D_SFX_CORE_RAKARRACK
#define SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
#define SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON
#define SHR3D_SFX_CORE_RAKARRACK_REVERBTRON
#define SHR3D_SFX_CORE_NEURALAMPMODELER
#define SHR3D_SHRED
#define SHR3D_OPENXR_CONTROLLER_PICO4
#define SHR3D_OPENXR_CONTROLLER_QUEST3
#endif // PLATFORM_QUEST_3

#ifdef PLATFORM_PICO_4
#define SHR3D_AUDIO_AAUDIO
//#define SHR3D_AUDIO_SUPERPOWERED
#define SHR3D_COLLECTION_WORKER_THREAD
#define SHR3D_ENVIRONMENT_SKYBOX
#define SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
#define SHR3D_ENVIRONMENT_STAGE
//#define SHR3D_FONT_BITMAP
#define SHR3D_FONT_MSDF
//#define SHR3D_GRAPHICS_MSAA
#define SHR3D_OPENXR_CONTROLLER_PICO4
#define SHR3D_OPENXR_CONTROLLER_QUEST3
#define SHR3D_MUSIC_STRETCHER
#define SHR3D_PARTICLE
#define SHR3D_PSARC
#define SHR3D_PSARC_REVORB
//#define SHR3D_SFX_CORE_AIRWINDOWS
#define SHR3D_SFX_CORE_HEXFIN
//#define SHR3D_SFX_CORE_HEXFIN_DIVIDED
//#define SHR3D_SFX_CORE_RAKARRACK
//#define SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
//#define SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON
//#define SHR3D_SFX_CORE_RAKARRACK_REVERBTRON
//#define SHR3D_SFX_CORE_NEURALAMPMODELER
#define SHR3D_SHRED
#endif // PLATFORM_PICO_4

// Webbrowser
#ifdef PLATFORM_EMSCRIPTEN
#define SHR3D_AUDIO_WEBAUDIO
#define SHR3D_BENCHMARK_FPS
#define SHR3D_CUSTOM_CURSOR
//#define SHR3D_FONT_BITMAP
#define SHR3D_FONT_MSDF
#define SHR3D_GETOPT
//#define SHR3D_HUD_DEVELOPMENT
//#define SHR3D_OPENGL_DRAW_NON_INDEXED
#define SHR3D_PARTICLE
#define SHR3D_PSARC
#define SHR3D_PSARC_REVORB
//#define SHR3D_RENDERER_DEVELOPMENT
#define SHR3D_SFX_CORE_AIRWINDOWS
#define SHR3D_SFX_CORE_EXTENSION_V2
#define SHR3D_SFX_CORE_HEXFIN
#define SHR3D_SFX_CORE_NEURALAMPMODELER
#define SHR3D_SFX_CORE_RAKARRACK
//#define SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
//#define SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON
//#define SHR3D_SFX_CORE_RAKARRACK_REVERBTRON
#define SHR3D_SHRED
#define SHR3D_WINDOW_SDL
#endif // PLATFORM_EMSCRIPTEN

// for buildWindowsNative.bat
#ifdef BUILD_WINDOWS_NATIVE 
#define SHR3D_AUDIO_WASAPI
#define SHR3D_WINDOW_WIN32
#undef SHR3D_AUDIO_SDL
#undef SHR3D_WINDOW_SDL
#undef SHR3D_ENVIRONMENT_MILK
#endif // BUILD_WINDOWS_NATIVE

// for buildWindowsNative.bat
#ifdef BUILD_WINDOWS_SDL
#define SHR3D_AUDIO_SDL
#define SHR3D_WINDOW_SDL
#undef SHR3D_AUDIO_WASAPI
#undef SHR3D_WINDOW_WIN32
#endif // BUILD_WINDOWS_SDL

#if defined(SHR3D_PSARC) && defined(SHR3D_PSARC_REVORB)
#define SHR3D_REVORB // revorb is only needed for psarc files
#endif

#if defined(SHR3D_SHRED) || defined(SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE)
#define SHR3D_PNG_DECODER
#endif

#if defined(SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE) && !defined(SHR3D_ENVIRONMENT_SKYBOX)
#error SHR3D_ENVIRONMENT_SKYBOX is requried
#endif

#if defined(SHR3D_SFX_CORE_HEXFIN_DIVIDED) && !defined(SHR3D_SFX_CORE_HEXFIN)
#error SHR3D_SFX_CORE_HEXFIN is requried
#endif

#if defined(SHR3D_AUDIO_ASIO_SECOND_DEVICE_FOR_TUNER_DIVIDED) && !defined(SHR3D_SFX_CORE_HEXFIN_DIVIDED)
#error SHR3D_SFX_CORE_HEXFIN_DIVIDED is requried
#endif

#if defined(SHR3D_SFX_CORE_HEXFIN_DIVIDED) && !(defined(SHR3D_AUDIO_ASIO) || defined(SHR3D_AUDIO_JACK) || defined(SHR3D_AUDIO_PIPEWIRE) || defined(SHR3D_AUDIO_SUPERPOWERED))
#error SHR3D_SFX_CORE_HEXFIN_DIVIDED requires either ASIO, JACK, PIPEWIRE or SUPERPOWERED
#endif

#if defined(SHR3D_AUDIO_SDL) || defined(SHR3D_WINDOW_SDL)
#define SHR3D_SDL
#endif

#if defined(SHR3D_SHRED) || defined(SHR3D_PSARC)
#define SHR3D_SHRED_OR_PSARC
#endif

#if defined(SHR3D_SHRED) && defined(SHR3D_PSARC)
#define SHR3D_SHRED_AND_PSARC
#endif

#if defined(SHR3D_SFX_CORE_AIRWINDOWS) || defined(SHR3D_SFX_CORE_EXTENSION_V2) || defined(SHR3D_SFX_CORE_NEURALAMPMODELER) || defined(SHR3D_SFX_CORE_RAKARRACK) || defined(SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE) || defined(SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON) || defined(SHR3D_SFX_CORE_RAKARRACK_REVERBTRON) || defined(SHR3D_SFX_CORE_HEXFIN)
#define SHR3D_SFX_CORE
#endif

#if defined(SHR3D_SFX_PLUGIN_CLAP) || defined(SHR3D_SFX_PLUGIN_LV2) || defined(SHR3D_SFX_PLUGIN_VST) || defined(SHR3D_SFX_PLUGIN_VST3)
#define SHR3D_SFX_PLUGIN
#endif

#if defined(SHR3D_SFX_CORE) || defined(SHR3D_SFX_PLUGIN)
#define SHR3D_SFX
#endif

#if defined(SHR3D_SFX_PLUGIN_VST_BENCHMARK) || defined(SHR3D_SFX_PLUGIN_VST3_BENCHMARK)
#define SHR3D_SFX_PLUGIN_BENCHMARK
#endif

#if defined(SHR3D_SFX_CORE_RAKARRACK) || defined(SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE) || defined(SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON) || defined(SHR3D_SFX_CORE_RAKARRACK_REVERBTRON) || defined(SHR3D_REVORB)
#define SHR3D_LIBSAMPLERATE
#endif

#if defined(SHR3D_SFX) || defined(SHR3D_PSARC)
#define SHR3D_BASE64
#endif

#if defined(PLATFORM_PICO_4) || defined(PLATFORM_QUEST_3)
#define PLATFORM_OPENXR_ANDROID
#define XR_USE_PLATFORM_ANDROID // for OpenXR
#define XR_USE_GRAPHICS_API_OPENGL_ES // for OpenXR
#endif

#if defined(SHR3D_OPENXR_PCVR) || defined(PLATFORM_OPENXR_ANDROID)
#define SHR3D_OPENXR
#endif

#if defined(SHR3D_OPENXR_CONTROLLER_PICO4) || defined(SHR3D_OPENXR_CONTROLLER_QUEST3)
#define SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
#endif

#if defined(SHR3D_AUDIO_ASIO) && defined(SHR3D_AUDIO_JACK) && defined(SHR3D_AUDIO_PIPEWIRE)
#define IS_DIVIDED_PICKUP_ENABLED (Settings::audioAsioDividedPickup || Settings::audioJackDividedPickup || Settings::audioPipewireDividedPickup)
#elif defined(SHR3D_AUDIO_ASIO) && defined(SHR3D_AUDIO_JACK)
#define IS_DIVIDED_PICKUP_ENABLED (Settings::audioAsioDividedPickup || Settings::audioJackDividedPickup)
#elif defined(SHR3D_AUDIO_ASIO) && defined(SHR3D_AUDIO_PIPEWIRE)
#define IS_DIVIDED_PICKUP_ENABLED (Settings::audioAsioDividedPickup || Settings::audioPipewireDividedPickup)
#elif defined(SHR3D_AUDIO_JACK) && defined(SHR3D_AUDIO_PIPEWIRE)
#define IS_DIVIDED_PICKUP_ENABLED (Settings::audioJackDividedPickup || Settings::audioPipewireDividedPickup)
#elif defined(SHR3D_AUDIO_ASIO)
#define IS_DIVIDED_PICKUP_ENABLED (Settings::audioAsioDividedPickup)
#elif defined(SHR3D_AUDIO_JACK)
#define IS_DIVIDED_PICKUP_ENABLED (Settings::audioJackDividedPickup)
#elif defined(SHR3D_AUDIO_PIPEWIRE)
#define IS_DIVIDED_PICKUP_ENABLED (Settings::audioPipewireDividedPickup)
#elif defined(SHR3D_AUDIO_SUPERPOWERED)
#define IS_DIVIDED_PICKUP_ENABLED (Settings::audioSuperpoweredDividedPickup)
#endif

#endif // CONFIGURATION_H
