include(ExternalProject)

find_package(Python3 REQUIRED COMPONENTS Interpreter)
find_package(Threads REQUIRED)
find_program(TIRTC_THIRD_MAKE_PROGRAM NAMES gmake make REQUIRED)
find_program(TIRTC_THIRD_FALSE_PROGRAM NAMES false REQUIRED)

include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/FFmpegProfile.cmake")

set(_ffmpeg_source_dir "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(_ffmpeg_profile_file "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FFmpegProfile.cmake")
set(_ffmpeg_verifier "${CMAKE_CURRENT_SOURCE_DIR}/tools/verify_build_profile.py")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/METADATA.json" _ffmpeg_metadata_json)
string(JSON _ffmpeg_revision GET "${_ffmpeg_metadata_json}" upstream revision)
string(JSON
    _ffmpeg_metadata_source_tree_sha256
    GET "${_ffmpeg_metadata_json}" source tree_sha256
)

if(NOT CMAKE_NM)
    find_program(CMAKE_NM NAMES llvm-nm nm REQUIRED)
endif()

file(SHA256 "${_ffmpeg_profile_file}" _ffmpeg_profile_sha256)
file(SHA256 "${_ffmpeg_verifier}" _ffmpeg_verifier_sha256)
file(SHA256 "${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt" _ffmpeg_wrapper_sha256)

set(_ffmpeg_platform_options)
if(ANDROID)
    list(APPEND _ffmpeg_platform_options
        --enable-cross-compile
        --arch=aarch64
        --target-os=android
    )
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
    list(APPEND _ffmpeg_platform_options
        --enable-cross-compile
        --arch=arm64
        --target-os=darwin
    )
elseif(CMAKE_SYSTEM_NAME STREQUAL "OHOS")
    list(APPEND _ffmpeg_platform_options
        --enable-cross-compile
        --arch=aarch64
        --target-os=android
    )
elseif(APPLE)
    string(TOLOWER "${CMAKE_OSX_ARCHITECTURES}" _ffmpeg_apple_architectures)
    string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _ffmpeg_apple_processor)
    if(
        _ffmpeg_apple_architectures MATCHES "^(x86_64|amd64)$"
        OR (
            _ffmpeg_apple_architectures STREQUAL ""
            AND _ffmpeg_apple_processor MATCHES "^(x86_64|amd64)$"
        )
    )
        list(APPEND _ffmpeg_platform_options
            --enable-cross-compile
            --arch=x86_64
            --target-os=darwin
            --disable-x86asm
        )
    elseif(
        _ffmpeg_apple_architectures STREQUAL "arm64"
        OR (
            _ffmpeg_apple_architectures STREQUAL ""
            AND _ffmpeg_apple_processor MATCHES "^(arm64|aarch64)$"
        )
    )
        list(APPEND _ffmpeg_platform_options
            --arch=arm64
            --target-os=darwin
        )
    else()
        message(FATAL_ERROR
            "Runtime FFmpeg Apple build requires one explicit arm64 or x86_64 "
            "architecture; got `${CMAKE_OSX_ARCHITECTURES}` / "
            "`${CMAKE_SYSTEM_PROCESSOR}`"
        )
    endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    list(APPEND _ffmpeg_platform_options
        --arch=x86_64
        --target-os=linux
        --disable-x86asm
    )
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
    list(APPEND _ffmpeg_platform_options
        --enable-cross-compile
        --arch=x86_64
        --target-os=mingw32
        --disable-x86asm
    )
else()
    message(FATAL_ERROR
        "Runtime FFmpeg source build does not support "
        "${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}"
    )
endif()

tirtc_third_external_cache(
    NAME ffmpeg
    SOURCE_DIR "${_ffmpeg_source_dir}"
    OPTIONS
        ${TIRTC_FFMPEG_COMMON_CONFIGURE_OPTIONS}
        ${_ffmpeg_platform_options}
        "pkg-config=${TIRTC_THIRD_FALSE_PROGRAM}"
        "profile=${_ffmpeg_profile_sha256}"
        "verifier=${_ffmpeg_verifier_sha256}"
        "wrapper=${_ffmpeg_wrapper_sha256}"
    OUTPUT_PREFIX _ffmpeg_cache
)

set(_ffmpeg_configure_options
    ${TIRTC_FFMPEG_COMMON_CONFIGURE_OPTIONS}
    ${_ffmpeg_platform_options}
    "--pkg-config=${TIRTC_THIRD_FALSE_PROGRAM}"
    "--cc=${_ffmpeg_cache_CC}"
    "--cxx=${_ffmpeg_cache_CXX}"
    "--ar=${CMAKE_AR}"
    "--ranlib=${CMAKE_RANLIB}"
    "--strip=${CMAKE_STRIP}"
    "--nm=${CMAKE_NM}"
    "--extra-cflags=${_ffmpeg_cache_C_FLAGS} -Os"
    "--extra-ldflags=${_ffmpeg_cache_LD_FLAGS}"
)
if(CMAKE_SYSROOT)
    list(APPEND _ffmpeg_configure_options "--sysroot=${CMAKE_SYSROOT}")
