SET(HEADERS "")
SET(SOURCES "")

#
# Package-specific configuration options
#

# access explicit instantiation
SET(BDIR ${CMAKE_CURRENT_BINARY_DIR})
IF(${PACKAGE_NAME}_ENABLE_EXPLICIT_INSTANTIATION)
  TRIBITS_INCLUDE_DIRECTORIES(${BDIR}/)
  APPEND_GLOB(HEADERS ${BDIR}/MueLu_ExplicitInstantiation.hpp)
ENDIF()

#
# Belos
#
IF(${PACKAGE_NAME}_ENABLE_Belos)

  TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/belos)

  APPEND_SET(HEADERS belos/BelosXpetraStatusTestGenResSubNorm.hpp belos/BelosMueLuAdapter.hpp)

ENDIF()

#
# Epetra
#
IF(${PACKAGE_NAME}_ENABLE_Epetra)

  TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/epetra)
  TRIBITS_SET_AND_INC_DIRS(DIR ${CMAKE_CURRENT_SOURCE_DIR}/aztecoo)

  APPEND_SET(
    HEADERS
    epetra/MueLu_EpetraOperator.hpp
    epetra/MueLu_CreateEpetraPreconditioner.hpp
    aztecoo/MueLu_AztecEpetraOperator.hpp
  )

  APPEND_SET(
    SOURCES
    epetra/MueLu_EpetraOperator.cpp
    epetra/MueLu_CreateEpetraPreconditioner.cpp
    aztecoo/MueLu_AztecEpetraOperator.cpp
  )

ENDIF()

#
# Tpetra
#
TRIBITS_SET_AND_INC_DIRS(DIR ${CMAKE_CURRENT_SOURCE_DIR}/tpetra)

APPEND_SET(
  HEADERS
  tpetra/MueLu_CreateTpetraPreconditioner.hpp
  tpetra/MueLu_TpetraOperator_decl.hpp
  tpetra/MueLu_TpetraOperator_def.hpp
  tpetra/MueLu_TpetraOperatorAsRowMatrix.hpp
)

IF(${PACKAGE_NAME}_ENABLE_Belos
   AND ${PACKAGE_NAME}_ENABLE_Ifpack2
   AND HAVE_TPETRA_COMPLEX_DOUBLE
)

  APPEND_SET(
    HEADERS
    tpetra/MueLu_ShiftedLaplacian_decl.hpp
    tpetra/MueLu_ShiftedLaplacian_def.hpp
    tpetra/MueLu_ShiftedLaplacianOperator_decl.hpp
    tpetra/MueLu_ShiftedLaplacianOperator_def.hpp
  )

ENDIF()

# TAW 1/20/2016
# it seems that the *.hpp files are automatically generated
# out of the *_decl.hpp and *_def.hpp files. So we do not have
# to call the CREATE_CLIENT_TEMPLATE_HEADERS routine again
#### TRILINOS_CREATE_CLIENT_TEMPLATE_HEADERS(${DIR})

#
# Stratimikos
#
IF(${PACKAGE_NAME}_ENABLE_Stratimikos)
  TRIBITS_SET_AND_INC_DIRS(DIR ${CMAKE_CURRENT_SOURCE_DIR}/stratimikos)

  APPEND_SET(SOURCES ${DIR}/Stratimikos_MueLuHelpers.cpp)

  # TAW 1/20/2016
  # The *.hpp filse should be autogenerated by the CREATE_CLIENT_TEMPLATE_HEADERS
  # call, but we need them already for compilation. Therefore we include them directly.
  APPEND_SET(
    HEADERS
    ${DIR}/Stratimikos_MueLuHelpers.hpp
    ${DIR}/Thyra_MueLuPreconditionerFactory_decl.hpp
    ${DIR}/Thyra_MueLuPreconditionerFactory_def.hpp
    ${DIR}/Thyra_MueLuPreconditionerFactory.hpp
    ${DIR}/Thyra_MueLuRefMaxwellPreconditionerFactory_decl.hpp
    ${DIR}/Thyra_MueLuRefMaxwellPreconditionerFactory_def.hpp
    ${DIR}/Thyra_MueLuRefMaxwellPreconditionerFactory.hpp
    ${DIR}/Thyra_MueLuMaxwell1PreconditionerFactory_decl.hpp
    ${DIR}/Thyra_MueLuMaxwell1PreconditionerFactory_def.hpp
    ${DIR}/Thyra_MueLuMaxwell1PreconditionerFactory.hpp
    ${DIR}/Thyra_XpetraLinearOp_decl.hpp
    ${DIR}/Thyra_XpetraLinearOp_def.hpp
    ${DIR}/Thyra_XpetraLinearOp.hpp
    ${DIR}/Xpetra_ThyraLinearOp.hpp
  )

  # Tpetra specific extensions
  IF(${PACKAGE_NAME}_ENABLE_Stratimikos AND ${PACKAGE_NAME}_ENABLE_ThyraTpetraAdapters)
    TRIBITS_SET_AND_INC_DIRS(DIR ${CMAKE_CURRENT_SOURCE_DIR}/stratimikos)
    IF(${PACKAGE_NAME}_ENABLE_Teko AND ${PACKAGE_NAME}_ENABLE_Experimental)
      TRIBITS_INCLUDE_DIRECTORIES(${DIR}/../../research/q2q1)
      APPEND_SET(
        HEADERS
        ${DIR}/Thyra_MueLuTpetraQ2Q1PreconditionerFactory_decl.hpp
        ${DIR}/Thyra_MueLuTpetraQ2Q1PreconditionerFactory_def.hpp
        ${DIR}/Thyra_MueLuTpetraQ2Q1PreconditionerFactory.hpp
      )
    ENDIF()
  ENDIF()
