cmake_minimum_required(VERSION 2.8)

# project name needs to be the same as the string given to the extend.tcl script in Slicer, so that SPECTRE.sln is created
project(SPECTRE)

# this flag is used during the development of the CMake files to build
# the SPECTRE plugin. The CMakeLists.txt files are checked out from
# and copied into the standard toads-cruise checkout. Hopefully the
# CMakeLists.txt files can be moved into the JHU repository and this
# flag can be set to 0.
set(COPY_FROM_CMAKE_FILES_REPOSITORY 1)


# if building as a Slicer extension, check that the application has java enabled
if (Slicer3_USE_JAVA)
  MESSAGE(STATUS "Slicer3_USE_JAVA is on")
else (Slicer3_USE_JAVA)
  MESSAGE(STATUS "\n***Slicer3_USE_JAVA is '${Slicer3_USE_JAVA}', cannot build SPECTRE without Java.\n")
  RETURN()
endif (Slicer3_USE_JAVA)

include(ExternalProject)

# Compute -G arg for configuring external projects with the same CMake generator:
if(CMAKE_EXTRA_GENERATOR)
  set(gen "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}")
else()
  set(gen "${CMAKE_GENERATOR}")
endif()


#########
# get the path to cvs

FIND_PACKAGE(CVS)

if (${CVS_EXECUTABLE} STREQUAL "CVS_EXECUTABLE-NOTFOUND")
   MESSAGE ( FATAL_ERROR "Could not find valid CVS_EXECUTABLE (found '${CVS_EXECUTABLE}'), necessary to check out this package")
endif ()

#########
# Find a previously installed version of MIPAV.

# set up minimum version requirements for mipav
set(MIPAV_MIN_VERSION 5.0.0)

# Defines MIPAV, which can be used with the java compiler to find jar files
# use MipavMain.class as it's in the windows, linux, and mac distributions
message(STATUS "looking for mipav main class in ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../Slicer3-lib/mipav")
FIND_PATH(MIPAV MipavMain.class
  PATHS "C:/Program Files/mipav" "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../Slicer3-lib/mipav" "/Applications/mipav"
  DOC "Path to MIPAV directory containing MipavMain.class"
)
if ("${MIPAV}" STREQUAL  "MIPAV-NOTFOUND")
message(STATUS "PATH = ${PATH}")
   message(FATAL_ERROR "MIPAV path not found, please install MIPAV (minimum required version ${MIPAV_MIN_VERSION}) and include the directory containing MipavMain.class in your system path, or set it via ccmake or cmake-gui")
endif()

message(STATUS "MIPAV = ${MIPAV}")



########
# try and check the version on the mipav that was found, look for a line in the about.txt file in the MIPAV dir
find_file(MIPAV_ABOUT "about.txt" ${MIPAV})
message(STATUS "MIPAV_ABOUT = ${MIPAV_ABOUT}")

if ("${MIPAV_ABOUT}" STREQUAL  "MIPAV_ABOUT-NOTFOUND")
  message (STATUS "Could not find mipav/about.txt, manual check against minimum version ${MIPAV_MIN_VERSION} may be necessary if SPECTRE fails to build or run")
else()
  file(STRINGS ${MIPAV_ABOUT} MIPAV_VERSION_STRING REGEX "Version:")
  message(STATUS "mipav version string = '${MIPAV_VERSION_STRING}'")
  # this will parse out number.number.number
  string(REGEX MATCH "[0-9]+[.][0-9]+[.][0-9]+" MIPAV_VERSION ${MIPAV_VERSION_STRING} )
  message(STATUS "mipav_version = ${MIPAV_VERSION}")
  if (${MIPAV_VERSION} VERSION_LESS ${MIPAV_MIN_VERSION})
    message(FATAL_ERROR "Version of mipav ${MIPAV_VERSION} is less than minimum required ${MIPAV_MIN_VERSION}, please install a newer version")
  else()
    message(STATUS "Version of mipav ${MIPAV_VERSION} is greater than minimum required ${MIPAV_MIN_VERSION}")
  endif()
endif()

