cmake_minimum_required(VERSION 3.5)
include(TripletHelper)

function(platform_check)
    set(PLATFORM_WIN32 FALSE PARENT_SCOPE)
    set(PLATFORM_WIN64 FALSE PARENT_SCOPE)
    set(PLATFORM_OSX FALSE PARENT_SCOPE)
    set(PLATFORM_LINUX FALSE PARENT_SCOPE)
    if(WIN32)
        if(CMAKE_CL_64)
          set(PLATFORM_WIN64 TRUE PARENT_SCOPE)
        else()
          set(PLATFORM_WIN32 TRUE PARENT_SCOPE)
        endif()
    endif()
    if(APPLE)
        if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
          set(PLATFORM_OSX TRUE PARENT_SCOPE)
        endif()
    endif()
endfunction()

function(print_list seriousness)
    foreach(elem ${ARGN})
        message(${seriousness} ${elem})
    endforeach()
endfunction()

function(print_global_property append name)
    get_property(testvar GLOBAL PROPERTY ${name})
    foreach(elem ${testvar})
        message(STATUS ${append} ${elem})
    endforeach()
endfunction()

macro(create_interface_target name)
    set(tgtname TP_${name})
    add_library(${tgtname} INTERFACE)
    get_property(temp GLOBAL PROPERTY ${name}_LIBRARIES)
    foreach(l ${temp})
        #set_property(TARGET ${tgtname} PROPERTY INTERFACE_LINK_LIBRARIES ${l})
        target_link_libraries(${tgtname} INTERFACE general ${l})
    endforeach()
    get_property(temp GLOBAL PROPERTY ${name}_LIBRARIES_DEBUG)
    foreach(l ${temp})
        #set_property(TARGET ${tgtname} PROPERTY INTERFACE_LINK_LIBRARIES_DEBUG ${l})
        target_link_libraries(${tgtname} INTERFACE debug ${l})
    endforeach()
    get_property(temp GLOBAL PROPERTY ${name}_LIBRARIES_RELEASE)
    foreach(l ${temp})
        #set_property(TARGET ${tgtname} PROPERTY INTERFACE_LINK_LIBRARIES_RELEASE ${l})
        target_link_libraries(${tgtname} INTERFACE optimized ${l})
    endforeach()
    get_property(temp GLOBAL PROPERTY ${name}_DEFINITIONS)
    #set_property(TARGET ${tgtname} PROPERTY INTERFACE_COMPILE_DEFINITIONS ${temp})
    target_compile_definitions(${tgtname} INTERFACE ${temp})
    get_property(temp GLOBAL PROPERTY ${name}_INCLUDES)
    #set_property(TARGET ${tgtname} PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${temp})
    target_include_directories(${tgtname} INTERFACE ${temp})
    add_library(ThirdParty::${name} ALIAS ${tgtname})
endmacro()

macro(append_list_with_current_source_dir target_var)
    foreach(elem ${ARGN})
        set_property(GLOBAL APPEND PROPERTY ${target_var} "${CMAKE_CURRENT_SOURCE_DIR}/${elem}")
    endforeach()
endmacro()

function(add_3rdparty_module target_name)
    set(os_list "WIN32;WIN64;OSX;LINUX")
    set(prop_list "LIBRARIES;LIBRARIES_DEBUG;LIBRARIES_RELEASE;DEFINITIONS;INCLUDES;ABSINCLUDES;BINS;BINS_DEBUG;BINS_RELEASE;DEPENDS")
    set(full_list "")
    foreach(curr_os ${os_list})
        foreach(curr_prop ${prop_list})
            string(CONCAT new_prop ${curr_os} _ ${curr_prop})
            list(APPEND full_list ${new_prop})
        endforeach()
    endforeach()
    list(APPEND full_list ${prop_list})
    cmake_parse_arguments(T "${os_list}" "VERSION" "${full_list}" ${ARGN})
    set_property(GLOBAL APPEND PROPERTY ${target_name}_LIBRARIES "${T_LIBRARIES}")
    set_property(GLOBAL APPEND PROPERTY ${target_name}_LIBRARIES_DEBUG "${T_LIBRARIES_DEBUG}")
    set_property(GLOBAL APPEND PROPERTY ${target_name}_LIBRARIES_RELEASE "${T_LIBRARIES_RELEASE}")
    set_property(GLOBAL APPEND PROPERTY ${target_name}_DEFINITIONS "${T_DEFINITIONS}")
    append_list_with_current_source_dir(${target_name}_INCLUDES "${T_INCLUDES}")
    set_property(GLOBAL APPEND PROPERTY ${target_name}_INCLUDES "${T_ABSINCLUDES}")
    set_property(GLOBAL APPEND PROPERTY ${target_name}_BINS "${T_BINS}")
    set_property(GLOBAL APPEND PROPERTY ${target_name}_BINS_DEBUG "${T_BINS_DEBUG}")
    set_property(GLOBAL APPEND PROPERTY ${target_name}_BINS_RELEASE "${T_BINS_RELEASE}")
    set_property(GLOBAL APPEND PROPERTY ${target_name}_DEPENDS "${T_DEPENDS}")
    platform_check()
    foreach(curr_platform ${os_list})
        #message(STATUS Doing ${curr_platform})
        if(PLATFORM_${curr_platform})
            #message(STATUS Checking against ${curr_platform})
            if(T_${curr_platform})
                set_property(GLOBAL PROPERTY ${target_name}_SUPPORTED TRUE)
                set_property(GLOBAL APPEND PROPERTY ${target_name}_LIBRARIES "${T_${curr_platform}_LIBRARIES}")
                set_property(GLOBAL APPEND PROPERTY ${target_name}_LIBRARIES_DEBUG "${T_${curr_platform}_LIBRARIES_DEBUG}")
                set_property(GLOBAL APPEND PROPERTY ${target_name}_LIBRARIES_RELEASE "${T_${curr_platform}_LIBRARIES_RELEASE}")
                set_property(GLOBAL APPEND PROPERTY ${target_name}_DEFINITIONS "${T_${curr_platform}_DEFINITIONS}")
                append_list_with_current_source_dir(${target_name}_INCLUDES "${T_${curr_platform}_INCLUDES}")
                set_property(GLOBAL APPEND PROPERTY ${target_name}_INCLUDES "${T_${curr_platform}_ABSINCLUDES}")
                set_property(GLOBAL APPEND PROPERTY ${target_name}_BINS "${T_${curr_platform}_BINS}")
                set_property(GLOBAL APPEND PROPERTY ${target_name}_BINS_DEBUG "${T_${curr_platform}_BINS_DEBUG}")
                set_property(GLOBAL APPEND PROPERTY ${target_name}_BINS_RELEASE "${T_${curr_platform}_BINS_RELEASE}")
                set_property(GLOBAL APPEND PROPERTY ${target_name}_DEPENDS "${T_${curr_platform}_DEPENDS}")
            else()
                get_property(already_supported GLOBAL PROPERTY ${target_name}_SUPPORTED)
                if(${already_supported})
                else()
                    set_property(GLOBAL PROPERTY ${target_name}_SUPPORTED FALSE)
                endif()
            endif()
        endif()
    endforeach()
    get_property(already_supported GLOBAL PROPERTY ${target_name}_SUPPORTED)
    if(${already_supported})
        create_interface_target(${target_name})
    endif()
    set_property(GLOBAL APPEND PROPERTY 3RDPARTY_MODULE_LIST ${target_name})
