cmake_minimum_required(VERSION 3.22)

project(MixerHost VERSION 0.3.0)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Optional patch toggle: include template/patch sources when enabled
option(PROMIXER_PATCH "Enable ProMixer optional patches and GUI template (adds MyComponent)" OFF)

# ── JUCE ──────────────────────────────────────────────────────────────────────
add_subdirectory(external/JUCE)

# ── ysfx ──────────────────────────────────────────────────────────────────────
# JSFX runtime. Submodule expected at external/ysfx. See SETUP_NOTES_PHASE4.md
# for the one-time `git submodule add` command.
set(MIXERHOST_WITH_JSFX ON CACHE BOOL "Enable JSFX hosting via ysfx")

if(MIXERHOST_WITH_JSFX)
    if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/external/ysfx/CMakeLists.txt")
        message(FATAL_ERROR
            "ysfx submodule not found at external/ysfx.\n"
            "Run: git submodule add https://github.com/JoepVanlier/ysfx.git external/ysfx\n"
            "Then: cd external/ysfx && git submodule update --init --recursive\n"
            "Or build without JSFX support by passing -DMIXERHOST_WITH_JSFX=OFF.")
    endif()

    # Turn off ysfx's own plugin/tests/test builds; we only want the library.
    # Portable mode avoids the MSVC x64 NASM requirement in ysfx's eel2 build.
    set(YSFX_PORTABLE ON CACHE BOOL "" FORCE)
    set(YSFX_SKIP_CHECKSUM ON CACHE BOOL "" FORCE)
    set(YSFX_PLUGIN OFF CACHE BOOL "" FORCE)
    set(YSFX_TESTS  OFF CACHE BOOL "" FORCE)
    set(YSFX_TOOLS  OFF CACHE BOOL "" FORCE)
    set(YSFX_PLUGIN_USE_SYSTEM_JUCE OFF CACHE BOOL "" FORCE)

    add_subdirectory(external/ysfx EXCLUDE_FROM_ALL)
endif()

# ── App target ────────────────────────────────────────────────────────────────
juce_add_gui_app(MixerHost
    PRODUCT_NAME "MixerHost"
)

juce_generate_juce_header(MixerHost)

target_sources(MixerHost PRIVATE
    Source/Main.cpp
    Source/MainComponent.cpp
    Source/Audio/AudioEngine.cpp
    Source/Audio/AuxBus.cpp
    Source/Audio/AuxBusBank.cpp
    Source/Audio/MixerTrack.cpp
    Source/Audio/PeakMeter.cpp
    Source/Audio/SlotChain.cpp
    Source/Audio/ProfileSerializer.cpp
    Source/Audio/FX/MasterLimiter.cpp
    Source/Audio/InternalSlots/InternalReverbSlot.cpp
    Source/Audio/InternalSlots/InternalDelaySlot.cpp
    Source/GUI/ChannelPageComponent.cpp
    Source/GUI/DevicePageComponent.cpp
    Source/GUI/OverviewPageComponent.cpp
    Source/GUI/RoutingPageComponent.cpp
    Source/GUI/SnapshotsPageComponent.cpp
    Source/GUI/MixerStripComponent.cpp
    Source/GUI/MasterStripComponent.cpp
    Source/GUI/InternalSlotComponent.cpp
    Source/GUI/ProMixerLookAndFeel.cpp
)


if(PROMIXER_PATCH)
    target_sources(MixerHost PRIVATE
        Source/GUI/MyComponent.cpp
        Source/GUI/UIEditorState.cpp
        Source/GUI/UIEditorRegistry.cpp
    )
    target_compile_definitions(MixerHost PRIVATE PROMIXER_PATCH=1)
endif()

if(MIXERHOST_WITH_JSFX)
    target_sources(MixerHost PRIVATE
        Source/Audio/JSFX/JsfxSlot.cpp
        Source/GUI/JsfxGfxComponent.cpp
        Source/GUI/JsfxSlotComponent.cpp
        Source/GUI/MasterChainEditor.cpp
        external/ysfx/plugin/components/graphics_view.cpp
        external/ysfx/plugin/utility/async_updater.cpp
        external/ysfx/plugin/utility/rt_semaphore.cpp
    )

    target_compile_definitions(MixerHost PRIVATE MIXERHOST_WITH_JSFX=1)
endif()

target_include_directories(MixerHost PRIVATE
    Source
)

target_compile_definitions(MixerHost PRIVATE
    JUCE_ASIO=1
    JUCE_ASIO_USE_EXTERNAL_SDK=0
    JUCE_WEB_BROWSER=0
    JUCE_USE_CURL=0
)

# ── Link libraries ────────────────────────────────────────────────────────────
target_link_libraries(MixerHost PRIVATE
    juce::juce_audio_utils
    juce::juce_audio_devices
    juce::juce_audio_basics
    juce::juce_audio_processors
    juce::juce_audio_formats
    juce::juce_dsp
    juce::juce_gui_extra
)

if(MIXERHOST_WITH_JSFX)
    # The ysfx target name has varied across forks: "ysfx" in jpcima's,
    # potentially "ysfx-s" or aliased "ysfx::ysfx" in Saike's. Pick whichever
    # exists at configure time so the build survives a fork swap.
    if(TARGET ysfx::ysfx)
        target_link_libraries(MixerHost PRIVATE ysfx::ysfx)
    elseif(TARGET ysfx)
        target_link_libraries(MixerHost PRIVATE ysfx)
    elseif(TARGET ysfx-s)
        target_link_libraries(MixerHost PRIVATE ysfx-s)
    else()
        message(FATAL_ERROR
            "Could not find a usable ysfx target. The ysfx submodule built but "
            "exposed none of: ysfx::ysfx, ysfx, ysfx-s. Inspect external/ysfx "
            "CMakeLists.txt to discover the actual target name and add it here.")
    endif()

    # The ysfx public headers live in external/ysfx/include.
    target_include_directories(MixerHost PRIVATE
        external/ysfx/include
        external/ysfx/plugin
    )
endif()