#########
# Download the atlas files
# define path to atlas file
set (SPECTRE_ATLAS_FILENAME SPECTRE_ATLASES-v2.tar.gz)
set (SPECTRE_ATLAS_URL http://www.nitrc.org/frs/download.php/3205/${SPECTRE_ATLAS_FILENAME})
set (SPECTRE_ATLAS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas)

# cannot use URL with a .zip, just .tar.gz or .tgz, (use the download command with .zip, but if it is a windows archive expansion may not work on unix)
# Timeout is in seconds, but not supported in 2.8.0 (it is supported in 2.8.2).
# DL from NITRC to SPL takes over a minute on a very fast connection, so make it a big timeout
# Don't download unless can use the timeout, as it's a 40+Mb file
IF ( ${CMAKE_VERSION} VERSION_GREATER 2.8.1 )
  MESSAGE (STATUS "Adding external project SPECTRE_ATLASES to download atlas file ${SPECTRE_ATLAS_URL}\n\tTimeout = ${TIMEOUT_COMMAND}")
  ExternalProject_Add(
    SPECTRE_ATLASES
    URL ${SPECTRE_ATLAS_URL}
    TIMEOUT 500
    DOWNLOAD_DIR  ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas
    SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas
    CONFIGURE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND ""
#    INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib/Slicer3/spectre_atlas
)

ENDIF ( ${CMAKE_VERSION} VERSION_GREATER 2.8.1 )

#########
# Check out the jist base source code 
SET (sourceDir ${CMAKE_SOURCE_DIR}/jist/JIST/src)

MESSAGE (STATUS "CMAKE_SOURCE_DIR = ${CMAKE_SOURCE_DIR}")

ExternalProject_Add(
  JISTBase
 CVS_REPOSITORY ":pserver:anonymous@www.nitrc.org:/cvsroot/jist"
  CVS_MODULE "JIST/src"
#  CVS_TAG -D "06/01/2010 00:00"
  CVS_TAG -A
  SOURCE_DIR ${sourceDir}
  BINARY_DIR jist-bin
  CMAKE_GENERATOR ${gen}
  CMAKE_ARGS -DMIPAV:PATH=${MIPAV}
  UPDATE_COMMAND ${CVS_EXECUTABLE} update -Pd
  INSTALL_COMMAND ""
)

#########
# also check out the lib dir before configuring the src dir
# MESSAGE ( STATUS "Checking out libs, CVS_EXECUTABLE = ${CVS_EXECUTABLE}" )

SET (sourceDir ${CMAKE_SOURCE_DIR}/jist/JIST)
SET (timeStamp "06/01/2010 00:00")
# co  -d lib -D ${timeStamp} JIST/lib
ExternalProject_Add_Step(JISTBase CheckoutJISTLib
  COMMAND ${CVS_EXECUTABLE} -d :pserver:anonymous@www.nitrc.org:/cvsroot/jist co  -d lib -A JIST/lib
  COMMENT "Check out the jist base lib dir after the src dir"
  DEPENDEES update
  DEPENDERS configure
  WORKING_DIRECTORY ${sourceDir}
)

######
# configure the separately checked out cmake file into the checkout dir
IF ( ${COPY_FROM_CMAKE_FILES_REPOSITORY} )
  message (STATUS "Copying ${CMAKE_CURRENT_SOURCE_DIR}/bin/jist/JIST/src/CMakeLists.txt to ${sourceDir}/CMakeLists.txt ")
  ExternalProject_Add_Step(JISTBase JISTBaseCopyCMakeLists
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bin/jist/JIST/src/CMakeLists.txt ${sourceDir}/src/CMakeLists.txt
    COMMENT "Copy the CMakeLists.txt file into the checkout dir"
    DEPENDEES update
    DEPENDERS configure
    WORKING_DIRECTORY ${sourceDir}
  )
ENDIF()

#########
# Check out the jist plugins

SET (sourceDir ${CMAKE_SOURCE_DIR}/jistPlugins/JIST/src)

ExternalProject_Add(
  JISTPlugins
  CVS_REPOSITORY ":pserver:anonymous@www.nitrc.org:/cvsroot/jhumipavplugins"
  CVS_MODULE "JIST-CVS/JIST/src"
  SOURCE_DIR ${sourceDir}
  BINARY_DIR jistPlugins-bin
  CMAKE_GENERATOR ${gen}
  CMAKE_ARGS -DMIPAV:PATH=${MIPAV}
  UPDATE_COMMAND ${CVS_EXECUTABLE} update -Pd
  INSTALL_COMMAND ""
  DEPENDS JISTBase
)

#########
# also check out the lib dir before configuring the jist plugins src dir
# MESSAGE ( STATUS "Checking out libs, CVS_EXECUTABLE = ${CVS_EXECUTABLE}" )

SET (sourceDir ${CMAKE_SOURCE_DIR}/jistPlugins/JIST)
ExternalProject_Add_Step(JISTPlugins CheckoutJISTPluginsLib
  COMMAND ${CVS_EXECUTABLE} -d :pserver:anonymous@www.nitrc.org:/cvsroot/jhumipavplugins co -d lib JIST-CVS/JIST/lib
  COMMENT "Check out the lib dir after the src dir"
  DEPENDEES update
  DEPENDERS configure
  WORKING_DIRECTORY ${sourceDir}
)

######
# configure the separately checked out cmake file into the checkout dir
IF ( ${COPY_FROM_CMAKE_FILES_REPOSITORY} )
  ExternalProject_Add_Step(JISTPlugins JISTPluginsCopyCMakeLists
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bin/jistPlugins/JIST/src/CMakeLists.txt ${sourceDir}/src/CMakeLists.txt
    COMMENT "Copy the Jist Plugins CMakeLists.txt file into the checkout dir"
    DEPENDEES update
    DEPENDERS configure
    WORKING_DIRECTORY ${sourceDir}
  )
ENDIF()


#########
# external project checkout for toads-cruise

SET (sourceDir ${CMAKE_SOURCE_DIR}/jistCRUISE/JIST/src)

ExternalProject_Add(
  JISTCRUISE
  CVS_REPOSITORY ":pserver:slicerjist:slicer@www.nitrc.org:/cvsroot/toads-cruise"
  CVS_MODULE "toads-cruise/src"
  SOURCE_DIR ${sourceDir}
  BINARY_DIR jistCRUISE-bin
  CMAKE_GENERATOR ${gen}
  CMAKE_ARGS -DMIPAV:PATH=${MIPAV}
  UPDATE_COMMAND ${CVS_EXECUTABLE} update -Pd
  INSTALL_COMMAND ""
  DEPENDS JISTBase JISTPlugins
)

######
# configure the separately checked out cmake file into the checkout dir
IF ( ${COPY_FROM_CMAKE_FILES_REPOSITORY} )
  ExternalProject_Add_Step(JISTCRUISE JISTCRUISECopyCMakeLists
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bin/jistCRUISE/JIST/src/CMakeLists.txt ${sourceDir}/CMakeLists.txt
    COMMENT "Copy the Jist CRUISE CMakeLists.txt file into the checkout dir"
    DEPENDEES update
    DEPENDERS configure
    WORKING_DIRECTORY ${sourceDir}
  )
ENDIF()


#########
# once all the downloads are done, extract the jar files to a top level dir in 
# preparation for super jar of the whole project. Uses an external cmake script file
# first copy the separately checked out .cmake file into the source checkout dir
IF ( ${COPY_FROM_CMAKE_FILES_REPOSITORY} )
  ExternalProject_Add_Step(JISTCRUISE JISTCRUISECopyJarExtract
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bin/JarExtract.cmake ${CMAKE_CURRENT_SOURCE_DIR}/JarExtract.cmake
    COMMENT "Copy the Jist CRUISE JarExtract.cmake file into the checkout dir, from  ${CMAKE_CURRENT_SOURCE_DIR}/bin to ${CMAKE_CURRENT_SOURCE_DIR}"
    DEPENDEES update
    DEPENDERS configure
    WORKING_DIRECTORY ${sourceDir}
  )
ENDIF()

# now extract
#message(STATUS "**** jar extract ext project, working dir = ${CMAKE_CURRENT_BINARY_DIR}")
ExternalProject_Add_Step(JISTCRUISE JarExtract
  COMMAND ${CMAKE_COMMAND} -DsourceDir=${sourceDir} -P ${CMAKE_CURRENT_SOURCE_DIR}/JarExtract.cmake
  COMMENT "Extract the jar files in the source dir to a jarextract dir in the bin dir  ${CMAKE_CURRENT_BINARY_DIR}"
  DEPENDEES JISTCRUISECopyJarExtract
  DEPENDERS configure
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  )


#########
# Now find the java programs
FIND_PACKAGE ( Java 1.6 )

# Since not all dashboard are running cmake 2.8.1, let's set the legacy variable
IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_LESS "2.8.1")
  SET(Java_JAVA_EXECUTABLE ${JAVA_RUNTIME})
  SET(Java_JAVAC_EXECUTABLE ${JAVA_COMPILE})
  SET(Java_JAR_EXECUTABLE ${JAVA_ARCHIVE})
