# DAPSS (Device Attachment Pipe Specification Source) preprocessing module
# This module provides functionality to preprocess .dapss files to .daps files
# using the C preprocessor, respecting include directories and target dependencies.
#
# Usage:
#   add_daps_target(target_name SOURCES file1.dapss file2.dapss ...)
#   register_daps_target(target_name)  # In subdirectories
#   add_all_daps_dependencies()        # In main CMakeLists.txt
#
# Examples:
#   add_daps_target(device_specs SOURCES devices/avia0.dapss devices/win0.dapss)
#   register_daps_target(device_specs)
#   add_all_daps_dependencies()
#
# The preprocessed .daps files will be placed in ${CMAKE_CURRENT_BINARY_DIR}/

# Function to add a DAPSS preprocessing target
# Usage: add_daps_target(target_name SOURCES file1.dapss file2.dapss ...)
function(add_daps_target target_name)
    set(options)
    set(oneValueArgs)
    set(multiValueArgs SOURCES)
    cmake_parse_arguments(DAPS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

    if(NOT DAPS_SOURCES)
        message(FATAL_ERROR "add_daps_target: No SOURCES specified for target ${target_name}")
    endif()

    # Use binary directory directly for processed files
    # This ensures files are created in the same directory as the target
    set(output_dir "${CMAKE_CURRENT_BINARY_DIR}")

    # List to store all output files
    set(output_files)

    # Process each source file
    foreach(source_file ${DAPS_SOURCES})
        # Get the base name without extension
        get_filename_component(base_name ${source_file} NAME_WE)
        get_filename_component(source_dir ${source_file} DIRECTORY)

        # Create output file path
        set(output_file "${output_dir}/${base_name}.daps")
        list(APPEND output_files ${output_file})

        # Get include directories from current directory and target
        get_directory_property(include_dirs INCLUDE_DIRECTORIES)

        # Build include flags
        set(include_flags)
        foreach(include_dir ${include_dirs})
            list(APPEND include_flags "-I${include_dir}")
        endforeach()

        # Add current source directory to includes if it's not already there
        if(source_dir)
            list(APPEND include_flags "-I${source_dir}")
        endif()

        # Convert list to space-separated string
        string(REPLACE ";" " " include_flags_str "${include_flags}")

        # Find C compiler if not already set
        if(NOT CMAKE_C_COMPILER)
            find_program(CMAKE_C_COMPILER gcc cc clang)
            if(NOT CMAKE_C_COMPILER)
                message(FATAL_ERROR "No C compiler found for DAPSS preprocessing")
            endif()
        endif()

        # Create custom command to preprocess the file
        add_custom_command(
            OUTPUT ${output_file}
            COMMAND sh -c "\"${CMAKE_C_COMPILER}\" -E -P -x c ${include_flags_str} \"${CMAKE_CURRENT_SOURCE_DIR}/${source_file}\" > \"${output_file}\""
            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${source_file}
            COMMENT "Preprocessing ${source_file} to ${base_name}.daps"
            VERBATIM
        )
    endforeach()

    # Create custom target that depends on all output files
    add_custom_target(${target_name} DEPENDS ${output_files})

    # Make the target part of the ALL target so it gets built by default
    # This ensures it gets built when building just this subdirectory
    set_target_properties(${target_name} PROPERTIES
        FOLDER "${CMAKE_CURRENT_SOURCE_DIR}"
        EXCLUDE_FROM_ALL FALSE
    )

    # Set target properties
    set_target_properties(${target_name} PROPERTIES
        DAPS_OUTPUT_DIR ${output_dir}
        DAPS_OUTPUT_FILES "${output_files}"
    )

    # Make the target available globally
    set(${target_name}_OUTPUT_DIR ${output_dir} PARENT_SCOPE)
    set(${target_name}_OUTPUT_FILES "${output_files}" PARENT_SCOPE)
endfunction()

# Function to register a DAPSS target for later dependency addition
# Usage: register_daps_target(target_name)
# This stores the target name in a global property for later use
function(register_daps_target target_name)
    # Store the target name in a global property
    get_property(registered_targets GLOBAL PROPERTY DAPS_REGISTERED_TARGETS)
    list(APPEND registered_targets ${target_name})
    set_property(GLOBAL PROPERTY DAPS_REGISTERED_TARGETS ${registered_targets})
    message(STATUS "Registered DAPSS target ${target_name} for later dependency addition")
endfunction()

# Function to add all registered DAPSS targets as dependencies
# Usage: add_all_daps_dependencies([TARGET main_target] [CONDITION condition_expression])
# This should be called from the main CMakeLists.txt after all subdirectories are processed
function(add_all_daps_dependencies)
    set(options)
    set(oneValueArgs TARGET CONDITION)
    set(multiValueArgs)
    cmake_parse_arguments(DAPS_ALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

    # Default target is PROJECT_NAME
    if(DAPS_ALL_TARGET)
        set(dep_target ${DAPS_ALL_TARGET})
    else()
        set(dep_target ${PROJECT_NAME})
    endif()

    # Get all registered targets
    get_property(registered_targets GLOBAL PROPERTY DAPS_REGISTERED_TARGETS)

    if(registered_targets)
        foreach(target_name ${registered_targets})
            if(TARGET ${target_name})
                if(DAPS_ALL_CONDITION)
                    if(${DAPS_ALL_CONDITION})
                        add_dependencies(${dep_target} ${target_name})
                        message(STATUS "Added registered DAPSS target ${target_name} as dependency of ${dep_target} (condition: ${DAPS_ALL_CONDITION})")
                    else()
                        message(STATUS "Skipped registered DAPSS target ${target_name} (condition: ${DAPS_ALL_CONDITION} not met)")
                    endif()
                else()
                    add_dependencies(${dep_target} ${target_name})
                    message(STATUS "Added registered DAPSS target ${target_name} as dependency of ${dep_target}")
                endif()
            else()
                message(WARNING "Registered DAPSS target ${target_name} does not exist")
            endif()
        endforeach()
    else()
        message(STATUS "No DAPSS targets registered for dependency addition")
    endif()
endfunction()