ENDIF()

IF(${PACKAGE_NAME}_ENABLE_AmgX)

  TRIBITS_SET_AND_INC_DIRS(DIR ${CMAKE_CURRENT_SOURCE_DIR}/amgx)

  APPEND_GLOB(HEADERS ${DIR}/*.hpp)
  APPEND_GLOB(SOURCES ${DIR}/*.cpp)

  # TAW 1/20/2016
  # it seems that the *.hpp files are automatically generated
  # out of the *_decl.hpp and *_def.hpp files. So we do not have
  # to call the CREATE_CLIENT_TEMPLATE_HEADERS routine again
  # #TRILINOS_CREATE_CLIENT_TEMPLATE_HEADERS(${DIR})

ENDIF()

###################################################
## TAW: 9/22/15
## CMake-based ETI system inspired by Ifpack2 ETI
## - no support for KokkosClassic
## - ETI system for muelu-adapters only
## - The ETI system of MueLu is not touched!
###################################################

# Function to generate ETI (explicit template instantiation) files
# from a template and list of class names
FUNCTION(
  MUELUADAPTERS_PROCESS_ETI_TEMPLATE
  ETI_CLASSES
  TEMPLATE_FILE
  PROCESSED_FILE
  SOURCES_LIST
)
  SET(SRCS "")
  FOREACH(CLASS ${ETI_CLASSES})
    STRING(
      REPLACE "::"
              "_"
              CLASS_FILE_NAME
              "${CLASS}"
    )
    STRING(TOUPPER "${CLASS_FILE_NAME}" UPPER_CASE_CLASS)
    STRING(
      REPLACE "CLASS_FILE_NAME"
              "${CLASS_FILE_NAME}"
              FINAL_FILE_NAME
              "${PROCESSED_FILE}"
    )
    CONFIGURE_FILE(${TEMPLATE_FILE} ${FINAL_FILE_NAME})
    SET(SRCS ${SRCS} ${FINAL_FILE_NAME})
  ENDFOREACH()
  SET(${SOURCES_LIST}
      ${SRCS}
      PARENT_SCOPE
  )
ENDFUNCTION(MUELUADAPTERS_PROCESS_ETI_TEMPLATE)

SET(MUELUADAPTERS_ETI_CPP_SOURCES "")
IF(${PACKAGE_NAME}_ENABLE_EXPLICIT_INSTANTIATION)
  # Set the list of classes in MueLu adapters that are templated
  # on <Scalar, LO, GO, Node> for which we want to do ETI using this system.
  GLOBAL_SET(MUELUADAPTERS_ETI_CLASSES)
  IF(${PACKAGE_NAME}_ENABLE_Stratimikos AND ${PACKAGE_NAME}_ENABLE_Thyra)
    APPEND_GLOBAL_SET(MUELUADAPTERS_ETI_CLASSES Thyra::MueLuPreconditionerFactory Thyra::XpetraLinearOp)
  ENDIF()
  IF(${PACKAGE_NAME}_ENABLE_AmgX)
    APPEND_GLOBAL_SET(MUELUADAPTERS_ETI_CLASSES MueLu::AMGXOperator)
  ENDIF()

  # Set the list of classes in MueLu adapters that are templated on <LO, GO, Node> for
  # which we want to do ETI using this system.
  GLOBAL_SET(MUELUADAPTERS_ETI_LO_GO_CLASSES)

  MUELUADAPTERS_PROCESS_ETI_TEMPLATE(
    "${MUELUADAPTERS_ETI_CLASSES}"
    ExplicitInstantiation/MueLu_ETI_SC_LO_GO.tmpl
    "ExplicitInstantiation/CLASS_FILE_NAME.cpp"
    MueLuAdapters_SRCS
  )
  LIST(APPEND MUELUADAPTERS_ETI_CPP_SOURCES ${MueLuAdapters_SRCS})
  MUELUADAPTERS_PROCESS_ETI_TEMPLATE(
    "${MUELUADAPTERS_ETI_LO_GO_CLASSES}"
    ExplicitInstantiation/MueLu_ETI_LO_GO.tmpl
    "ExplicitInstantiation/CLASS_FILE_NAME.cpp"
    MueLuAdapters_SRCS
  )
  LIST(APPEND MUELUADAPTERS_ETI_CPP_SOURCES ${MueLuAdapters_SRCS})

  # add only automatically generated ETI cpp files
  APPEND_SET(SOURCES ${MUELUADAPTERS_ETI_CPP_SOURCES})
ENDIF()

############################################

# Must glob the binary dir last to get all of the auto-generated headers
TRIBITS_SET_AND_INC_DIRS(DIR ${CMAKE_CURRENT_BINARY_DIR})
APPEND_GLOB(HEADERS ${DIR}/*.hpp)
APPEND_GLOB(SOURCES ${DIR}/*.cpp)

IF("${SOURCES}" STREQUAL "")
  # always include at least one file in the adapters library.
  TRIBITS_SET_AND_INC_DIRS(DIR ${CMAKE_CURRENT_SOURCE_DIR})
  APPEND_GLOB(SOURCES ${DIR}/muelu-trivial-adapter.cpp)
ENDIF()
TRIBITS_ADD_LIBRARY(
  muelu-adapters
  HEADERS ${HEADERS}
  SOURCES ${SOURCES}
  DEPLIBS muelu
  ADDED_LIB_TARGET_NAME_OUT MUELU_ADAPTERS_LIBNAME
)

# Set linker language explicitly for CUDA builds.
SET_TARGET_PROPERTIES(${MUELU_ADAPTERS_LIBNAME} PROPERTIES LINKER_LANGUAGE CXX)
