# -*- mode: cmake; coding: utf-8; cmake-tab-width: 4; indent-tabs-mode: nil; -*- vim:fenc=utf-8:ft=cmake:et:sw=4:ts=4:sts=4
#------------------------------------------------------------------------
#
# DEFINES:
#   CMAKE_INSTALL_PREFIX  - Installation prefix
#   MATLAB_NO_NODISPLAY   - Run the matlab tests w/o using the -nodisplay option
#   PROG_MATLAB           - Full path to MATLAB executable
#   REPLAY_BLOB_CACHE_DIR - Directory containing replay blobs for testing
#------------------------------------------------------------------------
cmake_minimum_required( VERSION 3.0 FATAL_ERROR )

set(NDS_HOME_PAGE_URL "https://wiki.ligo.org/Computing/NDSClient")
set(NDS_SOURCE_URL "https://software.igwn.org/lscsoft/source")

set( NDS_CLIENT_SWIG_VERSION 0.16.12)
set( NDS_CLIENT_VERSION 0.16.8)

project(nds2-client-swig
    VERSION "${NDS_CLIENT_SWIG_VERSION}"
    LANGUAGES C CXX)

set( CMAKE_CXX_STANDARD 11 )

set( NDS_CONFIG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/config/cmake/")
set( PROJECT_BASENAME nds2-client )

set( CMAKE_MODULE_PATH "${NDS_CONFIG_PATH}/Modules;${CMAKE_MODULE_PATH}" )
set( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE )

include(UseNDS)
include(Cpp11)
include(CheckIncludeFileCXX)

include(CheckCXXCompilerFlag)
include(GNUInstallDirs)
if ( NOT DEFINED CMAKE_INSTALL_PKGDATADIR )
    set( CMAKE_INSTALL_PKGDATADIR ${CMAKE_INSTALL_DATADIR}/nds2-client )
endif( )

cond_set_policy( CMP0042 NEW )
cond_set_policy( CMP0068 NEW )

if (COMBINED_BUILD)
    add_library(nds::cxx ALIAS ndscxx)
    add_library(nds::daqc ALIAS ndsclient)
    set(CONLIBNDSCXX_OBJECTS $<TARGET_OBJECTS:ndscxx_obj>)

    get_target_property(nds2-client_INCLUDE_DIRS nds::cxx INCLUDE_DIRECTORIES)

    message("nds::cxx includes = ${nds2-client_INCLUDE_DIRS}")

    set( NDSTester_FOUND "${CMAKE_CURRENT_SOURCE_DIR}/../client/tests/nds_tester.py" )
    get_filename_component( PROG_NDS_TESTER "${NDSTester_FOUND}" ABSOLUTE)
    get_filename_component ( ABS_TESTERDIR "${CMAKE_CURRENT_SOURCE_DIR}/../client/tests/" ABSOLUTE)
else()
    include(ax_packaging)
    find_package( nds2-client REQUIRED ${NDS_CLIENT_VERSION})
    file( GLOB CONLIBNDSCXX_OBJECTS ${CONLIBNDSCXX_LIBRARY_DIRS}/* )

    find_package(
            NDSTester 0.15.3 REQUIRED
            HINTS ${nds2-client_DIR} )
endif()

include(Autotools/Archive/Archive)
include(Autotools/ArchiveX/ArchiveX)

set( NDS_TESTER_FOUND ${NDSTester_FOUND} )
if ( NDS_TESTER_FOUND )
    set(NDS_TESTER_FLAGS
            "--builddir=\${CMAKE_CURRENT_BINARY_DIR}"
            "--abs-top-srcdir=${CMAKE_CURRENT_SOURCE_DIR}"
            "--abs-srcdir=\${CMAKE_CURRENT_SOURCE_DIR}"
            "--abs-top-builddir=${CMAKE_CURRENT_BINARY_DIR}"
            "--abs-testerdir=${ABS_TESTERDIR}"
            )
endif()

#========================================================================
# Local macros
#========================================================================

macro(is_enabled _VARNAME)
  # ---------------------------------------------------------------------
  #
  # ---------------------------------------------------------------------
  if( ${_VARNAME} )
    set(IS_ENABLED_VALUE "ENABLED")
  else ()
    set(IS_ENABLED_VALUE "DISABLED")
  endif ()
endmacro(is_enabled)

function(set_nds_protocols variable TEST_NAME)
    string(REPLACE "_" ";" name_list ${TEST_NAME})
    list(SORT name_list)
    list(REMOVE_DUPLICATES name_list)
    list(REMOVE_ITEM name_list "")
    ## message(STATUS "DEBUG: set_nds_protocols: name_list: ${name_list}")

    list(FIND name_list nds1 _index)
    if (${_index} GREATER -1)
        set(protocol_list ${NDS_TESTING_PROTOCOLS_NDS1})
    endif (${_index} GREATER -1)

    list(FIND name_list nds2 _index)
    if (${_index} GREATER -1)
        set(protocol_list ${NDS_TESTING_PROTOCOLS_NDS2})
    endif (${_index} GREATER -1)
    list(LENGTH protocol_list len)
    if ( NOT DEFINED protocol_list )
        message(FATAL_ERROR "Unable to determine NDS protocol for test ${TEST_NAME}")
    endif ( NOT DEFINED protocol_list )
    ## message(STATUS "DEBUG: set_nds_protocols: protocol_list: ${protocol_list}")
    set(${variable} ${protocol_list} PARENT_SCOPE)
endfunction(set_nds_protocols)

macro( unquote VAR )
    #--------------------------------------------------------------------
    # Removes outer most level of quotation.
    #--------------------------------------------------------------------
    string( STRIP "${${VAR}}" ${VAR} )
    string( REGEX REPLACE "^\"(.*)\"$" "\\1" ${VAR} ${${VAR}} )
endmacro( unquote VAR )

function( verify_release_info filename pattern )
    #--------------------------------------------------------------------
    # verifies that file has string pattern for release.
    #--------------------------------------------------------------------
    file(READ ${filename} buffer)
    string( FIND "${buffer}" ${pattern} matchres )
    if( ${matchres} EQUAL -1 )
        message( FATAL_ERROR "File: ${filename} has not been updated for release ${pattern}" )
    else( )
        message( STATUS "File: ${filename} has been updated for release ${pattern}" )
    endif( )
endfunction( )

#========================================================================
# Release version number
#========================================================================
set( PACKAGE_NAME ${PROJECT_NAME} )
set( PACKAGE_VERSION ${${PROJECT_NAME}_VERSION} )

# The following line is an input marker for some sed work when doing a
# CI build, it is used to inject an updated version tag when building
# a deb/rep/...  so it is only used on a copy of this file.
##CI_code_version_update

verify_release_info( "${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog.md" "${PROJECT_NAME}-${PROJECT_VERSION}")
verify_release_info( "${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog" "${PROJECT_NAME} (${PROJECT_VERSION}-1)")

#========================================================================
# Prepare for testing
#========================================================================

if ( NOT DEFINED NDS_TESTING_PROTOCOLS_NDS1 )
    set( NDS_TESTING_PROTOCOLS_NDS1
        nds1-12_2 )
endif ( NOT DEFINED NDS_TESTING_PROTOCOLS_NDS1 )
if ( NOT DEFINED NDS_TESTING_PROTOCOLS_NDS2 )
    set( NDS_TESTING_PROTOCOLS_NDS2
        nds2-1_6 nds2-1_5 )
endif ( NOT DEFINED NDS_TESTING_PROTOCOLS_NDS2 )
if ( DEFINED CTEST_TESTING_TIMEOUT )
    set( CTEST_TESTING_TIMEOUT 60 )
endif ( DEFINED CTEST_TESTING_TIMEOUT )

if( NOT CTEST_MEMORYCHECK_COMMAND )
    find_program( CTEST_MEMORYCHECK_COMMAND NAMES valgrind )
endif( NOT CTEST_MEMORYCHECK_COMMAND )
if( NOT MEMORYCHECK_COMMAND )
    set( MEMORYCHECK_COMMAND ${CTEST_MEMORYCHECK_COMMAND} )
endif( NOT MEMORYCHECK_COMMAND )

if( NOT CTEST_MEMORYCHECK_COMMAND_OPTIONS )
    set( CTEST_MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full" )
endif( NOT CTEST_MEMORYCHECK_COMMAND_OPTIONS )
if( NOT MEMORYCHECK_COMMAND_OPTIONS )
    set( MEMORYCHECK_COMMAND_OPTIONS ${CTEST_MEMORYCHECK_COMMAND_OPTIONS} )
endif( NOT MEMORYCHECK_COMMAND_OPTIONS )


include( CTest )


# message( FATAL_ERROR "DEBUG: NDS_TESTER_FOUND: ${NDS_TESTER_FOUND}" )

#========================================================================
# Prepare for distribuition
#========================================================================
#   G e n e r a l
#------------------------------------------------------------------------
set( CPACK_PACKAGE_VENDOR "LIGO" )
set( CPACK_PACKAGE_MAJOR ${${PROJECT_NAME}_MAJOR_VERSION} )
set( CPACK_PACKAGE_MINOR ${${PROJECT_NAME}_MINOR_VERSION} )
set( CPACK_PACKAGE_PATCH ${${PROJECT_NAME}_PATCH_VERSION} )
set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "Client interface to NDS and NDS2 servers" )
set( CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_MAJOR}.${CPACK_PACKAGE_MINOR}.${CPACK_PACKAGE_PATCH}" )
#------------------------------------------------------------------------
#   S O U R C E
#------------------------------------------------------------------------
set( CPACK_SOURCE_GENERATOR TBZ2 )
set( CPACK_SOURCE_PACKAGE_FILE_NAME
     ${PROJECT_NAME}-${${PROJECT_NAME}_VERSION} )
#set( CPACK_SYSTEM_NAME noarch )
set( CPACK_SOURCE_IGNORE_FILES "/.*~$/;/(CVS|autom4te[.]cache)/;/[.]svn/;[.]swap$;[.]#;.*~$;cscope.*")

include(CPack)

cpack_add_component_group(Runtime
                          DESCRIPTION "Pieces needed for running")

#========================================================================
# Find import pieces
#========================================================================

find_package(SWIG 3.0.7 REQUIRED)
if( SWIG_FOUND)
    if( DEFINED SWIG_USE_FILE )
        include(${SWIG_USE_FILE})
    else( )
        include(UseSWIG)
    endif( )
endif( )

message( STATUS "DEBUG: NDS_CLIENT_LIBRARIES: ${NDS_CLIENT_LIBRARIES}" )
message( STATUS "DEBUG: NDS_CLIENT_CFLAGS: ${NDS_CLIENT_CFLAGS}" )
message( STATUS "DEBUG: NDS_CLIENT_INCLUDE_DIRS: ${NDS_CLIENT_INCLUDE_DIRS}" )

#========================================================================
# Get the default python interpreter for testing purposes
#========================================================================

cx_python( PREFIX PYTHON_DFLT )
find_program( PROG_MATLAB matlab )

#========================================================================
# Handle the target languages
#========================================================================

set( SUBPORTS
    ${PROJECT_BASENAME}-java
    ${PROJECT_BASENAME}-matlab
    # ${PROJECT_BASENAME}-octave
    py27-${PROJECT_BASENAME}
    py34-${PROJECT_BASENAME}
    py35-${PROJECT_BASENAME}
    py36-${PROJECT_BASENAME}
    )

add_subdirectory(common)
add_subdirectory(python)
add_subdirectory(java)
add_subdirectory(octave)

add_subdirectory(matlab)

#========================================================================
# Generation of documentation
#========================================================================

find_package(Doxygen)

if(DOXYGEN_FOUND)
  configure_file(
      ${CMAKE_CURRENT_SOURCE_DIR}/manual.txt.in
      ${CMAKE_CURRENT_BINARY_DIR}/manual.txt
      @ONLY )
  #--------------------------------------------------------------------
  # User documentation
  #--------------------------------------------------------------------
  cx_target_manual(
    TARGET SwigUser
    OUTPUT_NAME User
    TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/NDSClientDoc.cfg.in
    ENABLE_SECTIONS "USER_SECTION"
    MAIN_PAGE ${CMAKE_CURRENT_BINARY_DIR}/manual.txt
    HIDE_UNDOC_MEMBERS
    HIDE_UNDOC_CLASSES
    EXCLUDE_PATTERNS */sqlite3.* */test/* */CMakeLists.txt *.in
    )
  cx_target_manual(
    TARGET SwigDeveloper
    OUTPUT_NAME Developer
    TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/NDSClientDoc.cfg.in
    ENABLE_SECTIONS "DEVELOPER_SECTION"
    MAIN_PAGE ${CMAKE_CURRENT_BINARY_DIR}/manual.txt
    EXTRACT_ALL
    EXTRACT_PRIVATE
    EXTRACT_STATIC
    EXTRACT_LOCAL_CLASSES
    EXTRACT_LOCAL_METHODS
    EXTRACT_ANON_NSPACES
    EXCLUDE_PATTERNS */sqlite3.* */test/* */CMakeLists.txt *.in
    )
  cx_target_manual(
    TARGET SwigAdministrator
    OUTPUT_NAME Administrator
    TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/NDSClientDoc.cfg.in
    ENABLE_SECTIONS "ADMIN_SECTION"
    MAIN_PAGE ${CMAKE_CURRENT_BINARY_DIR}/manual.txt
    HIDE_UNDOC_MEMBERS
    HIDE_UNDOC_CLASSES
    EXCLUDE_PATTERNS */sqlite3.* */test/* */CMakeLists.txt *.in
    )
endif(DOXYGEN_FOUND)

#========================================================================
# Provide additional information regarding components
#========================================================================
cpack_add_component(Development
    DISPLAY_NAME "SWIG  extensions"
    DESCRIPTION
        "Pieces needed to build extensions to the nds2 client using SWIG"
        )

#========================================================================
# Testing of the packaging
#========================================================================
if (NOT COMBINED_BUILD)
    set( AX_SOURCE_SPEC_FILENAME "${NDS_CONFIG_PATH}/${PROJECT_NAME}.spec.in" )
    ax_packaging( )
endif()

if ( MACPORTSBUILD AND TARGET macports-subport-${PROJECT_BASENAME}-java )
    add_dependencies(
        macports-subport-${PROJECT_BASENAME}-matlab
        macports-subport-${PROJECT_BASENAME}-java )
endif( )
#========================================================================
# Save command line to file for later rebuilding
#========================================================================
get_cmake_property(CACHE_VARS CACHE_VARIABLES)
foreach(CACHE_VAR ${CACHE_VARS})
  get_property(CACHE_VAR_HELPSTRING CACHE ${CACHE_VAR} PROPERTY HELPSTRING)
  if(CACHE_VAR_HELPSTRING STREQUAL "No help, variable specified on the command line.")
    get_property(CACHE_VAR_TYPE CACHE ${CACHE_VAR} PROPERTY TYPE)
    if(CACHE_VAR_TYPE STREQUAL "UNINITIALIZED")
      set(CACHE_VAR_TYPE)
    else()
      set(CACHE_VAR_TYPE :${CACHE_VAR_TYPE})
    endif()
    set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR}${CACHE_VAR_TYPE}=\"${${CACHE_VAR}}\"")
  endif()
