cmake_minimum_required(VERSION 3.21)

project(alarcade-mc-launcher VERSION ${ALARCADE_VERSION} LANGUAGES C CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# ALARCADE_BACKEND (android | windows) is chosen in the top-level CMakeLists.txt.

find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Network Quick QuickControls2 Svg Concurrent)

set(LAUNCHER_VERSION_NAME "${PROJECT_VERSION}" CACHE STRING "Version name shown in the app")
set(LAUNCHER_VERSION_CODE "1" CACHE STRING "Integer build number, used for changelog and update checks")
set(LAUNCHER_CHANGE_LOG "" CACHE STRING "Changelog shown after an update")
set(ALARCADE_UPDATE_FEED_URL "" CACHE STRING "HTTPS URL of the release feed (latest.json); empty disables update checks")
option(LAUNCHER_DISABLE_DEV_MODE "Hide the developer settings unless started with --enable-devmode" ON)

# ---------------------------------------------------------------- shared
set(SHARED_SOURCES
    main.cpp
    launcherapp.cpp launcherapp.h
    launchersettings.h
    branding.h
    qmlurlutils.h
    stdio_helper.cpp stdio_helper.h
    updatechecker.cpp updatechecker.h
    secretstore.h
    core/platform.cpp core/platform.h
    core/jobqueue.cpp core/jobqueue.h
    core/ziputil.cpp core/ziputil.h
    core/leveldat.cpp core/leveldat.h
    core/worldmanager.cpp core/worldmanager.h
    core/packmanager.cpp core/packmanager.h
    third_party/miniz/miniz.c third_party/miniz/miniz.h
)
if(APPLE)
    list(APPEND SHARED_SOURCES launcherapp_osx.mm macos/secretstore_mac.mm)
elseif(WIN32)
    list(APPEND SHARED_SOURCES windows/secretstore_win.cpp)
else()
    list(APPEND SHARED_SOURCES secretstore_settings.cpp)
endif()
if(WIN32)
    list(APPEND SHARED_SOURCES windows/crash_handler_win.cpp crash_handler.h)
else()
    list(APPEND SHARED_SOURCES crash_handler.cpp crash_handler.h)
endif()

