# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: Copyright (C) 2026 Max A. Vilkki a.k.a. codise
#
# The flipSID player.
#
# macOS: an app bundle, flipSID.app. The bundle's Info.plist is what makes it a proper
# app: its name in the menu bar and Dock, Retina rendering, the integrated GPU on
# dual-GPU Macs (NSSupportsAutomaticGraphicsSwitching), and later file associations,
# microphone access for recording (§8) and a DMG. The executable inside,
# flipSID.app/Contents/MacOS/flipSID, still runs from a terminal with arguments.
# Windows: a GUI-subsystem exe (no console window); SDL_main supplies WinMain.
# Linux: a plain executable.

# What the app decides without a window or device (the command line, when to run the audio
# device, one file dialog at a time), on its own so the tests can link it.
add_library(flipsid_cli STATIC command_line.cpp device_policy.cpp file_dialogs.cpp
    hvsc_view.cpp sid_out_config.cpp sid_out_view.cpp)
add_library(flipsid::cli ALIAS flipsid_cli)
target_include_directories(flipsid_cli PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
# sid_out_config: from the settings' USB SID entries to the SID-out service's configuration.
# sid_out_view: what a HardSID entry's row on the Output tab says.
# hvsc_view: the first start's condition, the folder checks and the HVSC window's view
# (DESIGN §8.1); flipsid::ui for the view's types only, which are plain data.
target_link_libraries(flipsid_cli
    PUBLIC flipsid::hvsc flipsid::settings flipsid::sidout flipsid::ui
    PRIVATE flipsid::common flipsid::library)
flipsid_configure_target(flipsid_cli)

add_executable(flipsid
    app.cpp
    app_hvsc.cpp
    app_library.cpp
    app_liked.cpp
    app_mixer.cpp
    app_playlist.cpp
    app_profiles.cpp
    app_scripted.cpp
    app_settings.cpp
    app_sid_out.cpp
    app_song_end.cpp
    app_theme.cpp
    app_ultimate.cpp
    main.cpp
    reveal.cpp
    trash.cpp
)

target_link_libraries(flipsid PRIVATE
    flipsid::cli
    flipsid::common
    flipsid::hardsid
    flipsid::hvsc
    flipsid::library
    flipsid::log
    flipsid::mixer
    flipsid::output
    flipsid::platform
    flipsid::player
    flipsid::playlist
    flipsid::profiles
    flipsid::settings
    flipsid::sidout
    flipsid::ui
    flipsid::ultimate
    flipsid::version
    ext::SDL3
    ext::imgui
)

# The built-in themes (DESIGN §5.8): a folder each in assets/themes/, with its theme.json
# and fonts, shipped as files beside the app. macOS: Resources/themes/;
# elsewhere themes/ next to the executable. Re-run CMake after adding a file.
set(themeDir "${PROJECT_SOURCE_DIR}/assets/themes")
# Kept in the repository but not shipped: ZOO 2026 waits for the organisers' artwork
# (user decision 2026-11-03).
set(themesLeftOut zoo-2026)
file(GLOB_RECURSE themeFiles CONFIGURE_DEPENDS "${themeDir}/*")
list(FILTER themeFiles EXCLUDE REGEX "/\\.[^/]*$")
list(FILTER themeFiles EXCLUDE REGEX "/README\\.md$")
foreach(theme IN LISTS themesLeftOut)
    list(FILTER themeFiles EXCLUDE REGEX "/assets/themes/${theme}/")
endforeach()
if(APPLE)
    foreach(file IN LISTS themeFiles)
        file(RELATIVE_PATH relative "${themeDir}" "${file}")
        get_filename_component(subdir "${relative}" DIRECTORY)
        target_sources(flipsid PRIVATE "${file}")
        set_source_files_properties("${file}" PROPERTIES
            MACOSX_PACKAGE_LOCATION "Resources/themes/${subdir}")
    endforeach()
elseif(themeFiles)
    # File by file, so the left-out themes stay out; themes/ is made afresh each time,
    # so one left out after a build doesn't linger there.
    set(themeCopies COMMAND "${CMAKE_COMMAND}" -E rm -rf "$<TARGET_FILE_DIR:flipsid>/themes")
    foreach(file IN LISTS themeFiles)
        file(RELATIVE_PATH relative "${themeDir}" "${file}")
        get_filename_component(subdir "${relative}" DIRECTORY)
        list(APPEND themeCopies
            COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:flipsid>/themes/${subdir}"
            COMMAND "${CMAKE_COMMAND}" -E copy "${file}" "$<TARGET_FILE_DIR:flipsid>/themes/${subdir}")
    endforeach()
    add_custom_command(TARGET flipsid POST_BUILD ${themeCopies} VERBATIM)
endif()

# The app icon (DESIGN §5, "App icon"): rendered by tools/icon/ into assets/icon/.
set(iconDir "${PROJECT_SOURCE_DIR}/assets/icon")

if(APPLE)
    target_sources(flipsid PRIVATE macos/app_menu.cpp macos/display_link.cpp macos/trash.cpp macos/window_sheet.cpp
        "${iconDir}/flipsid.icns")
    set_source_files_properties("${iconDir}/flipsid.icns" PROPERTIES
        MACOSX_PACKAGE_LOCATION Resources)
    target_link_libraries(flipsid PRIVATE "-framework CoreVideo" "-framework CoreFoundation" "-framework Foundation")
    set_target_properties(flipsid PROPERTIES
        MACOSX_BUNDLE TRUE
        OUTPUT_NAME flipSID
        MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in"
        MACOSX_BUNDLE_BUNDLE_NAME flipSID
        MACOSX_BUNDLE_GUI_IDENTIFIER com.dahliazone.flipsid
        MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}"
        MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}"
        MACOSX_BUNDLE_ICON_FILE flipsid.icns
    )
    # Finder and the Dock cache a bundle's icon until the bundle itself looks changed;
    # a build only changes files inside it.
    add_custom_command(TARGET flipsid POST_BUILD
        COMMAND touch "$<TARGET_BUNDLE_DIR:flipsid>"
        VERBATIM)