endforeach()
set(USED_CMD_LINE "${CMAKE_COMMAND} ${CMAKE_ARGS} ${CMAKE_CURRENT_SOURCE_DIR}")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/config.status ${USED_CMD_LINE} )
#========================================================================
# Report configuration information
#  CMAKE_MAKE_PROGRAM:FILEPATH
#========================================================================
message(STATUS "=========================================================")
message(STATUS "  ${PROJECT_NAME} has now ben successfully configured:")
is_enabled( ENABLE_SWIG_JAVA )
message(STATUS "      SWIG interface for Java is     ${IS_ENABLED_VALUE}")
is_enabled( ENABLE_SWIG_PYTHON2 )
message(STATUS "      SWIG interface for Python 2 is ${IS_ENABLED_VALUE}")
is_enabled( ENABLE_SWIG_PYTHON3 )
message(STATUS "      SWIG interface for Python 3 is ${IS_ENABLED_VALUE}")
is_enabled( ENABLE_SWIG_OCTAVE )
message(STATUS "      SWIG interface for Octave is   ${IS_ENABLED_VALUE}")
message(STATUS "          Octave version is          ${OCTAVE_VERSION_STRING}" )
is_enabled( ENABLE_SWIG_MATLAB )
message(STATUS "      SWIG interface for MATLAB is   ${IS_ENABLED_VALUE}")
message(STATUS " Other programs:" )
message(STATUS "      SWIG                           ${SWIG_EXECUTABLE} - ${SWIG_VERSION}" )
message(STATUS "      JAVA                           $ENV{JAVA}" )
message(STATUS "      MATLAB                         ${PROG_MATLAB}" )
message(STATUS "      PYTHON2                        ${PYTHON2_EXECUTABLE}" )
message(STATUS "      PYTHON2_VERSION_STRING         ${PYTHON2_VERSION_STRING}" )
message(STATUS "      PYTHON2_LIBRARIES              ${PYTHON2_LIBRARIES}" )
message(STATUS "      PYTHON2LIBS_VERSION_STRING     ${PYTHON2LIBS_VERSION_STRING}" )
message(STATUS "      PYTHON3                        ${PYTHON3_EXECUTABLE}" )
message(STATUS "      PYTHON3_VERSION_STRING         ${PYTHON3_VERSION_STRING}" )
message(STATUS "      PYTHON3_LIBRARIES              ${PYTHON3_LIBRARIES}" )
message(STATUS "      PYTHON3LIBS_VERSION_STRING     ${PYTHON3LIBS_VERSION_STRING}" )
message(STATUS " installation directories:" )
message(STATUS "      CMAKE_INSTALL_BINDIR           ${CMAKE_INSTALL_BINDIR}" )
message(STATUS "      CMAKE_INSTALL_DATADIR          ${CMAKE_INSTALL_DATADIR}" )
message(STATUS " ")
message(STATUS "  Now run 'cmake --build .' to build ${PROJECT_NAME}")
message(STATUS "  and run 'cpack' to package ${PROJECT_NAME}")
message(STATUS "=========================================================")
