#=============================================================================
#    Copyright (c) 2017 Paul Fultz II
#    CMakeLists.txt
#    Distributed under the Boost Software License, Version 1.0. (See accompanying
#    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#==============================================================================
cmake_minimum_required (VERSION 2.8)
project (boost_hof)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

foreach(level MAJOR MINOR PATCH)
    file(STRINGS include/boost/hof/version.hpp
                 _define_${level}
                 REGEX "#define BOOST_HOF_${level}_VERSION")
    string(REGEX MATCH "([0-9]+)" boost_hof_VERSION_${level} "${_define_${level}}")
endforeach() 

include(CheckCXXCompilerFlag)
enable_language(CXX)

if(NOT CMAKE_CXX_FLAGS MATCHES "-std=")

    if(CMAKE_HOST_APPLE)
      check_cxx_compiler_flag("-stdlib=libc++" COMPILER_HAS_CXX_FLAG_libcxx)
      if(COMPILER_HAS_CXX_FLAG_libcxx)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
      endif()
    endif()

    set(ENABLE_CXXFLAGS_TO_CHECK 
        -std=gnu++17
        -std=c++17
        -std=gnu++1z
        -std=c++1z
        -std=gnu++14
        -std=c++14
        -std=gnu++1y 
        -std=c++1y
        -std=gnu++11 
        -std=c++11
        -std=gnu++0x 
        -std=c++0x)

    foreach(flag ${ENABLE_CXXFLAGS_TO_CHECK})
        string(REPLACE "-std=" "_" flag_var ${flag})
        string(REPLACE "+" "x" flag_var ${flag_var})
        check_cxx_compiler_flag("${flag}" COMPILER_HAS_CXX_FLAG${flag_var})
        if(COMPILER_HAS_CXX_FLAG${flag_var})
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
            break()
        endif()
    endforeach()

endif()

install (DIRECTORY include/boost DESTINATION include)
configure_file(boost_hof.pc.in boost_hof.pc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/boost_hof.pc DESTINATION lib/pkgconfig)

include(SphinxDoc)

add_sphinx_doc(${CMAKE_CURRENT_SOURCE_DIR}/doc HTML_DIR ${CMAKE_CURRENT_SOURCE_DIR}/doc/html)

include(BCMTest)

include_directories(include)

file(GLOB TESTS test/*.cpp)
foreach(TEST ${TESTS})
    get_filename_component(BASE_NAME ${TEST} NAME_WE)
    bcm_add_test(NAME ${BASE_NAME} SOURCES ${TEST})
    set_tests_properties(${BASE_NAME} PROPERTIES FAIL_REGULAR_EXPRESSION "FAILED")
endforeach()
bcm_add_test(NAME static_def SOURCES test/static_def/static_def.cpp test/static_def/static_def2.cpp)
set_tests_properties(static_def PROPERTIES FAIL_REGULAR_EXPRESSION "FAILED")

file(GLOB FAIL_TESTS test/fail/*.cpp)
foreach(TEST ${FAIL_TESTS})
    get_filename_component(BASE_NAME ${TEST} NAME_WE)
    bcm_add_test(NAME fail-${BASE_NAME} COMPILE_ONLY WILL_FAIL SOURCES ${TEST})
endforeach()

file(GLOB HEADERS include/boost/hof/*.hpp)
foreach(HEADER ${HEADERS})
    get_filename_component(BASE_NAME ${HEADER} NAME_WE)
    bcm_test_header(NAME ${BASE_NAME} HEADER boost/hof/${BASE_NAME}.hpp STATIC)
endforeach()
bcm_test_header(NAME hof HEADER boost/hof.hpp STATIC)

function(extract_doc SOURCE OUTPUTVAR)
    file(READ ${SOURCE} CONTENT)
    string(REGEX REPLACE "(\n(/[^/][^/]|//[^/]|[^/][^/][^/])([^\n])*)" "" CONTENT "\n${CONTENT}")
    string(REPLACE "/// " "" CONTENT "${CONTENT}")
    set(${OUTPUTVAR} "${CONTENT}" PARENT_SCOPE)
endfunction()

function(build_example SECTIONCONTENT NAME)
    string(MD5 MD5_SECTION "${SECTIONCONTENT}")
    set(TARGET_NAME "example-${NAME}-${MD5_SECTION}")
    set(CONTENT "")
    foreach(LINE ${SECTIONCONTENT})
        if(LINE MATCHES "^    ")
            string(SUBSTRING ${LINE} "4" "-1" OUTPUT_LINE)
            list(APPEND CONTENT ${OUTPUT_LINE})
        endif()
    endforeach()
    string(REPLACE ";" "\n" CONTENT "${CONTENT}")
    string(REPLACE "$$__semicolon__$$" ";" CONTENT "${CONTENT}")
    if(NOT CONTENT MATCHES "int main")
        string(APPEND CONTENT "int main() {}")
    endif()
    message(STATUS "Adding example: ${TARGET_NAME}")
    bcm_add_test(NAME ${TARGET_NAME} CONTENT "${CONTENT}\n")
endfunction()

function(extract_example SOURCE)
    extract_doc(${SOURCE} CONTENT)
    string(REPLACE ";" "$$__semicolon__$$" CONTENT "${CONTENT}")
    string(REPLACE "\n" ";" CONTENT "${CONTENT}")

    get_filename_component(BASE_NAME ${SOURCE} NAME_WE)

    set(SECTION "")
    set(PREVLINE "")
    set(APPEND_SECTION Off)
    foreach(LINE ${CONTENT})
        if(APPEND_SECTION)
            if((LINE MATCHES "^---") OR (LINE MATCHES "^==="))
                build_example("${SECTION}" ${BASE_NAME})
                set(APPEND_SECTION Off)
                set(SECTION "")
            elseif(NOT PREVLINE MATCHES "^---")
                list(APPEND SECTION ${PREVLINE})
            endif()
        else()
            if((LINE MATCHES "^---") AND (PREVLINE MATCHES "^Example"))
                set(APPEND_SECTION One)
            endif()
        endif()
        set(PREVLINE "${LINE}")
    endforeach()
    list(APPEND SECTION ${PREVLINE})
    if(APPEND_SECTION)
        build_example("${SECTION}" ${BASE_NAME})
    endif()
endfunction()

set(BUILD_EXAMPLES off CACHE BOOL "Set this to build the examples")

if (BUILD_EXAMPLES)
    file(GLOB EXAMPLES example/*.cpp)
    foreach(EXAMPLE ${EXAMPLES})
        get_filename_component(BASE_NAME ${EXAMPLE} NAME_WE)
        bcm_add_test(NAME example-${BASE_NAME} SOURCES ${EXAMPLE})
    endforeach()
    foreach(HEADER ${HEADERS})
        extract_example(${HEADER})
    endforeach()
endif()
