##############################################################################
# @file  CMakeLists.txt
# @brief CMake configuration of bundle.
#
# See INSTALL.txt for information on how to build the entire bundle.
#
# Copyright (c) 2012 University of Pennsylvania. All rights reserved.
# See http://www.rad.upenn.edu/sbia/software/license.html or COPYING file.
#
# Contact: SBIA Group <sbia-software at uphs.upenn.edu>
##############################################################################

cmake_minimum_required (VERSION 2.8.4)

include (ExternalProject)

# ============================================================================
# global settings
# ============================================================================

project (DTIDROIDBundle)

option (BUILD_DOCUMENTATION "Whether to configure and build the documentation." OFF)
option (BUILD_EXAMPLE       "Whether to install the example files."             OFF)
option (TEST_BEFORE_INSTALL "Whether to run the tests before installation."     OFF)
option (USE_SYSTEM_GSL      "Skip build of GSL if already installed."           OFF)

if (NOT CMAKE_BUILD_TYPE)
  set_property (CACHE CMAKE_BUILD_TYPE PROPERTY VALUE "Release")
endif ()

set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")

if (NOT BUNDLE_PROJECTS)
  set (BUNDLE_PROJECTS) # tells BASIS which other packages belong to the same build
                          # each package which is build via ExternalProject_Add
                          # shall be added to this list and passed on to CMake
                          # for the configuration of any BASIS-based project
                          # using -DBUNDLE_PROJECTS:INTERNAL=<names>.
endif ()

# ============================================================================
# bundle packages
# ============================================================================