# Resources are collected by folder: shared UI, then the backend's own screens.
file(GLOB SHARED_RESOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS
    qml/*.qml qml/Components/*.qml qml/Components/*.js qml/Components/qmldir qml/pages/*.qml
    icons/*.svg fonts/*.ttf Resources/*.png Resources/*.svg)
list(APPEND SHARED_RESOURCE_FILES LICENSE)
set(QML_RESOURCES)

# ---------------------------------------------------------------- backends
if(ALARCADE_BACKEND STREQUAL "android")
    find_package(OpenSSL REQUIRED COMPONENTS Crypto)
    set(BACKEND_SOURCES
        googleloginhelper.cpp googleloginhelper.h googleaccount.h
        googleplayapi.cpp googleplayapi.h
        googleversionchannel.cpp googleversionchannel.h
        googleapkdownloadtask.cpp googleapkdownloadtask.h
        downloadtask.cpp downloadtask.h
        versionmanager.cpp versionmanager.h
        archivalversionlist.cpp archivalversionlist.h
        apkextractiontask.cpp apkextractiontask.h
        zipextractiontask.cpp zipextractiontask.h
        gamelauncher.cpp gamelauncher.h
        profilemanager.cpp profilemanager.h
        modmanager.cpp modmanager.h
        updatemanager.cpp updatemanager.h
        troubleshooter.cpp troubleshooter.h
        supportedandroidabis.cpp supportedandroidabis.h
        cpuid.cpp cpuid.h
        gamepad.h
        encryption.h encryption.cpp
        encrypted_file_login_cache.cpp encrypted_file_login_cache.h
    )
    set(BACKEND_LIBS mcpelauncher-extract-lib mcpelauncher-common mcpelauncher-apkinfo file-util gplayapi OpenSSL::Crypto)
    if(APPLE)
        list(APPEND BACKEND_SOURCES supportedandroidabis.mm macos/googlesigninwindow.h macos/googlesigninwindow_mac.mm)
        list(APPEND BACKEND_LIBS "-framework WebKit")
    else()
        list(APPEND BACKEND_LIBS playdl-signin-ui-qt-lib)
    endif()
    file(GLOB BACKEND_RESOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS qml/android/*.qml)

    set(LAUNCHER_VERSIONDB_PATH "" CACHE STRING "Local mcpelauncher-versiondb checkout to embed")
    set(LAUNCHER_VERSIONDB_URL "https://raw.githubusercontent.com/minecraft-linux/mcpelauncher-versiondb/HEAD" CACHE STRING "Remote versiondb used to check game version compatibility")
    if(NOT "${LAUNCHER_VERSIONDB_PATH}" STREQUAL "")
        foreach(abi armeabi-v7a x86 arm64-v8a x86_64)
            configure_file("${LAUNCHER_VERSIONDB_PATH}/versions.${abi}.json.min" ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
        endforeach()
        configure_file(archivalversionlist.qrc ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
        list(APPEND QML_RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/archivalversionlist.qrc)
    endif()
elseif(ALARCADE_BACKEND STREQUAL "windows")
    if(WIN32)
        set(BACKEND_SOURCES windows/bedrockinstallations.cpp windows/bedrockinstallations.h)
    else()
        # UI preview of the Windows edition on other platforms (development only).
        set(BACKEND_SOURCES windows/bedrockinstallations_preview.cpp windows/bedrockinstallations.h)
    endif()
    set(BACKEND_LIBS)
    file(GLOB BACKEND_RESOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS qml/windows/*.qml)
else()
    message(FATAL_ERROR "Unknown ALARCADE_BACKEND '${ALARCADE_BACKEND}'")
endif()

# ---------------------------------------------------------------- translations
set(TRANSLATION_SOURCES)
find_package(Qt6 COMPONENTS LinguistTools)
if(Qt6LinguistTools_FOUND)
    file(GLOB TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
    qt6_add_translation(QM_FILES ${TS_FILES})
    set(TRANSLATIONS_QRC "${CMAKE_CURRENT_BINARY_DIR}/translations.qrc")
    file(WRITE ${TRANSLATIONS_QRC} "<RCC>\n  <qresource prefix=\"/translations\">\n")
    foreach(QM_FILE IN LISTS QM_FILES)
        get_filename_component(QM_NAME "${QM_FILE}" NAME)
        file(APPEND ${TRANSLATIONS_QRC} "    <file>${QM_NAME}</file>\n")
    endforeach()
    file(APPEND ${TRANSLATIONS_QRC} "  </qresource>\n</RCC>\n")
    # The .qm files are generated, so AUTORCC compiles this qrc after they exist.
    set(TRANSLATION_SOURCES ${TRANSLATIONS_QRC} ${QM_FILES})
endif()

# ---------------------------------------------------------------- target
set(APP_TARGET alarcade-mc-launcher)
set(COMPILED_RESOURCES)
if(QML_RESOURCES)
    qt6_add_resources(COMPILED_RESOURCES ${QML_RESOURCES})
endif()
add_executable(${APP_TARGET} ${SHARED_SOURCES} ${BACKEND_SOURCES} ${COMPILED_RESOURCES} ${TRANSLATION_SOURCES})
qt6_add_resources(${APP_TARGET} "app_ui" PREFIX "/" FILES ${SHARED_RESOURCE_FILES} ${BACKEND_RESOURCE_FILES})

if(WIN32)
    set(ALARCADE_ICON_PATH "${CMAKE_SOURCE_DIR}/branding/app.ico")
    set(ALARCADE_MANIFEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/windows/app.manifest")
    configure_file(windows/app.rc.in ${CMAKE_CURRENT_BINARY_DIR}/app.rc @ONLY)
    target_sources(${APP_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/app.rc)
    set_target_properties(${APP_TARGET} PROPERTIES WIN32_EXECUTABLE ON OUTPUT_NAME "AL-Arcade MC Launcher")
endif()

target_link_libraries(${APP_TARGET} PRIVATE
    Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Network Qt6::Quick Qt6::QuickControls2 Qt6::Svg Qt6::Concurrent
    ${BACKEND_LIBS})
if(APPLE)
    target_link_libraries(${APP_TARGET} PRIVATE "-framework AppKit" "-framework Security")
    # The Objective-C++ sources added by this project use ARC; upstream's do not.
    set_source_files_properties(macos/googlesigninwindow_mac.mm macos/secretstore_mac.mm PROPERTIES COMPILE_OPTIONS "-fobjc-arc")
elseif(WIN32)
    target_link_libraries(${APP_TARGET} PRIVATE advapi32 crypt32 shell32 ole32)
endif()

string(TOUPPER "${ALARCADE_BACKEND}" BACKEND_UPPER)
target_compile_definitions(${APP_TARGET} PRIVATE
    ALARCADE_BACKEND_${BACKEND_UPPER}
    ALARCADE_BACKEND_NAME="${ALARCADE_BACKEND}"
    LAUNCHER_VERSION_NAME="${LAUNCHER_VERSION_NAME}"
    LAUNCHER_VERSION_CODE="${LAUNCHER_VERSION_CODE}"
    LAUNCHER_VERSION_COMPAT=${LAUNCHER_VERSION_COMPAT}
    LAUNCHER_ENABLE_GOOGLE_PLAY_LICENCE_CHECK
    LAUNCHER_MACOS_HAVE_ARMLAUNCHER
)
if(ALARCADE_BACKEND STREQUAL "android" AND NOT "${LAUNCHER_VERSIONDB_URL}" STREQUAL "")
    target_compile_definitions(${APP_TARGET} PRIVATE LAUNCHER_VERSIONDB_URL="${LAUNCHER_VERSIONDB_URL}")
endif()
if(NOT "${ALARCADE_UPDATE_FEED_URL}" STREQUAL "")
    target_compile_definitions(${APP_TARGET} PRIVATE ALARCADE_UPDATE_FEED_URL="${ALARCADE_UPDATE_FEED_URL}")
endif()
if(NOT "${LAUNCHER_CHANGE_LOG}" STREQUAL "")
    target_compile_definitions(${APP_TARGET} PRIVATE LAUNCHER_CHANGE_LOG="${LAUNCHER_CHANGE_LOG}")
endif()
if(LAUNCHER_DISABLE_DEV_MODE)
    target_compile_definitions(${APP_TARGET} PRIVATE LAUNCHER_DISABLE_DEV_MODE)
endif()

install(TARGETS ${APP_TARGET} RUNTIME DESTINATION bin)
