#===============================================================================
# Macro for managing subpackages
# ------------------------------
# Usage:
#
#     subpackage(module_name)
#
# the packages are expected to exist in the module_name sub directory
#
# generated variables:
#     lib_src_${arch}         : list of all module_${name}_lib_src_${arch} variables
#     lib_obj_${arch}         : list of all module_${name}_lib_obj_${arch} variables
#     test_utils_src_${arch}  : list of all module_${name}_test_utils_src_${arch} variables
#
# Module Requirements:
#     module_${name}_lib_src_${arch}          : the files to be included in the main library
#     module_${name}_lib_obj_${arch}          : the precompiled object files to be included in the main library
#     module_${name}_test_utils_src_${arch}   : the files to be included in the test_utils library
#
#===============================================================================

# -- create a working directory
SET(SUBPACKAGE_WORK_DIR ${CMAKE_BINARY_DIR}/_subpackages) # the top directory
#SET(SUBPACKAGE_WORK_PATH ${SUBPACKAGE_WORK_DIR})                # position in subpackage hierarcy
SET(SUBPACKAGE_NAME "")                                   # name of the subpacakge
mark_as_advanced(SUBPACKAGE_WORK_DIR)
mark_as_advanced(SUBPACKAGE_WORK_PATH)
mark_as_advanced(SUBPACKAGE_NAME)
mark_as_advanced(SUBPACKAGE_CMAKE_INCLUDES)
FILE(MAKE_DIRECTORY ${SUBPACKAGE_WORK_DIR})


# - generate a subpackage workfile
macro(SUBPACKAGE_FILE package )
    FILE(MAKE_DIRECTORY "${SUBPACKAGE_WORK_PATH}")
    file(WRITE ${SUBPACKAGE_FILENAME}
        "# Autogenerated file for the subpackage : ${package} - do not edit\n"
        )
endmacro(SUBPACKAGE_FILE)


#
# Add any new device types here
#
set(arch_types cpu cuda fpga)

macro(SUBPACKAGE name)
    if(NOT subpackage_path)
        set(subpackage_parent "")
        set(subpackage_path "${name}")
        set(subpackage_top "${name}")
        set(subpackage_namespace "${name}")
    else(NOT subpackage_path)
        set(subpackage_parent ${subpackage_path})
        set(subpackage_path "${subpackage_path}/${name}")
        set(subpackage_namespace "${subpackage_namespace}::${name}")
    endif(NOT subpackage_path)

    # manage subpackage build files and variables for working files
    set(SUBPACKAGE_WORK_PATH "${SUBPACKAGE_WORK_DIR}/${subpackage_path}")
    set(SUBPACKAGE_NAME "${name}")
    set(SUBPACKAGE_FILENAME "${SUBPACKAGE_WORK_PATH}/${name}.cmake")
    subpackage_file("${name}")

    # -- don't propagate working variables into subdirectories
    foreach(arch ${arch_types})
        set(_tmp_lib_src_${arch} ${lib_src_${arch}})
        set(_tmp_lib_obj_${arch} ${lib_obj_${arch}})
        set(lib_src_${arch} "")
        set(lib_obj_${arch} "")
        set(_tmp_test_utils_src_${arch} ${test_utils_src_${arch}})
        set(_tmp_test_utils_obj_${arch} ${test_utils_obj_${arch}})
        set(test_utils_src_${arch} "")
        set(test_utils_obj_${arch} "")
    endforeach(arch)
    add_subdirectory(${name})

    foreach(arch ${arch_types})
        set(lib_src_${arch} ${_tmp_lib_src_${arch}})
        set(lib_obj_${arch} ${_tmp_lib_obj_${arch}})
        set(test_utils_src_${arch} ${_tmp_test_utils_src_${arch}})
        set(test_utils_obj_${arch} ${_tmp_test_utils_obj_${arch}})

        # src from submodules
        set(mod_list_${arch} "")
        foreach(src ${module_${name}_lib_src_${arch}})
            list(APPEND mod_list_${arch} "${name}/${src}")
        endforeach(src)
        list(APPEND lib_src_${arch} ${mod_list_${arch}})

        # objects from submodules
        set(mod_list_${arch} "")
        foreach(obj ${module_${name}_lib_obj_${arch}})
            list(APPEND mod_list_${arch} "${obj}")
        endforeach(obj)
        list(APPEND lib_obj_${arch} ${mod_list_${arch}})
        set(lib_obj_${arch} ${lib_obj_${arch}} PARENT_SCOPE)

        set(mod_utils_list_${arch} "")
        foreach(src ${module_${name}_test_utils_src_${arch}})
            list(APPEND mod_utils_list_${arch} "${name}/test_utils/${src}")
        endforeach(src)
        list(APPEND test_utils_src_${arch} ${mod_utils_list_${arch}})
        # test_utils objects from submodules
        set(mod_utils_list_${arch} "")
        foreach(obj ${module_${name}_test_utils_obj_${arch}})
            list(APPEND mod_utils_list_${arch} "${name}/test_utils/${obj}")
        endforeach(obj)
        list(APPEND test_utils_obj_${arch} ${mod_utils_list_${arch}})
    endforeach(arch)

    # -- add header install targets
    file(GLOB include_files "${name}/*.h")
    file(GLOB detail_files "${name}/detail/*.*")
    install(FILES ${include_files} DESTINATION "${INCLUDE_INSTALL_DIR}/${subpackage_path}")
    install(FILES ${detail_files} DESTINATION "${INCLUDE_INSTALL_DIR}/${subpackage_path}/detail")

    # propagate the include files to the parents SUBPACKAGE_CMAKE_INCLUDES variable
    list(APPEND SUBPACKAGE_CMAKE_INCLUDES "${SUBPACKAGE_FILENAME}")
    set(SUBPACKAGE_CMAKE_INCLUDES ${SUBPACKAGE_CMAKE_INCLUDES} PARENT_SCOPE)

    # restore subpackage tracking variables to the parent scope
    set(subpackage_path "${subpackage_parent}")
    set(subpackage_namespace "${subpackage_parent}")
    set(subpackage_top "")

    set(SUBPACKAGE_WORK_PATH "${SUBPACKAGE_WORK_DIR}/${subpackage_path}")
    set(SUBPACKAGE_FILENAME "${SUBPACKAGE_WORK_PATH}/${SUBPACKAGE_NAME}.cmake")

endmacro(SUBPACKAGE)

macro(INCLUDE_SUBPACKAGE_FILES)
    foreach(dir ${SUBPACKAGE_CMAKE_INCLUDES})
       include("${dir}")
    endforeach()
endmacro(INCLUDE_SUBPACKAGE_FILES)

macro(TEST_UTILS)
    get_filename_component(name ${CMAKE_CURRENT_SOURCE_DIR} NAME)
    add_subdirectory(test_utils)
    foreach(arch ${arch_types})
        set(module_${name}_test_utils_src_${arch} 
            ${module_${name}_test_utils_src_${arch}}
            PARENT_SCOPE
        )
    endforeach(arch)
endmacro(TEST_UTILS)

