# -*- mode: cmake -*-

set(EXTERNAL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/external)
set(EXTERNAL_BUILD_DIR ${PROJECT_BINARY_DIR}/external/build)

# Clang < 3.2 breaks Eigen
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  check_cxx_source_compiles("
    #ifdef __clang__
    #if ((__clang_major__ == 3 && __clang_minor__ < 2) || (__clang_major__ < 3))
    #error clang < 3.2
    #endif
    #endif
    int main() { }
  " CLANG_VERSION_32)
  if (NOT CLANG_VERSION_32)
    message(FATAL_ERROR "Clang => 3.2 is required to compile Eigen")
  endif()
endif()

set(HAVE_EIGEN FALSE)
find_package(Eigen 3.0)

# if found, try sanity check: try compiling a simple program
if (EIGEN_FOUND)
  set(Eigen_INCLUDE_DIR ${EIGEN_INCLUDE_DIR})

  list(INSERT CMAKE_REQUIRED_INCLUDES 0 ${EIGEN_INCLUDE_DIR})
  file(READ ${EXTERNAL_SOURCE_DIR}/EigenCompiles.cxx EigenCompilesCxx)
  CHECK_CXX_SOURCE_COMPILES("${EigenCompilesCxx}" EIGEN_COMPILES)
  list(REMOVE_AT CMAKE_REQUIRED_INCLUDES 0)

  if (NOT EIGEN_COMPILES)
    message("** Eigen found at ${Eigen_INCLUDE_DIR} but failed to compile")
    message("** See CMakeFiles/CMakeError.log for details")
    set(HAVE_EIGEN FALSE)
  else()
    include_directories(${Eigen_INCLUDE_DIR})
    set(HAVE_EIGEN TRUE)
  endif()
endif()

#if eigen not found or did not compile, use the built in
if (NOT HAVE_EIGEN)

  include(ExternalProject)

  set(EIGEN_URL https://bitbucket.org/eigen/eigen/get/3.1.3.tar.gz)
  set(EIGEN_URL_HASH MD5=dc4247efd4f5d796041f999e8774af04)

  if (EXISTS ${EXTERNAL_SOURCE_DIR}/eigen.tar.gz)
    set(EIGEN_URL ${EXTERNAL_SOURCE_DIR}/eigen.tar.gz)
    set(EIGEN_URL_HASH "")
    message(STATUS "Using Eigen archive ${EIGEN_URL}")
  endif()

  add_dependencies(External Eigen)
  set(Eigen_INCLUDE_DIR ${EXTERNAL_BUILD_DIR}/Eigen/include)
  include_directories(${Eigen_INCLUDE_DIR})
  set(HAVE_EIGEN TRUE)

  ExternalProject_Add(
    Eigen
    PREFIX ${EXTERNAL_BUILD_DIR}/Eigen
    URL ${EIGEN_URL}
    URL_HASH ${EIGEN_URL_HASH}
    CONFIGURE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND
      ${CMAKE_COMMAND} -E copy_directory
      ${EXTERNAL_BUILD_DIR}/Eigen/src/Eigen/Eigen/
      ${EXTERNAL_BUILD_DIR}/Eigen/include/Eigen/
  )

  # external Eigen test target as we can't test it during configuration step
  add_executable(EigenCompiles ${EXTERNAL_SOURCE_DIR}/EigenCompiles.cxx)
  set_target_properties(EigenCompiles PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${EXTERNAL_BUILD_DIR})

  add_dependencies(EigenCompiles Eigen)
  add_dependencies(External EigenCompiles)
  add_dependencies(External Eigen)

endif()

if (HAVE_EIGEN)
  list(APPEND CMAKE_REQUIRED_INCLUDES ${EIGEN_INCLUDE_DIR})
endif()
