set(LOG_COMPRESSED_MODULE "")
set(LOG_COMPRESSED_MODULE_CODE_PATH "")
set(BT_ROOT_PATH $ENV{IDF_PATH}/components/bt)
set(LOG_COMPRESSED_SRCS_DIR "${CMAKE_BINARY_DIR}/ble_log/.compressed_srcs")

# default config value for ble mesh module
set(BLE_MESH_CODE_PATH "")
set(BLE_MESH_LOG_INDEX_HEADER "\"\"")
set(BLE_MESH_TAGS "")
set(BLE_MESH_TAGS_PRESERVE "")

# default config value for host module (Bluedroid or NimBLE)
set(HOST_CODE_PATH "")
set(HOST_LOG_INDEX_HEADER "\"\"")
set(BLE_HOST_TAGS "")
set(BLE_HOST_TAGS_PRESERVE "")

# default config value for ble iso module
# (esp_ble_iso owns the unified LOG_* family; consumers like esp_ble_audio
# and future HID-over-ISO compile under the same BLE_ISO module so that all
# share one iso_log_index.h and one log-id counter — no per-consumer
# bookkeeping, no redefinition risk.)
set(BLE_ISO_CODE_PATH "")
set(BLE_ISO_LOG_INDEX_HEADER "\"\"")
set(BLE_ISO_TAGS "")
set(BLE_ISO_TAGS_PRESERVE "")

if(CONFIG_BLE_MESH_COMPRESSED_LOG_ENABLE)
    list(APPEND LOG_COMPRESSED_MODULE "BLE_MESH")

    # update config file
    set(BLE_MESH_CODE_PATH "esp_ble_mesh")
    set(BLE_MESH_LOG_INDEX_HEADER "mesh_log_index.h")
    set(BLE_MESH_LOG_SCRIPT_PATH
        "${CMAKE_CURRENT_LIST_DIR}/scripts/module_scripts/ble_mesh/make_mesh_log_macro.py")
    # update BLE_MESH_TAGS and BLE_MESH_TAGS_PRESERVE
    include(${CMAKE_CURRENT_LIST_DIR}/cmake/ble_mesh_log_tags.cmake)
    if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_MESH_LOG_INDEX_HEADER}")
        file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_MESH_LOG_INDEX_HEADER}" "")
    endif()
    list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH ${BLE_MESH_CODE_PATH})
endif()

if(CONFIG_BLE_ISO_COMPRESSED_LOG_ENABLE)
    list(APPEND LOG_COMPRESSED_MODULE "BLE_ISO")

    # esp_ble_audio sources share the same LOG_* macro family from
    # esp_ble_iso/include/zephyr/logging/log.h; compile them under the
    # single BLE_ISO module so they all hit one iso_log_index.h with one
    # monotonic log-id counter. Future ISO consumers (e.g. HID-over-ISO)
    # extend this list the same way — no per-consumer index header or
    # Kconfig toggle.
    set(BLE_ISO_CODE_PATH "esp_ble_iso" "esp_ble_audio")
    set(BLE_ISO_LOG_INDEX_HEADER "iso_log_index.h")
    set(BLE_ISO_LOG_SCRIPT_PATH
        "${CMAKE_CURRENT_LIST_DIR}/scripts/module_scripts/ble_iso/make_iso_log_macro.py")
    include(${CMAKE_CURRENT_LIST_DIR}/cmake/ble_iso_log_tags.cmake)
    if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_ISO_LOG_INDEX_HEADER}")
        file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_ISO_LOG_INDEX_HEADER}" "")
    endif()
    list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH ${BLE_ISO_CODE_PATH})
endif()

if(CONFIG_BLE_HOST_COMPRESSED_LOG_ENABLE AND CONFIG_BT_BLUEDROID_ENABLED)
    list(APPEND LOG_COMPRESSED_MODULE "BLE_HOST")

    # update config file
    set(HOST_CODE_PATH "host/bluedroid")
    set(HOST_LOG_INDEX_HEADER "host_log_index.h")
    set(BLE_HOST_LOG_SCRIPT_PATH
        "${CMAKE_CURRENT_LIST_DIR}/scripts/module_scripts/bluedroid/make_bluedroid_log_macro.py")

    include(${CMAKE_CURRENT_LIST_DIR}/cmake/ble_host_bluedroid_tags.cmake)
    if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/${HOST_LOG_INDEX_HEADER}")
        file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/${HOST_LOG_INDEX_HEADER}" "")
    endif()
    list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH ${HOST_CODE_PATH})