elseif(WIN32)
    set_target_properties(flipsid PROPERTIES WIN32_EXECUTABLE TRUE)
    enable_language(RC)
    set(FLIPSID_ICON_ICO "${iconDir}/flipsid.ico")
    configure_file(windows/flipsid.rc.in "${CMAKE_CURRENT_BINARY_DIR}/flipsid.rc" @ONLY)
    target_sources(flipsid PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/flipsid.rc")
else()
    # X11 has no bundle or resource to take it from: the window gets it at runtime
    # (SDL_SetWindowIcon()). About 4 KB.
    flipsid_embed_files(flipsid
        NAMESPACE flipsid::embedded
        HEADER flipsid/app_icon.h
        FILES
            appIcon32=${iconDir}/flipsid-linux-32.png
            appIcon64=${iconDir}/flipsid-linux-64.png
    )
    target_compile_definitions(flipsid PRIVATE FLIPSID_WINDOW_ICON=1)
endif()

# The top bar's banner unless the user picks their own or turns it off (DESIGN §5);
# 168 x 128 pixels, about 11 KB.
flipsid_embed_files(flipsid
    NAMESPACE flipsid::embedded
    HEADER flipsid/default_banner.h
    FILES
        defaultBanner=${PROJECT_SOURCE_DIR}/assets/banner/flipsid-128.png
)

# The playlists a new settings folder starts with (DESIGN §4.4), copied there on the first
# run; HVSC tunes only. About 185 KB.
set(playlistDir "${PROJECT_SOURCE_DIR}/assets/playlists")
flipsid_embed_files(flipsid
    NAMESPACE flipsid::embedded
    HEADER flipsid/bundled_playlists.h
    FILES
        "playlistEpic=${playlistDir}/Epic C64 SID Collection.json"
        "playlistSoundTest=${playlistDir}/Sound Test SIDs.json"
        "playlistZoo2Sid=${playlistDir}/ZOO 2026-2SID.json"
        "playlistZooBangers=${playlistDir}/ZOO 2026-bangers.json"
        "playlistZooChill=${playlistDir}/ZOO 2026-chill.json"
        "playlistZooCovers=${playlistDir}/ZOO 2026-covers.json"
        "playlistZooGames=${playlistDir}/ZOO 2026-games.json"
        "playlistZooGrue=${playlistDir}/ZOO 2026-grue.json"
        "playlist10YearsHvsc=${playlistDir}/10 Years HVSC.json"
)

flipsid_configure_app(flipsid)