elseif(APPLE AND CMAKE_OSX_SYSROOT)
    list(APPEND _ffmpeg_configure_options "--sysroot=${CMAKE_OSX_SYSROOT}")
endif()
if(
    APPLE
    AND NOT CMAKE_SYSTEM_NAME STREQUAL "iOS"
    AND NOT _ffmpeg_cache_PLATFORM STREQUAL "macos-x64"
)
    list(APPEND _ffmpeg_configure_options
        "--host-cc=${_ffmpeg_cache_CC}"
        "--host-cflags=${_ffmpeg_cache_C_FLAGS}"
    )
endif()

set(_ffmpeg_build_dir "${_ffmpeg_cache_ROOT}/build")
set(_ffmpeg_stage_dir "${_ffmpeg_cache_ROOT}/stage")
set(_ffmpeg_manifest "${_ffmpeg_cache_ROOT}/build-manifest.json")
set(_ffmpeg_toolchain_sha256 "")
if(CMAKE_TOOLCHAIN_FILE AND EXISTS "${CMAKE_TOOLCHAIN_FILE}")
    file(SHA256 "${CMAKE_TOOLCHAIN_FILE}" _ffmpeg_toolchain_sha256)
endif()
set(_ffmpeg_sdk_identity "${CMAKE_SYSROOT}")
set(_ffmpeg_deployment_identity "${CMAKE_SYSTEM_VERSION}")
if(APPLE)
    set(_ffmpeg_sdk_identity "${CMAKE_OSX_SYSROOT}")
    set(_ffmpeg_deployment_identity "${CMAKE_OSX_DEPLOYMENT_TARGET}")
elseif(ANDROID)
    set(_ffmpeg_deployment_identity "${ANDROID_PLATFORM}")
elseif(CMAKE_SYSTEM_NAME STREQUAL "OHOS")
    set(_ffmpeg_deployment_identity "${OHOS_PLATFORM}")
endif()
set(_ffmpeg_library_paths)
foreach(_ffmpeg_library IN LISTS TIRTC_FFMPEG_LIBRARIES)
    list(APPEND _ffmpeg_library_paths "${_ffmpeg_stage_dir}/lib/lib${_ffmpeg_library}.a")
endforeach()

set(_ffmpeg_probe_args)
if(NOT CMAKE_CROSSCOMPILING
   AND (_ffmpeg_cache_PLATFORM MATCHES "^macos-(arm64|x64)$"
        OR _ffmpeg_cache_PLATFORM STREQUAL "linux-x64"))
    list(APPEND _ffmpeg_probe_args
        --run-probe
        "--cc=${_ffmpeg_cache_CC}"
        "--c-flags=${_ffmpeg_cache_C_FLAGS}"
        "--ld-flags=${_ffmpeg_cache_LD_FLAGS}"
    )
endif()

file(MAKE_DIRECTORY "${_ffmpeg_stage_dir}/include" "${_ffmpeg_stage_dir}/lib")

if(_ffmpeg_cache_REUSE_COMPLETED_CACHE)
    add_custom_target(tirtc_third_ffmpeg_external)