ENDIF()

IF(NOT Java_JAR_EXECUTABLE)
  MESSAGE(STATUS "Skipping Jarring stuff up  - Set Java_JAR_EXECUTABLE variable to fix the problem")
  RETURN()
ENDIF()

#########
# jar them up, from the clean bin subdirs that should just have .class files in them, 
# but have to grab everything from the lib directories, so get the CVS files for now
# The depends is hacky, custom targets can't depend on external projects, so have to do a separate add_dependencies call
ADD_CUSTOM_TARGET ( SPECTRE-SUPER-BASE.jar ALL
      ${Java_JAR_EXECUTABLE} cvf  ${CMAKE_BINARY_DIR}/SPECTRE_Slicer.jar -C "jist-bin/bin"  "." 
      COMMENT "\n\n\nJarring to  ${CMAKE_BINARY_DIR}/SPECTRE_Slicer.jar from working dir ${CMAKE_CURRENT_BINARY_DIR}"
      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(SPECTRE-SUPER-BASE.jar JISTBase JISTPlugins JISTCRUISE)

ADD_CUSTOM_TARGET ( SPECTRE-SUPER-PLUGINS.jar ALL
      COMMAND ${Java_JAR_EXECUTABLE} uvf ${CMAKE_BINARY_DIR}/SPECTRE_Slicer.jar -C "jistPlugins-bin/bin" "." -C  "jarextract" "."
      COMMENT "Adding plugins and jar extract to  ${CMAKE_BINARY_DIR}/SPECTRE_Slicer.jar from working dir ${CMAKE_CURRENT_BINARY_DIR}" 
      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )
add_dependencies(SPECTRE-SUPER-PLUGINS.jar  SPECTRE-SUPER-BASE.jar)

ADD_CUSTOM_TARGET ( SPECTRE-SUPER-CRUISE.jar ALL 
      ${Java_JAR_EXECUTABLE}  uvf ${CMAKE_BINARY_DIR}/SPECTRE_Slicer.jar -C "jistCRUISE-bin/bin" "." 
      COMMENT "Adding cruise class files to  ${CMAKE_BINARY_DIR}/SPECTRE_Slicer.jar from working dir ${CMAKE_CURRENT_BINARY_DIR}" 
      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )
add_dependencies(SPECTRE-SUPER-CRUISE.jar SPECTRE-SUPER-PLUGINS.jar  SPECTRE-SUPER-BASE.jar)

#########
# now configure the slicer wrapper script with path to mipav and the SPECTRE_Slicer.jar
message(STATUS "CMake current source dir =  ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "Spectre binary dir = ${SPECTRE_BINARY_DIR}")

# configure and copy the tcl file to build dir, setting the SPECTRE_SLICER_JAR variable for the configure step 
# (it points to the jar file which will be installed in the same directory as the .tcl file)
# the configure also uses the value of the MIPAV variable
set (SPECTRE_SLICER_JAR ./SPECTRE_Slicer.jar)
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/SPECTRE.tcl.in
		${SPECTRE_BINARY_DIR}/SPECTRE.tcl
		@ONLY
)

# install the jar and tcl files
message(STATUS "Install prefix = ${CMAKE_INSTALL_PREFIX}")
install (
  FILES ${SPECTRE_BINARY_DIR}/SPECTRE_Slicer.jar
  DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/Slicer3
)
install (
  FILES  ${SPECTRE_BINARY_DIR}/SPECTRE.tcl
  DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/Slicer3
)

# install the atlas files from the source dir
if (EXISTS  ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas)
  message (STATUS "Installing atlas files from ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas to ${CMAKE_INSTALL_PREFIX}/lib/Slicer3")
  install (
     DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas
     DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/Slicer3
  )
else (EXISTS  ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas)
  message (WARNING "SPECTRE Atlas archive did not get downloaded to ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas")
endif (EXISTS  ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas)

###############
# configure the python wrapper script in a similar manner to the tcl one
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/SPECTRE.py.in
		${SPECTRE_BINARY_DIR}/SPECTRE.py
		@ONLY
)
# install the python wrapper script
#install (
#  FILES  ${SPECTRE_BINARY_DIR}/SPECTRE.py
#  DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/Slicer3
#)