if (NOT BUNDLE_SOURCE_DIR)
  set (BUNDLE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
endif ()

# BASIS
if (EXISTS "${BUNDLE_SOURCE_DIR}/basis-2.0.0-source.tar.gz")
  set (BASIS_URL "${BUNDLE_SOURCE_DIR}/basis-2.0.0-source.tar.gz")
else ()
  set (BASIS_URL "http://www.rad.upenn.edu/sbia/software/distributions/basis-2.0.0-source.tar.gz")
endif ()
# GSL
if (EXISTS "${BUNDLE_SOURCE_DIR}/gsl-1.15.tar.gz")
  set (GSL_URL "${BUNDLE_SOURCE_DIR}/gsl-1.15.tar.gz")
else ()
  set (GSL_URL "http://mirrors.syringanetworks.net/gnu/gsl/gsl-1.15.tar.gz")
endif ()
# DTI-DROID
if (NOT DTIDROID_SOURCE_DIR)
  set (DTIDROID_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/..")
endif ()

# ============================================================================
# 1. BASIS
# ============================================================================

set (BUNDLE_DEPENDS) # either BASIS or nothing if BASIS already installed

# circumvent issue with CMake's find_package() interpreting these variables
# relative to the current binary directory instead of the top-level directory
if (BASIS_DIR AND NOT IS_ABSOLUTE "${BASIS_DIR}")
  set (BASIS_DIR "${CMAKE_BINARY_DIR}/${BASIS_DIR}")
  get_filename_component (BASIS_DIR "${BASIS_DIR}" ABSOLUTE)
endif ()
# moreover, users tend to specify the installation prefix instead of the
# actual directory containing the package configuration file
if (IS_DIRECTORY "${BASIS_DIR}")
  list (INSERT CMAKE_PREFIX_PATH 0 "${BASIS_DIR}")
endif ()

# find BASIS or build it as external project
if (DEFINED BASIS_DIR)
  find_package (BASIS REQUIRED)
else ()
  option (USE_SYSTEM_BASIS "Skip build of BASIS if already installed." OFF)

  if (USE_SYSTEM_BASIS)
    find_package (BASIS QUIET)
  endif ()

  if (NOT BASIS_FOUND)
    set (BASIS_CMAKE_CACHE_ARGS)
    if (TEST_BEFORE_INSTALL)
      find_package (ITK REQUIRED) # the test driver of BASIS yet requires ITK
      list (APPEND BASIS_CMAKE_CACHE_VARS "-DITK_DIR:PATH=${ITK_DIR}")
      list (APPEND BASIS_CMAKE_CACHE_VARS "-DUSE_ITK:BOOL=ON")
    else ()
      list (APPEND BASIS_CMAKE_CACHE_VARS "-DUSE_ITK:BOOL=OFF")
    endif ()
    ExternalProject_Add (
      BASIS
      PREFIX           bundle
      URL              "${BASIS_URL}"
      CMAKE_CACHE_ARGS "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
                       "-DBUILD_DOCUMENTATION:BOOL=OFF"
                       "-DBUILD_EXAMPLE:BOOL=OFF"
                       "-DBUILD_TESTING:BOOL=OFF"
                       "-DINSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}"
                       "-DINSTALL_SINFIX:BOOL=ON"
                       "-DBUILD_PROJECT_TOOL:BOOL=OFF"
                       "-DINSTALL_DEPRECATED_TEMPLATES:BOOL=OFF"
                       "-DUSE_Bash:BOOL=ON"
                       "-DUSE_PythonInterp:BOOL=ON"
                       "-DUSE_Perl:BOOL=ON"
                       "-DUSE_MATLAB:BOOL=OFF"
                       ${BASIS_CMAKE_CACHE_ARGS}
    )
    list (APPEND BUNDLE_DEPENDS    BASIS)
    list (APPEND BUNDLE_PROJECTS BASIS)
  endif ()
endif ()

# ============================================================================
# 2. other bundle packages
# ============================================================================

# this is by defaul done even when BASIS was found such that the build of the
# remaining packages is always the same even if it would not be necessary to
# have the external "bundle" project. this switch is also used by the "bundle"
# project to skip the addition of this external project. otherwise, it would
# be an endless recursion...
option (BASIS_BUNDLE_PROJECTS "Whether to bundle all external projects even if already installed BASIS is used." ON)
mark_as_advanced (BASIS_BUNDLE_PROJECTS)

if (BASIS_BUNDLE_PROJECTS)
  # build all other packages as external project which itself just builds
  # the following external projects. this is necessary as BASIS has to be
  # build before the other external projects can be even configured.
  # in particular the Find<Pkg>.cmake modules coming with BASIS are required
  # to find any already installed packages
  ExternalProject_Add (
    bundle
    DEPENDS          ${BUNDLE_DEPENDS}
    DOWNLOAD_COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_LIST_FILE}" CMakeLists.txt
    PREFIX           bundle
    DOWNLOAD_DIR     bundle
    SOURCE_DIR       bundle
    BINARY_DIR       bundle
    STAMP_DIR        bundle/tmp
    TMP_DIR          bundle/tmp
    CMAKE_CACHE_ARGS "-DBUNDLE_PROJECTS:STRING=${BUNDLE_PROJECTS}"
                     "-DBUILD_DOCUMENTATION:BOOL=${BUILD_DOCUMENTATION}"
                     "-DBUILD_EXAMPLE:BOOL=${BUILD_EXAMPLE}"
                     "-DTEST_BEFORE_INSTALL:BOOL=${TEST_BEFORE_INSTALL}"
                     "-DUSE_SYSTEM_GSL:BOOL=${USE_SYSTEM_GSL}"
                     "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
                     "-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}"
                     "-DBASIS_DIR:PATH=${CMAKE_INSTALL_PREFIX}"
                     "-DBUNDLE_SOURCE_DIR:PATH=${BUNDLE_SOURCE_DIR}"
                     "-DDTIDROID_SOURCE_DIR:PATH=${DTIDROID_SOURCE_DIR}"
                     "-DBASIS_BUNDLE_PROJECTS:INTERNAL=OFF"
    INSTALL_COMMAND  ""
  )
  # remove all bundle files on "make clean"
  set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/bundle")
  # do not continue... the external "bundle" project will do the rest
  return ()
endif ()

set_directory_properties (PROPERTY EP_PREFIX "${CMAKE_CURRENT_BINARY_DIR}")

# external projects which the respective external project depends on
# note that dependencies may already be installed
set (DTIDROID_DEPENDS)

# ----------------------------------------------------------------------------
# minimal requirements
basis_find_package (BASH                       REQUIRED)
basis_find_package (PythonInterp               REQUIRED)
basis_find_package (PythonModules{numpy,nifti} REQUIRED)
basis_find_package (Perl                       REQUIRED)

# ----------------------------------------------------------------------------
# GSL
if (USE_SYSTEM_GSL)
  basis_find_package (GSL QUIET)
endif ()

if (NOT GSL_FOUND)
  ExternalProject_Add (
    GSL
      URL               "${GSL_URL}"
      URL_MD5           494ffefd90eef4ada678c306bab4030b
      BUILD_IN_SOURCE   1
      CONFIGURE_COMMAND ./configure --prefix "${CMAKE_INSTALL_PREFIX}"
      BUILD_COMMAND     make
      INSTALL_COMMAND   make install
  )
  set (GSL_DIR "${CMAKE_INSTALL_PREFIX}")
  list (APPEND BUNDLE_PROJECTS  "GSL")
  list (APPEND DTIDROID_DEPENDS "GSL")
endif ()

# ----------------------------------------------------------------------------
# DTI-DROID
ExternalProject_Add (
  DTIDROID
    DEPENDS             ${DTIDROID_DEPENDS}
    SOURCE_DIR          "${DTIDROID_SOURCE_DIR}"
    CMAKE_CACHE_ARGS    "-DBASIS_DIR:PATH=${BASIS_DIR}"
                        "-DGSL_DIR:PATH=${GSL_DIR}"
                        "-DBUNDLE_PROJECTS:INTERNAL=${BUNDLE_PROJECTS}"
                        "-DBASIS_ALL_DOC:BOOL=${BUILD_DOCUMENTATION}"
                        "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
                        "-DBUILD_DOCUMENTATION:BOOL=${BUILD_DOCUMENTATION}"
                        "-DBUILD_EXAMPLE:BOOL=${BUILD_EXAMPLE}"
                        "-DBUILD_TESTING:BOOL=${TEST_BEFORE_INSTALL}"
                        "-DINSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}"
                        "-DINSTALL_SINFIX:BOOL=ON"
    TEST_BEFORE_INSTALL ${TEST_BEFORE_INSTALL}
)
