################################################################################
# Options
################################################################################
set (FILIB_DIR "" CACHE PATH "Path to the Filib lib and include directories")

################################################################################
# May be needed to install missing dependencies
################################################################################
include (ExternalProject)
include (Utils3rd)

# Looking for filib.h
set (FILIB_HDR "interval/interval.hpp")
set (MSG "Looking for ${FILIB_HDR}")
message (STATUS "${MSG}")
find_path (filib_INCLUDE_DIR ${FILIB_HDR} HINTS ${FILIB_DIR}
           PATH_SUFFIXES include
           DOC "Set to exact include directory to bypass internal test")
if (filib_INCLUDE_DIR)
  message (STATUS "${MSG} -- found at ${filib_INCLUDE_DIR}")
  if (filib_INCLUDE_DIR MATCHES "^${FILIB_DIR}")
    set (filib_INCLUDE_DIR ${filib_INCLUDE_DIR})
  else ()
    set (filib_INCLUDE_DIR $<BUILD_INTERFACE:${filib_INCLUDE_DIR}>)
  endif ()
else()
  message (STATUS "${MSG} -- not found")
endif()

# Looking for libprim
set (FILIB_LIB "prim")
set (MSG "Looking for ${FILIB_LIB}")
message (STATUS "${MSG}")
find_library (filib_LIBRARY NAMES ${FILIB_LIB} HINTS ${FILIB_DIR}
              PATH_SUFFIXES lib
              DOC "Set to exact lib directory to bypass internal test")
if (filib_LIBRARY)
  message (STATUS "${MSG} -- found at ${filib_LIBRARY}")
  set (_tmp "$<BUILD_INTERFACE:${filib_LIBRARY}>$<INSTALL_INTERFACE:")
  if (filib_LIBRARY MATCHES "^${FILIB_DIR}")
    get_filename_component (_libdir "${filib_LIBRARY}" DIRECTORY)
    set (_tmp "${_tmp}-L${_libdir} ")
  endif ()
  set (filib_LIBRARY "${_tmp}-lprim>")
else()
  message (STATUS "${MSG} -- not found")
endif()

if (NOT filib_INCLUDE_DIR OR NOT filib_LIBRARY)
  message (STATUS "Will install and use library Filib from 3rd/ subdirectory")
  ExternalProject_Add (libfilib_3rd
                        PREFIX filib-3.0.2.2
                        URL ${CMAKE_CURRENT_SOURCE_DIR}/3rd/filibsrc-3.0.2.2.tar.gz
                        BUILD_IN_SOURCE 1
                        CONFIGURE_COMMAND ./configure --prefix=<INSTALL_DIR>)
  ExternalProject_Get_Property (libfilib_3rd INSTALL_DIR)
  # install headers and set build and install include directory
  set (_incdir ${INSTALL_DIR}/include)
  install (DIRECTORY ${_incdir}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR_3RD})
  set (filib_INCLUDE_DIR $<BUILD_INTERFACE:${_incdir}>$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR_3RD}>)
  file (MAKE_DIRECTORY "${_incdir}") # need to exist during generation step
  #
  lib_full_path (filib_LIBRARY ${INSTALL_DIR}/lib prim)
  install (FILES ${filib_LIBRARY} DESTINATION ${CMAKE_INSTALL_LIBDIR_3RD})
  set (filib_LIBRARY "$<BUILD_INTERFACE:${filib_LIBRARY}>$<INSTALL_INTERFACE:-L$<INSTALL_PREFIX>/${CMAKE_INSTALL_LIBDIR_3RD} -lprim>")
  unset (INSTALL_DIR)
endif ()

# 
mark_as_advanced (filib_INCLUDE_DIR filib_LIBRARY)

# Create an interface imported target
add_library (filib INTERFACE IMPORTED GLOBAL)
set_target_properties (filib PROPERTIES
    INTERFACE_INCLUDE_DIRECTORIES ${filib_INCLUDE_DIR}
    INTERFACE_LINK_LIBRARIES ${filib_LIBRARY}
  )

# With Filib, we add "-Wno-deprecated" to remove lots of warnings generated by
# a function definition in interval.icc
CHECK_CXX_COMPILER_FLAG ("-Wno-deprecated" COMPILER_SUPPORTS_WNO_DEPRECATED)
if (COMPILER_SUPPORTS_WNO_DEPRECATED)
  set_target_properties (filib PROPERTIES
                              INTERFACE_COMPILE_OPTIONS -Wno-deprecated)
endif()

# With Filib, we need to add flags "-frounding-math" and "-ffloat-store"
# It is necessary to use filib, to avoid problem with x80 processor.
# This option prevents undesirable excess precision on machines such as the
# 68000 where the floating registers (of the 68881) keep more precision than a
# "double" is supposed to have. Similarly for the x86 architecture. For most
# programs, the excess precision does only good, but a few programs rely on the
# precise definition of IEEE floating point. Use -ffloat-store for such
# programs, after modifying them to store all pertinent intermediate
# computations into variables.
foreach (flag "-frounding-math" "-ffloat-store")
  CHECK_CXX_COMPILER_FLAG (${flag} COMPILER_SUPPORTS_${flag})
  if (COMPILER_SUPPORTS_${flag})
    get_target_property (OPT filib INTERFACE_COMPILE_OPTIONS)
    if (OPT)
      list (APPEND OPT ${flag})
    else ()
      set (OPT ${flag})
    endif ()
    set_target_properties (filib PROPERTIES INTERFACE_COMPILE_OPTIONS "${OPT}")
  else ()
    message (WARNING "The compiler does not the flag ${flag} needed by Filib. "
                     "You may get incorrect/inconsistent results.")
  endif()
endforeach ()

# TODO -msse2 -msse3 ??