elseif(CONFIG_BLE_HOST_COMPRESSED_LOG_ENABLE AND CONFIG_BT_NIMBLE_ENABLED)
    list(APPEND LOG_COMPRESSED_MODULE "BLE_HOST")

    set(HOST_CODE_PATH "host/nimble/nimble/nimble/host")
    set(HOST_LOG_INDEX_HEADER "nimble_log_index.h")
    set(BLE_HOST_LOG_SCRIPT_PATH
        "${CMAKE_CURRENT_LIST_DIR}/scripts/module_scripts/nimble/make_nimble_log_macro.py")
    set(BLE_HOST_TAGS "MODLOG_DFLT, BLE_HS_LOG")
    set(BLE_HOST_TAGS_PRESERVE "")

    if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/${HOST_LOG_INDEX_HEADER}")
        file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/${HOST_LOG_INDEX_HEADER}" "")
    endif()
    list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH ${HOST_CODE_PATH})
endif()

if(BLE_COMPRESSED_LIB_LOG_BUILD)
    if(NOT (BLE_COMPRESSED_LIB_NAME AND BLE_COMPRESSED_LIB_CODE_DIR AND BLE_COMPRESSED_LIB_LOG_TAGS))
        message(FATAL_ERROR "Invalid settings")
    else()
        message("Building compressed log for ${BLE_COMPRESSED_LIB_NAME}")
    endif()
    list(APPEND LOG_COMPRESSED_MODULE ${BLE_COMPRESSED_LIB_NAME})
    if(NOT EXISTS "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_COMPRESSED_LIB_LOG_INDEX_HEADER}")
        file(WRITE "${CMAKE_BINARY_DIR}/ble_log/include/${BLE_COMPRESSED_LIB_LOG_INDEX_HEADER}" "")
    endif()
    list(APPEND LOG_COMPRESSED_MODULE_CODE_PATH ${BLE_COMPRESSED_LIB_CODE_DIR})

    string(REPLACE ";" "," BLE_COMPRESSED_LIB_CODE_DIR "${BLE_COMPRESSED_LIB_CODE_DIR}")
    string(REPLACE ";" "," BLE_COMPRESSED_LIB_LOG_TAGS "${BLE_COMPRESSED_LIB_LOG_TAGS}")
    string(REPLACE ";" "," BLE_COMPRESSED_LIB_LOG_TAGS_PRESERVE "${BLE_COMPRESSED_LIB_LOG_TAGS_PRESERVE}")
else()
    set(BLE_COMPRESSED_LIB_NAME "placeholder")
endif()