################
# add a test
ENABLE_TESTING()
INCLUDE(CTest)

# install the CTest config file for nightly testing
MESSAGE(STATUS "Installing ${CMAKE_CURRENT_SOURCE_DIR}/CTestConfig.cmake to ${SPECTRE_BINARY_DIR}")
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CTestConfig.cmake
		${SPECTRE_BINARY_DIR}/CTestConfig.cmake COPYONLY IMMEDIATE)

add_test( SPECTRE_TEST_HEAP_SIZE tclsh ${SPECTRE_BINARY_DIR}/SPECTRE.tcl --maxMemoryUsage 500 --xml)
add_test( SPECTRE_TEST_XML tclsh ${SPECTRE_BINARY_DIR}/SPECTRE.tcl --xml)
add_test( SPECTRE_TEST_INSTALL_XML tclsh ${CMAKE_INSTALL_PREFIX}/lib/Slicer3/SPECTRE.tcl --xml)


# define path to sample input data
set (SPECTRE_TEST_SAMPLE_DATA ${CMAKE_CURRENT_SOURCE_DIR}/spectre_sample_data)

FIND_FILE(SPECTRE_ATLAS_TXT oasis-3-v2.txt
#          ${SPECTRE_ATLAS_PATH}
          ${CMAKE_CURRENT_SOURCE_DIR}/spectre_atlas
          ${CMAKE_INSTALL_PREFIX}/lib/Slicer3/spectre_altas
          Doc "Path to SPECTRE atlas, available from ${SPECTRE_ATLAS_URL}")