else()
    ExternalProject_Add(
        tirtc_third_ffmpeg_external
        PREFIX "${_ffmpeg_cache_ROOT}/project"
        STAMP_DIR "${_ffmpeg_cache_ROOT}/stamp"
        TMP_DIR "${_ffmpeg_cache_ROOT}/tmp"
        SOURCE_DIR "${_ffmpeg_source_dir}"
        BINARY_DIR "${_ffmpeg_build_dir}"
        INSTALL_DIR "${_ffmpeg_stage_dir}"
        DOWNLOAD_COMMAND ""
        UPDATE_COMMAND ""
        PATCH_COMMAND ""
        CONFIGURE_COMMAND
            "${CMAKE_COMMAND}" -E env
            "PKG_CONFIG_PATH="
            "PKG_CONFIG_LIBDIR="
            "${_ffmpeg_source_dir}/configure"
            ${_ffmpeg_configure_options}
        BUILD_COMMAND
            "${TIRTC_THIRD_MAKE_PROGRAM}"
            "-j${_ffmpeg_cache_BUILD_JOBS}"
        INSTALL_COMMAND
            "${TIRTC_THIRD_MAKE_PROGRAM}"
            "DESTDIR=<INSTALL_DIR>"
            install-libs
            install-headers
            COMMAND
            "${Python3_EXECUTABLE}"
            "${_ffmpeg_verifier}"
            --build-dir "<BINARY_DIR>"
            --stage-dir "<INSTALL_DIR>"
            --manifest "${_ffmpeg_manifest}"
            "--nm=${CMAKE_NM}"
            "--platform=${_ffmpeg_cache_PLATFORM}"
            "--revision=${_ffmpeg_revision}"
            "--source-tree-sha256=${_ffmpeg_metadata_source_tree_sha256}"
            "--profile-sha256=${_ffmpeg_profile_sha256}"
            "--fingerprint=${_ffmpeg_cache_FINGERPRINT}"
            "--compiler-id=${CMAKE_C_COMPILER_ID}"
            "--compiler-version=${CMAKE_C_COMPILER_VERSION}"
            "--compiler-target=${CMAKE_C_COMPILER_TARGET}"
            "--cc=${_ffmpeg_cache_CC}"
            "--cxx=${_ffmpeg_cache_CXX}"
            "--ar=${CMAKE_AR}"
            "--ranlib=${CMAKE_RANLIB}"
            "--nm-tool=${CMAKE_NM}"
            "--strip=${CMAKE_STRIP}"
            "--make=${TIRTC_THIRD_MAKE_PROGRAM}"
            "--toolchain-file=${CMAKE_TOOLCHAIN_FILE}"
            "--toolchain-file-sha256=${_ffmpeg_toolchain_sha256}"
            "--sdk-sysroot=${_ffmpeg_sdk_identity}"
            "--deployment-target=${_ffmpeg_deployment_identity}"
            "--build-type=${CMAKE_BUILD_TYPE}"
            "--c-flags=${_ffmpeg_cache_C_FLAGS}"
            "--cxx-flags=${_ffmpeg_cache_CXX_FLAGS}"
            "--ld-flags=${_ffmpeg_cache_LD_FLAGS}"
            "--cmake-generator=${CMAKE_GENERATOR}"
            "--cmake-version=${CMAKE_VERSION}"
            ${_ffmpeg_probe_args}
        BUILD_BYPRODUCTS
            ${_ffmpeg_library_paths}
            "${_ffmpeg_manifest}"
        USES_TERMINAL_CONFIGURE TRUE
        USES_TERMINAL_BUILD TRUE
        USES_TERMINAL_INSTALL TRUE
    )
endif()

set(_ffmpeg_imported_targets)
foreach(_ffmpeg_library IN LISTS TIRTC_FFMPEG_LIBRARIES)
    set(_ffmpeg_target "tirtc_third_ffmpeg_${_ffmpeg_library}")
    add_library("${_ffmpeg_target}" STATIC IMPORTED GLOBAL)
    set_target_properties(
        "${_ffmpeg_target}"
        PROPERTIES
            IMPORTED_LOCATION "${_ffmpeg_stage_dir}/lib/lib${_ffmpeg_library}.a"
            INTERFACE_INCLUDE_DIRECTORIES "${_ffmpeg_stage_dir}/include"
            INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_ffmpeg_stage_dir}/include"
    )
    add_dependencies("${_ffmpeg_target}" tirtc_third_ffmpeg_external)
    list(APPEND _ffmpeg_imported_targets "${_ffmpeg_target}")
endforeach()

add_library(tirtc_third::ffmpeg INTERFACE IMPORTED GLOBAL)
add_dependencies(tirtc_third::ffmpeg tirtc_third_ffmpeg_external)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    list(JOIN _ffmpeg_imported_targets "," _ffmpeg_link_group_items)
    target_link_libraries(
        tirtc_third::ffmpeg
        INTERFACE
            "$<LINK_GROUP:RESCAN,${_ffmpeg_link_group_items}>"
    )
else()
    target_link_libraries(tirtc_third::ffmpeg INTERFACE ${_ffmpeg_imported_targets})
endif()
target_link_libraries(tirtc_third::ffmpeg INTERFACE Threads::Threads)

if(WIN32)
    target_link_libraries(tirtc_third::ffmpeg INTERFACE bcrypt)
endif()

if(UNIX AND NOT APPLE)
    find_library(_ffmpeg_math_library m REQUIRED)
    target_link_libraries(tirtc_third::ffmpeg INTERFACE ${_ffmpeg_math_library})
endif()

set_property(
    TARGET tirtc_third::ffmpeg
    PROPERTY TIRTC_FFMPEG_BUILD_MANIFEST_FILE "${_ffmpeg_manifest}"
)
set_property(
    TARGET tirtc_third::ffmpeg
    PROPERTY TIRTC_THIRD_LINK_FILES "${_ffmpeg_library_paths}"
)

install(
    FILES "${_ffmpeg_manifest}"
    DESTINATION "${CMAKE_INSTALL_DATADIR}/licenses/tirtc/third_party/ffmpeg"
)