if(LOG_COMPRESSED_MODULE)
    # When building the library, ble_log_compression.c and its dependencies are not needed
    if(NOT BLE_COMPRESSED_LIB_LOG_BUILD)
        list(APPEND srcs "common/ble_log/extension/log_compression/ble_log_compression.c")
        list(APPEND include_dirs "${CMAKE_BINARY_DIR}/ble_log/include")
    endif()
    if(NOT CMAKE_VERSION VERSION_LESS 3.15.0)
        set(Python3_FIND_STRATEGY LOCATION)
        find_package(Python3 COMPONENTS Interpreter)
        if(Python3_Interpreter_FOUND)
            set(BLE_PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
        endif()
    else()
        find_package(PythonInterp 3)
        if(PYTHONINTERP_FOUND)
            set(BLE_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE})
        endif()
    endif()

    if(BLE_PYTHON_EXECUTABLE)
        set(PYTHON_SCRIPT ${BT_ROOT_PATH}/common/ble_log/extension/log_compression/scripts/ble_log_compress.py)

        set(compressed_srcs "")
        set(uncompressed_srcs "")
        set(compressed_srcs_with_abs_path "")

        execute_process(COMMAND ${BLE_PYTHON_EXECUTABLE}
                                ${BT_ROOT_PATH}/common/ble_log/extension/log_compression/scripts/env_check.py
                            RESULT_VARIABLE result
                            OUTPUT_VARIABLE   out
                            ERROR_VARIABLE    err
                        )

        if(NOT ${result} EQUAL 0)
            message(WARNING "${err}")
            message(WARNING "Exit this log compression due to failure of environment check")
            set(LOG_COMPRESS_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE)
            set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
            return()
        endif()

        set(CONFIG_FILE_PATH "${CMAKE_BINARY_DIR}/ble_log/module_info.yml")
        if(NOT EXISTS "${CONFIG_FILE_PATH}")
            file(WRITE "${CMAKE_BINARY_DIR}/ble_log/module_info.yml")
        endif()
        set(YML_IN  "${BT_ROOT_PATH}/common/ble_log/extension/log_compression/scripts/configs/module_info.yml.in")

        # BLE_ISO has multiple code paths; rewrite CMake list ";" → YAML ", "
        # into a sibling variable so BLE_ISO_CODE_PATH itself stays a CMake
        # list usable by any later code that wants to iterate or append.
        string(REPLACE ";" ", " BLE_ISO_CODE_PATH_YAML "${BLE_ISO_CODE_PATH}")

        configure_file(${YML_IN} ${CONFIG_FILE_PATH} @ONLY)

        string(REPLACE ";" "|" MODULE_CODE_PATH "${LOG_COMPRESSED_MODULE_CODE_PATH}")
        set(MATCH_PATTERN "(${MODULE_CODE_PATH}).+\\.c")
        foreach(src ${srcs})
            # Normalize absolute paths to relative paths (relative to CODE_BASE_PATH)
            # so that pattern matching works and .compressed_srcs/ has a clean layout
            if(IS_ABSOLUTE "${src}")
                get_filename_component(src "${src}" ABSOLUTE)
                file(RELATIVE_PATH src "${CODE_BASE_PATH}" "${src}")
            endif()
            if(src MATCHES ${MATCH_PATTERN})
                set(dest "${LOG_COMPRESSED_SRCS_DIR}/${src}")
                file(WRITE "${dest}" "")
                list(APPEND compressed_srcs ${src})
                list(APPEND compressed_srcs_with_abs_path "${dest}")
            else()
                list(APPEND uncompressed_srcs ${src})
            endif()
        endforeach()
        string(REPLACE "|" ";" LOG_COMPRESSED_MODULE_CODE_PATH "${MODULE_CODE_PATH}")

        # Some header files of NIMBLE are not added to include_dirs,
        # but rely on relative path searches. This will cause the header
        # files to be found due to the change in the source code location
        # after using the log compression scheme.
        # Therefore, these paths are added to include_dirs here to avoid
        # unfinished compilation errors.
        if(CONFIG_BT_NIMBLE_ENABLED)
            list(APPEND include_dirs
                "host/nimble/nimble/nimble/host/src"
                "host/nimble/nimble/nimble/host/store/config/src")
        endif()

        if(BLE_COMPRESSED_LIB_LOG_BUILD)
            execute_process(COMMAND ${BLE_PYTHON_EXECUTABLE} ${PYTHON_SCRIPT}
                                compress
                                --compressed_srcs_path "${LOG_COMPRESSED_SRCS_DIR}"
                                --build_path "${CMAKE_BINARY_DIR}"
                                --module "${LOG_COMPRESSED_MODULE}"
                                --code_base_path "${CODE_BASE_PATH}"
                                --srcs "${compressed_srcs}"
                                RESULT_VARIABLE result
                                OUTPUT_VARIABLE   out
                                ERROR_VARIABLE    err)
            if(NOT ${result} EQUAL 0)
                message(WARNING "${err}")
                message(WARNING "Exit this log compression due to failure of compression")
                set(LOG_COMPRESS_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE)
                set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
                return()
            endif()
        else()
            add_custom_target(ble_log_compression ALL
                COMMAND ${BLE_PYTHON_EXECUTABLE} ${PYTHON_SCRIPT}
                    compress
                    --compressed_srcs_path "${LOG_COMPRESSED_SRCS_DIR}"
                    --build_path "${CMAKE_BINARY_DIR}"
                    --module "'${LOG_COMPRESSED_MODULE}'"
                    --code_base_path "${CODE_BASE_PATH}"
                    --srcs "'${compressed_srcs}'"
                DEPENDS ${compressed_srcs_with_abs_path} ${PYTHON_SCRIPT}
                COMMENT "Log compression is being performed, please wait..."
                WORKING_DIRECTORY ${BT_ROOT_PATH}
                USES_TERMINAL
            )
        endif()

        # List of files with their compile flags: format "file_path|flag1;flag2;..."
        set(FILES_WITH_COMPILE_FLAGS "")

        function(add_flags_if_in_list file file_list compile_flags)
            set(PROCESSED OFF PARENT_SCOPE)
            foreach(item IN LISTS file_list)
                if(item STREQUAL file)
                    set(abs_file_path "${LOG_COMPRESSED_SRCS_DIR}/${file}")
                    # Append to global list with format: "file_path|compile_flags"
                    list(APPEND FILES_WITH_COMPILE_FLAGS "${abs_file_path}|${compile_flags}")
                    set(FILES_WITH_COMPILE_FLAGS "${FILES_WITH_COMPILE_FLAGS}" PARENT_SCOPE)
                    message("set pro ${LOG_COMPRESSED_SRCS_DIR}/${file} ${compile_flags}")
                    set(PROCESSED ON PARENT_SCOPE)
                    break()
                endif()
            endforeach()
        endfunction()

        foreach(src ${compressed_srcs})
            set(PROCESSED OFF)
            if(CONFIG_BT_BLUEDROID_ENABLED)
                    set(files_with_compile_flags
                        "host/bluedroid/bta/gatt/bta_gattc_act.c"
                        "host/bluedroid/bta/gatt/bta_gattc_cache.c"
                        "host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c"
                        "host/bluedroid/btc/profile/std/gatt/btc_gatts.c")
                add_flags_if_in_list("${src}"
                                     "${files_with_compile_flags}"
                                     "-Wno-address-of-packed-member")

                if(NOT CMAKE_BUILD_EARLY_EXPANSION)
                    set(jump_table_opts "-fjump-tables")
                    if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang") )
                        set(jump_table_opts "${jump_table_opts} -ftree-switch-conversion")
                    endif()
                    set(files_with_compile_flags
                        "host/bluedroid/bta/hf_ag/bta_ag_cmd.c"
                        "host/bluedroid/btc/profile/std/gap/btc_gap_ble.c"
                    )
                    add_flags_if_in_list("${src}"
                                         "${files_with_compile_flags}"
                                         "${jump_table_opts}")
                endif()

                if((CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 15.0) OR
                    CMAKE_C_COMPILER_ID MATCHES "Clang")
                    set(files_with_compile_flags "host/bluedroid/device/controller.c")
                    add_flags_if_in_list("${src}"
                                         "${files_with_compile_flags}"
                                         "-Wno-unterminated-string-initialization")
                endif()
            endif()
            if(CONFIG_BT_NIMBLE_ENABLED)
                if(CONFIG_BT_NIMBLE_MESH)
                    message(ERROR "The current log compression scheme does not support NIMBLE MESH")
                endif()
            endif()
            if(NOT PROCESSED)
                set_source_files_properties("${LOG_COMPRESSED_SRCS_DIR}/${src}"
                    PROPERTIES GENERATED TRUE
                    OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ble_log_compression
                )
            endif()
        endforeach()

        set(LOG_COMPRESSION_TARGET ble_log_compression PARENT_SCOPE)
        # set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
        set(LOG_COMPRESS_SRCS "${compressed_srcs_with_abs_path};${uncompressed_srcs}" PARENT_SCOPE)
        set(LOG_COMPRESS_FILES_WITH_FLAGS "${FILES_WITH_COMPILE_FLAGS}" PARENT_SCOPE)
        if(NOT BLE_COMPRESSED_LIB_LOG_BUILD)
            list(APPEND include_dirs "common/ble_log/extension/log_compression/include")
        endif()
        list(APPEND include_dirs "${CMAKE_BINARY_DIR}/ble_log/include")
        set(LOG_COMPRESS_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE)
    else()
        set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
        message("Python 3 used for log compressing not found")
    endif()
else()
    set(LOG_COMPRESSION_TARGET "" PARENT_SCOPE)
    message(STATUS "No module enabled for log compress")
endif()