if ("${SPECTRE_ATLAS_TXT}" STREQUAL  "SPECTRE_ATLAS_TXT-NOTFOUND")
  message(STATUS "Unable to find SPECTRE atlas, try downloading it from ${SPECTRE_ATLAS_URL} and installing it at ${SPECTRE_ATLAS_PATH}")
else()
  # try to find input data
  FIND_FILE(INPUT_AXIAL_SUBSAMPLE oasis0001_original_axial_subsample.hdr
         ${SPECTRE_TEST_SAMPLE_DATA}
         DOC "Path to input subsampled data")
  if ("${INPUT_AXIAL_SUBSAMPLE}" STREQUAL  "INPUT_AXIAL_SUBSAMPLE-NOTFOUND")
    message(STATUS "Didn't find input file oasis0001_original_axial_subsample.hdr using path ${SPECTRE_TEST_SAMPLE_DATA}. Skipping adding a test.")
  else ()
    message(STATUS "Found input file oasis0001_original_axial_subsample.hdr at ${INPUT_AXIAL_SUBSAMPLE}, adding a test using atlas file  ${SPECTRE_ATLAS_TXT}")
    set(TEMP_DIR "${SPECTRE_BINARY_DIR}/Testing/Temporary")
    file(MAKE_DIRECTORY ${TEMP_DIR})
    add_test( SPECTRE_TEST_SMALL_ATLAS tclsh ${CMAKE_INSTALL_PREFIX}/lib/Slicer3/SPECTRE.tcl --inVolume ${SPECTRE_TEST_SAMPLE_DATA}/oasis0001_original_axial_subsample.hdr --inAtlas ${SPECTRE_ATLAS_TXT} --inImage T1_MPRAGE --outStripped ${TEMP_DIR}/oasis0001_spectre_stripped_axial_subsample.hdr)
# compare is used by the cxx test drivers
#    --compare ${SPECTRE_TEST_SAMPLE_DATA}/oasis0001_spectre_result_axial_subsample.hdr ${TEMP_DIR}/oasis0001_spectre_stripped_axial_subsample.hdr
  endif()
endif()

