cmake_minimum_required(VERSION 3.22)
project(TeaVoxPlus VERSION 1.0.0 LANGUAGES C CXX)
option(TEAVOX_BUILD_TESTS "Build native validation programs" ON)
set(TEAVOX_AUTO_MANIFEST TRUE)
if(CMAKE_CROSSCOMPILING AND NOT APPLE)
    # JUCE's optional metadata helper is a target executable, which cannot run here.
    # VST3 hosts can discover these bundles directly through their factory entry point.
    set(TEAVOX_AUTO_MANIFEST FALSE)
endif()
if(APPLE)
    enable_language(OBJC OBJCXX)
    set(TEAVOX_FORMATS VST3 AU Standalone)
    set(TEALY_TRANSPORT Source/TealyTransport.mm)
    set(LICENSE_TRANSPORT ../Shared/Licensing/LicenseTransport.mm)
else()
    set(TEAVOX_FORMATS VST3 Standalone)
    set(TEALY_TRANSPORT Source/TealyTransport.cpp)
    set(LICENSE_TRANSPORT ../Shared/Licensing/LicenseTransport.cpp)
    find_package(CURL 7.85 REQUIRED)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum macOS")
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "Target architecture")
set(JUCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/JUCE" CACHE PATH "JUCE source")
add_subdirectory("${JUCE_ROOT}" "${CMAKE_BINARY_DIR}/JUCE" EXCLUDE_FROM_ALL)
juce_add_plugin(TeaVox
    COMPANY_NAME "Methane Co: Project Imitatio Dei"
    BUNDLE_ID "audio.teavox.plus"
    PLUGIN_MANUFACTURER_CODE TeaA
    PLUGIN_CODE Tvxp
    FORMATS ${TEAVOX_FORMATS}
    PRODUCT_NAME "TeaVox+"
    DESCRIPTION "Methane Co: Project Imitatio Dei - TeaVox+ vocal chain"
    IS_SYNTH FALSE
    NEEDS_MIDI_INPUT TRUE
    NEEDS_MIDI_OUTPUT FALSE
    EDITOR_WANTS_KEYBOARD_FOCUS FALSE
    MICROPHONE_PERMISSION_ENABLED TRUE
    MICROPHONE_PERMISSION_TEXT "Methane Co: Project Imitatio Dei uses your microphone for live vocals and note recording."
    VST3_AUTO_MANIFEST ${TEAVOX_AUTO_MANIFEST}
    COPY_PLUGIN_AFTER_BUILD FALSE
    VST3_CATEGORIES Fx Dynamics Distortion PitchShift
    AU_MAIN_TYPE kAudioUnitType_MusicEffect)
target_sources(TeaVox PRIVATE
    Source/PluginProcessor.cpp Source/PluginEditor.cpp Source/TealyPage.cpp Source/Tealy.cpp ${TEALY_TRANSPORT}
    Source/PitchEngine.cpp Source/TeaDSP.cpp Source/TeaEffects.cpp Source/TeaEQ.cpp Source/MidiController.cpp
    ../TeaGate/Source/GateEngine.cpp ../TeaMIDI/Source/MidiEngine.cpp)
target_sources(TeaVox PRIVATE ../Shared/Licensing/LicenseManager.cpp ../Shared/Licensing/ActivationPanel.cpp ${LICENSE_TRANSPORT})
target_include_directories(TeaVox PUBLIC Source)
set_target_properties(TeaVox PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN YES)
target_compile_definitions(TeaVox PUBLIC
    JUCE_WEB_BROWSER=0 JUCE_USE_CURL=0 JUCE_VST3_CAN_REPLACE_VST2=0
    JUCE_PLUGINHOST_VST3=1 JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS=0)
target_link_libraries(TeaVox PRIVATE juce::juce_audio_utils juce::juce_dsp juce::juce_cryptography
    PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_warning_flags)
if(APPLE)
    set_source_files_properties(Source/TealyTransport.mm PROPERTIES COMPILE_FLAGS "-fobjc-arc")
    set_source_files_properties(${LICENSE_TRANSPORT} PROPERTIES COMPILE_FLAGS "-fobjc-arc")
    target_link_libraries(TeaVox PRIVATE "-framework Foundation")
else()
    target_link_libraries(TeaVox PRIVATE CURL::libcurl)
    if(UNIX)
        # Keep bundled curl/c-ares symbols from interposing a DAW's own libraries.
        target_link_options(TeaVox INTERFACE "LINKER:--exclude-libs,ALL")
    endif()
endif()

if(TEAVOX_BUILD_TESTS)
juce_add_console_app(TeaVoxTests PRODUCT_NAME "TeaVoxTests")
target_sources(TeaVoxTests PRIVATE Tests/PluginTests.cpp)
if(APPLE)
    target_link_options(TeaVoxTests PRIVATE "-Wl,-exported_symbol,_main")
endif()
target_link_libraries(TeaVoxTests PRIVATE TeaVox)
target_include_directories(TeaVoxTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(TeaVoxTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
juce_add_console_app(TeaVoxNativeHost PRODUCT_NAME "TeaVoxNativeHost")
target_sources(TeaVoxNativeHost PRIVATE Tests/NativeHost.cpp)
if(APPLE)
    target_link_options(TeaVoxNativeHost PRIVATE "-Wl,-exported_symbol,_main")
endif()
target_link_libraries(TeaVoxNativeHost PRIVATE TeaVox)
target_include_directories(TeaVoxNativeHost PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(TeaVoxNativeHost PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
add_executable(PitchTests Tests/PitchTests.cpp Source/PitchEngine.cpp)
target_include_directories(PitchTests PRIVATE Source)
add_executable(DynamicsTests Tests/DynamicsTests.cpp Source/TeaDSP.cpp)
target_include_directories(DynamicsTests PRIVATE Source)
add_executable(EffectsTests Tests/EffectsTests.cpp Source/TeaEffects.cpp)
target_include_directories(EffectsTests PRIVATE Source)
add_executable(EQTests Tests/EQTests.cpp Source/TeaEQ.cpp)
target_include_directories(EQTests PRIVATE Source)
enable_testing()
add_test(NAME pitch COMMAND PitchTests)
add_test(NAME dynamics COMMAND DynamicsTests)
add_test(NAME processor COMMAND TeaVoxTests)
add_test(NAME effects COMMAND EffectsTests)
add_test(NAME eq COMMAND EQTests)
set_tests_properties(pitch dynamics processor effects eq PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")

add_executable(GateTests ../TeaGate/Tests/GateTests.cpp ../TeaGate/Source/GateEngine.cpp)
target_include_directories(GateTests PRIVATE ../TeaGate/Source)
add_executable(MidiTests ../TeaMIDI/Tests/MidiTests.cpp ../TeaMIDI/Source/MidiEngine.cpp Source/PitchEngine.cpp)
target_include_directories(MidiTests PRIVATE ../TeaMIDI/Source Source)
juce_add_console_app(MidiControllerTests PRODUCT_NAME "MidiControllerTests")
target_sources(MidiControllerTests PRIVATE Tests/MidiControllerTests.cpp)
target_link_libraries(MidiControllerTests PRIVATE TeaVox)
target_include_directories(MidiControllerTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(MidiControllerTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
add_test(NAME gate COMMAND GateTests)
add_test(NAME midi COMMAND MidiTests)
add_test(NAME midi_controller COMMAND MidiControllerTests)
set_tests_properties(gate midi midi_controller PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")

endif()

# TeaMIDI is a separate voice-to-notes recorder with its own plugin identity.
juce_add_plugin(TeaMIDIPlugin
    VERSION 1.0.0
    COMPANY_NAME "Methane Co: Project Imitatio Dei"
    BUNDLE_ID "audio.teavox.teamidi"
    PLUGIN_MANUFACTURER_CODE TeaA
    PLUGIN_CODE Tmid
    FORMATS ${TEAVOX_FORMATS}
    PRODUCT_NAME "TeaMIDI"
    DESCRIPTION "Methane Co: Project Imitatio Dei - TeaMIDI voice-to-MIDI recorder"
    IS_SYNTH FALSE
    NEEDS_MIDI_INPUT FALSE
    NEEDS_MIDI_OUTPUT TRUE
    EDITOR_WANTS_KEYBOARD_FOCUS FALSE
    MICROPHONE_PERMISSION_ENABLED TRUE
    MICROPHONE_PERMISSION_TEXT "Methane Co: Project Imitatio Dei uses your microphone for live vocals and note recording."
    VST3_AUTO_MANIFEST ${TEAVOX_AUTO_MANIFEST}
    COPY_PLUGIN_AFTER_BUILD FALSE
    VST3_CATEGORIES Fx PitchShift
    AU_MAIN_TYPE kAudioUnitType_MusicEffect)
target_sources(TeaMIDIPlugin PRIVATE
    ../TeaMIDI/Source/TeaMIDIProcessor.cpp
    ../TeaMIDI/Source/TeaMIDIEditor.cpp
    ../TeaMIDI/Source/MidiEngine.cpp Source/PitchEngine.cpp)
target_sources(TeaMIDIPlugin PRIVATE ../Shared/Licensing/LicenseManager.cpp ../Shared/Licensing/ActivationPanel.cpp ${LICENSE_TRANSPORT})
target_include_directories(TeaMIDIPlugin PUBLIC ../TeaMIDI/Source)
set_target_properties(TeaMIDIPlugin PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN YES)
target_compile_definitions(TeaMIDIPlugin PUBLIC
    JUCE_WEB_BROWSER=0 JUCE_USE_CURL=0 JUCE_VST3_CAN_REPLACE_VST2=0
    JUCE_PLUGINHOST_VST3=1 JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS=0)
target_link_libraries(TeaMIDIPlugin PRIVATE juce::juce_audio_utils juce::juce_dsp juce::juce_cryptography
    PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_warning_flags)
if(APPLE)
    target_link_libraries(TeaMIDIPlugin PRIVATE "-framework Foundation")
else()
    target_link_libraries(TeaMIDIPlugin PRIVATE CURL::libcurl)
    if(UNIX)
        target_link_options(TeaMIDIPlugin INTERFACE "LINKER:--exclude-libs,ALL")
    endif()
endif()
if(TEAVOX_BUILD_TESTS)
juce_add_console_app(LicenseVerifierTests PRODUCT_NAME "LicenseVerifierTests")
target_sources(LicenseVerifierTests PRIVATE ../Shared/Licensing/tests/LicenseVerifierTests.cpp)
target_compile_definitions(LicenseVerifierTests PRIVATE JUCE_WEB_BROWSER=0 JUCE_USE_CURL=0)
target_link_libraries(LicenseVerifierTests PRIVATE juce::juce_core juce::juce_cryptography PUBLIC juce::juce_recommended_config_flags)
set(GMFM_TEST_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/../../.gmfm-secrets" CACHE PATH "Private signed licensing verification fixtures")
add_test(NAME license_verifier COMMAND LicenseVerifierTests "${GMFM_TEST_FIXTURES}/public-key.txt" "${GMFM_TEST_FIXTURES}/valid.json" "${GMFM_TEST_FIXTURES}/tampered.json" "${GMFM_TEST_FIXTURES}/test.json" "${GMFM_TEST_FIXTURES}/wrong-product.json" "${GMFM_TEST_FIXTURES}/bundle.json")
juce_add_console_app(LicenseManagerTests PRODUCT_NAME "LicenseManagerTests")
target_sources(LicenseManagerTests PRIVATE ../Shared/Licensing/tests/LicenseManagerTests.cpp ../Shared/Licensing/LicenseManager.cpp ${LICENSE_TRANSPORT})
target_compile_definitions(LicenseManagerTests PRIVATE JUCE_WEB_BROWSER=0 JUCE_USE_CURL=0)
target_link_libraries(LicenseManagerTests PRIVATE juce::juce_core juce::juce_cryptography PUBLIC juce::juce_recommended_config_flags)
if(APPLE)
    target_link_libraries(LicenseManagerTests PRIVATE "-framework Foundation")
else()
    target_link_libraries(LicenseManagerTests PRIVATE CURL::libcurl)
endif()
juce_add_console_app(TeaVoxLockedTests PRODUCT_NAME "TeaVoxLockedTests")
target_sources(TeaVoxLockedTests PRIVATE ../Shared/Licensing/tests/TeaVoxLockedTests.cpp)
target_link_libraries(TeaVoxLockedTests PRIVATE TeaVox)
target_include_directories(TeaVoxLockedTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(TeaVoxLockedTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
juce_add_console_app(TeaMIDILockedTests PRODUCT_NAME "TeaMIDILockedTests")
target_sources(TeaMIDILockedTests PRIVATE ../Shared/Licensing/tests/TeaMIDILockedTests.cpp)
target_link_libraries(TeaMIDILockedTests PRIVATE TeaMIDIPlugin)
target_include_directories(TeaMIDILockedTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(TeaMIDILockedTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
juce_add_console_app(TeaMIDIRecordingTests PRODUCT_NAME "TeaMIDIRecordingTests")
target_sources(TeaMIDIRecordingTests PRIVATE ../TeaMIDI/Tests/RecordingTests.cpp)
target_link_libraries(TeaMIDIRecordingTests PRIVATE TeaMIDIPlugin)
target_include_directories(TeaMIDIRecordingTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(TeaMIDIRecordingTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
if(APPLE)
    target_link_options(TeaMIDIRecordingTests PRIVATE "-Wl,-exported_symbol,_main")
endif()
add_test(NAME midi_recording COMMAND TeaMIDIRecordingTests)
set_tests_properties(midi_recording PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../TeaMIDI")

juce_add_console_app(TeaMIDIWorkflowTests PRODUCT_NAME "TeaMIDIWorkflowTests")
target_sources(TeaMIDIWorkflowTests PRIVATE ../TeaMIDI/Tests/WorkflowTests.cpp)
target_link_libraries(TeaMIDIWorkflowTests PRIVATE TeaMIDIPlugin)
target_include_directories(TeaMIDIWorkflowTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(TeaMIDIWorkflowTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
if(APPLE)
    target_link_options(TeaMIDIWorkflowTests PRIVATE "-Wl,-exported_symbol,_main")
endif()
add_test(NAME midi_workflow COMMAND TeaMIDIWorkflowTests)
set_tests_properties(midi_workflow PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../TeaMIDI")

add_executable(MidiStabilityTests ../TeaMIDI/Tests/StabilityTests.cpp ../TeaMIDI/Source/MidiEngine.cpp Source/PitchEngine.cpp)
target_include_directories(MidiStabilityTests PRIVATE ../TeaMIDI/Source Source)
add_test(NAME midi_stability COMMAND MidiStabilityTests)
set_tests_properties(midi_stability PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../TeaMIDI")

juce_add_console_app(TealyTests PRODUCT_NAME "TealyTests")
target_sources(TealyTests PRIVATE Tests/TealyTests.cpp)
target_link_libraries(TealyTests PRIVATE TeaVox)
target_include_directories(TealyTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(TealyTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
juce_add_console_app(TealyPageTests PRODUCT_NAME "TealyPageTests")
target_sources(TealyPageTests PRIVATE Tests/TealyPageTests.cpp)
target_link_libraries(TealyPageTests PRIVATE TeaVox)
target_include_directories(TealyPageTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(TealyPageTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
if(APPLE)
 target_link_options(TealyTests PRIVATE "-Wl,-exported_symbol,_main")
 target_link_options(TealyPageTests PRIVATE "-Wl,-exported_symbol,_main")
endif()
add_test(NAME tealy COMMAND TealyTests)
add_test(NAME tealy_page COMMAND TealyPageTests)
set_tests_properties(tealy tealy_page PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")

if(APPLE)
juce_add_console_app(TealyTransportTests PRODUCT_NAME "TealyTransportTests")
target_sources(TealyTransportTests PRIVATE Tests/TealyTransportTests.mm Source/Tealy.cpp ${TEALY_TRANSPORT})
set_source_files_properties(Tests/TealyTransportTests.mm PROPERTIES COMPILE_FLAGS "-fobjc-arc")
target_include_directories(TealyTransportTests PRIVATE Source)
target_compile_definitions(TealyTransportTests PRIVATE TEALY_TRANSPORT_TEST=1 JUCE_WEB_BROWSER=0 JUCE_USE_CURL=0)
target_link_libraries(TealyTransportTests PRIVATE juce::juce_core "-framework Foundation" PUBLIC juce::juce_recommended_config_flags)
if(APPLE)
 target_link_options(TealyTransportTests PRIVATE "-Wl,-exported_symbol,_main")
endif()
add_test(NAME tealy_transport COMMAND TealyTransportTests)
set_tests_properties(tealy_transport PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" TIMEOUT 45)

endif()

juce_add_console_app(PresetSelectionTests PRODUCT_NAME "PresetSelectionTests")
target_sources(PresetSelectionTests PRIVATE Tests/PresetSelectionTests.cpp)
target_link_libraries(PresetSelectionTests PRIVATE TeaVox)
target_include_directories(PresetSelectionTests PRIVATE "${JUCE_ROOT}/modules")
target_compile_definitions(PresetSelectionTests PRIVATE JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1)
if(APPLE)
 target_link_options(PresetSelectionTests PRIVATE "-Wl,-exported_symbol,_main")
endif()
add_test(NAME preset_selection COMMAND PresetSelectionTests)
set_tests_properties(preset_selection PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")

endif() # TEAVOX_BUILD_TESTS