endfunction()

function(dump_3rdparty_module name)
    message(STATUS ------${name}------)
    print_global_property("SUPPORTED: " ${name}_SUPPORTED)
    print_global_property("BINS: " ${name}_BINS)
    print_global_property("BINS DEBUG: " ${name}_BINS_DEBUG)
    print_global_property("BINS RELEASE: " ${name}_BINS_RELEASE)
    print_global_property("LIBS: " ${name}_LIBRARIES)
    print_global_property("LIBS DEBUG: " ${name}_LIBRARIES_DEBUG)
    print_global_property("LIBS RELEASE: " ${name}_LIBRARIES_RELEASE)
    print_global_property("DEFS: " ${name}_DEFINITIONS)
    print_global_property("INCLUDES: " ${name}_INCLUDES)
endfunction()

function(dump_all_3rdparty_module)
    get_property(mlist GLOBAL PROPERTY 3RDPARTY_MODULE_LIST)
    list(REMOVE_DUPLICATES mlist)
    foreach(m ${mlist})
        dump_3rdparty_module(${m})
    endforeach()
endfunction()


macro(module_link_module name linkage module)
    get_property(mlist GLOBAL PROPERTY 3RDPARTY_MODULE_LIST)
    list(FIND mlist ${module} found)
    if(found EQUAL -1)
        message(STATUS "[${name}] <- [${module}]")
        target_link_libraries(${name} ${linkage} ${module})
    else()
        message(STATUS "[${name}] <- ${module}")
        target_link_libraries(${name} ${linkage} ThirdParty::${module})
        get_property(temp GLOBAL PROPERTY ${module}_BINS)
        foreach(l ${temp})
            add_custom_command(TARGET ${name} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${l} $<TARGET_FILE_DIR:${name}>)
        endforeach()
        get_property(temp GLOBAL PROPERTY ${module}_BINS_DEBUG)
        foreach(l ${temp})
            add_custom_command(TARGET ${name} POST_BUILD COMMAND ${CMAKE_COMMAND} -E
			$<$<CONFIG:Debug>:copy_if_different> $<$<CONFIG:Debug>:${l}> $<$<CONFIG:Debug>:$<TARGET_FILE_DIR:${name}>>
			$<$<NOT:$<CONFIG:Debug>>:echo> $<$<NOT:$<CONFIG:Debug>>:"Copying optimized libraries">)
        endforeach()
        get_property(temp GLOBAL PROPERTY ${module}_BINS_RELEASE)
        foreach(l ${temp})
            add_custom_command(TARGET ${name} POST_BUILD COMMAND ${CMAKE_COMMAND} -E
			$<$<NOT:$<CONFIG:Debug>>:copy_if_different> $<$<NOT:$<CONFIG:Debug>>:${l}> $<$<NOT:$<CONFIG:Debug>>:$<TARGET_FILE_DIR:${name}>>
			$<$<CONFIG:Debug>:echo> $<$<CONFIG:Debug>:"Copying debug libraries">)
        endforeach()
        get_property(deplist GLOBAL PROPERTY ${module}_DEPENDS)
        if(deplist)
            list(REMOVE_DUPLICATES deplist)
            foreach(dep ${deplist})
                module_link_module(${name} ${linkage} ${dep})
            endforeach()
        endif()
    endif()
endmacro()
