# - Try to find libCeresSolver
#
#  CeresSolver_FOUND - system has libCeresSolver
#  CeresSolver_INCLUDE_DIRS - the libCeresSolver include directories
#  CeresSolver_LIBRARIES - link these to use libCeresSolver

SET(SEARCH_LIBS "/usr/lib;/usr/local/lib;/usr/local/homebrew/lib;/opt/local/lib")
SET(SEARCH_HDRS "/usr/include;/usr/local/include;/usr/local/homebrew/include;/opt/local/include")

####################################################################
# Find CeresSolver lib
####################################################################

FIND_PATH(
  CeresSolver_INCLUDE_DIRS
  NAMES ceres/ceres.h
  PATHS ${SEARCH_HDRS}
)

FIND_LIBRARY(
  CeresSolver_LIBRARY
  NAMES ceres
  PATHS ${SEARCH_LIBS}
)

IF(CeresSolver_INCLUDE_DIRS AND CeresSolver_LIBRARY)
   SET(CeresSolver_LIBRARIES ${CeresSolver_LIBRARY})
   SET(CeresSolver_FOUND TRUE)
ENDIF()

####################################################################
# Find Dependencies (based on ceres CMakeLists.txt
####################################################################

IF(CeresSolver_FOUND)

# Locations to search for SuiteSparse
SET(SUITESPARSE_SEARCH_LIBS ${SEARCH_LIBS})
LIST(APPEND SUITESPARSE_SEARCH_LIBS /usr/lib/suitesparse) # Ubuntu
LIST(APPEND SUITESPARSE_SEARCH_LIBS /usr/local/lib/suitesparse)
LIST(APPEND SUITESPARSE_SEARCH_LIBS /opt/local/lib/ufsparse) # Mac OS X

SET(SUITESPARSE_SEARCH_HEADERS ${SEARCH_HEADERS})
LIST(APPEND SUITESPARSE_SEARCH_HEADERS /usr/include/suitesparse) # Ubuntu
LIST(APPEND SUITESPARSE_SEARCH_HEADERS /usr/local/include/suitesparse)
LIST(APPEND SUITESPARSE_SEARCH_HEADERS /opt/local/include/ufsparse) # Mac OS X

SET(CXSPARSE_SEARCH_LIBS ${SEARCH_LIBS})
SET(CXSPARSE_SEARCH_HEADERS ${SEARCH_HEADERS})
LIST(APPEND CXSPARSE_SEARCH_HEADERS /usr/include/suitesparse) # Ubuntu

# Check for SuiteSparse dependencies
MESSAGE("-- Check for AMD")
SET(AMD_FOUND TRUE)

FIND_LIBRARY(AMD_LIB NAMES amd PATHS ${SUITESPARSE_SEARCH_LIBS})
IF (EXISTS ${AMD_LIB})
  MESSAGE("-- Found AMD library: ${AMD_LIB}")
ELSE (EXISTS ${AMD_LIB})
  MESSAGE("-- Did not find AMD library")
  SET(AMD_FOUND FALSE)
ENDIF (EXISTS ${AMD_LIB})

FIND_PATH(AMD_INCLUDE NAMES amd.h PATHS ${SUITESPARSE_SEARCH_HEADERS})
IF (EXISTS ${AMD_INCLUDE})
  MESSAGE("-- Found AMD header in: ${AMD_INCLUDE}")
ELSE (EXISTS ${AMD_INCLUDE})
  MESSAGE("-- Did not find AMD header")
  SET(AMD_FOUND FALSE)
ENDIF (EXISTS ${AMD_INCLUDE})

MESSAGE("-- Check for CAMD")
SET(CAMD_FOUND TRUE)

FIND_LIBRARY(CAMD_LIB NAMES camd PATHS ${SUITESPARSE_SEARCH_LIBS})
IF (EXISTS ${CAMD_LIB})
  MESSAGE("-- Found CAMD library: ${CAMD_LIB}")
ELSE (EXISTS ${CAMD_LIB})
  MESSAGE("-- Did not find CAMD library")
  SET(CAMD_FOUND FALSE)
ENDIF (EXISTS ${CAMD_LIB})

FIND_PATH(CAMD_INCLUDE NAMES camd.h PATHS ${SUITESPARSE_SEARCH_HEADERS})
IF (EXISTS ${CAMD_INCLUDE})
  MESSAGE("-- Found CAMD header in: ${CAMD_INCLUDE}")
ELSE (EXISTS ${CAMD_INCLUDE})
  MESSAGE("-- Did not find CAMD header")
  SET(CAMD_FOUND FALSE)
ENDIF (EXISTS ${CAMD_INCLUDE})

MESSAGE("-- Check for COLAMD")
SET(COLAMD_FOUND TRUE)

FIND_LIBRARY(COLAMD_LIB NAMES colamd PATHS ${SUITESPARSE_SEARCH_LIBS})
IF (EXISTS ${COLAMD_LIB})
  MESSAGE("-- Found COLAMD library: ${COLAMD_LIB}")
ELSE (EXISTS ${COLAMD_LIB})
  MESSAGE("-- Did not find COLAMD library")
  SET(COLAMD_FOUND FALSE)
ENDIF (EXISTS ${COLAMD_LIB})

FIND_PATH(COLAMD_INCLUDE NAMES colamd.h PATHS ${SUITESPARSE_SEARCH_HEADERS})
IF (EXISTS ${COLAMD_INCLUDE})
  MESSAGE("-- Found COLAMD header in: ${COLAMD_INCLUDE}")
ELSE (EXISTS ${COLAMD_INCLUDE})
  MESSAGE("-- Did not find COLAMD header")
  SET(COLAMD_FOUND FALSE)
ENDIF (EXISTS ${COLAMD_INCLUDE})

MESSAGE("-- Check for CCOLAMD")
SET(CCOLAMD_FOUND TRUE)

FIND_LIBRARY(CCOLAMD_LIB NAMES ccolamd PATHS ${SUITESPARSE_SEARCH_LIBS})
IF (EXISTS ${CCOLAMD_LIB})
  MESSAGE("-- Found CCOLAMD library: ${CCOLAMD_LIB}")
ELSE (EXISTS ${CCOLAMD_LIB})
  MESSAGE("-- Did not find CCOLAMD library")
  SET(CCOLAMD_FOUND FALSE)
ENDIF (EXISTS ${CCOLAMD_LIB})

FIND_PATH(CCOLAMD_INCLUDE NAMES ccolamd.h PATHS ${SUITESPARSE_SEARCH_HEADERS})
IF (EXISTS ${CCOLAMD_INCLUDE})
  MESSAGE("-- Found CCOLAMD header in: ${CCOLAMD_INCLUDE}")
ELSE (EXISTS ${CCOLAMD_INCLUDE})
  MESSAGE("-- Did not find CCOLAMD header")
  SET(CCOLAMD_FOUND FALSE)
ENDIF (EXISTS ${CCOLAMD_INCLUDE})

MESSAGE("-- Check for CHOLMOD")
SET(CHOLMOD_FOUND TRUE)

FIND_LIBRARY(CHOLMOD_LIB NAMES cholmod PATHS ${SUITESPARSE_SEARCH_LIBS})
IF (EXISTS ${CHOLMOD_LIB})
  MESSAGE("-- Found CHOLMOD library: ${CHOLMOD_LIB}")
ELSE (EXISTS ${CHOLMOD_LIB})
  MESSAGE("-- Did not find CHOLMOD library")
  SET(CHOLMOD_FOUND FALSE)
ENDIF (EXISTS ${CHOLMOD_LIB})

FIND_PATH(CHOLMOD_INCLUDE NAMES cholmod.h PATHS ${SUITESPARSE_SEARCH_HEADERS})
IF (EXISTS ${CHOLMOD_INCLUDE})
  MESSAGE("-- Found CHOLMOD header in: ${CHOLMOD_INCLUDE}")
ELSE (EXISTS ${CHOLMOD_INCLUDE})
  MESSAGE("-- Did not find CHOLMOD header")
  SET(CHOLMOD_FOUND FALSE)
ENDIF (EXISTS ${CHOLMOD_INCLUDE})

# If SuiteSparse version is >= 4 then SuiteSparse_config is required.
# For SuiteSparse 3, UFconfig.h is required.
MESSAGE("-- Check for SuiteSparse_config (SuiteSparse v4)")
SET(SUITESPARSE_CONFIG_FOUND TRUE)

FIND_LIBRARY(SUITESPARSE_CONFIG_LIB
             NAMES suitesparseconfig
             PATHS ${SUITESPARSE_SEARCH_LIBS})
IF (EXISTS ${SUITESPARSE_CONFIG_LIB})
  MESSAGE("-- Found SuiteSparse_config library: ${SUITESPARSE_CONFIG_LIB}")
ELSE (EXISTS ${SUITESPARSE_CONFIG_LIB})
  MESSAGE("-- Did not find SuiteSparse_config library")
ENDIF (EXISTS ${SUITESPARSE_CONFIG_LIB})

FIND_PATH(SUITESPARSE_CONFIG_INCLUDE
          NAMES SuiteSparse_config.h
          PATHS ${SUITESPARSE_SEARCH_HEADERS})
IF (EXISTS ${SUITESPARSE_CONFIG_INCLUDE})
  MESSAGE("-- Found SuiteSparse_config header in: ${SUITESPARSE_CONFIG_INCLUDE}")
ELSE (EXISTS ${SUITESPARSE_CONFIG_INCLUDE})
  MESSAGE("-- Did not find SuiteSparse_config header")
ENDIF (EXISTS ${SUITESPARSE_CONFIG_INCLUDE})

IF (NOT EXISTS ${SUITESPARSE_CONFIG_LIB} OR NOT EXISTS ${SUITESPARSE_CONFIG_INCLUDE})
  SET(SUITESPARSE_CONFIG_FOUND FALSE)
ENDIF (NOT EXISTS ${SUITESPARSE_CONFIG_LIB} OR NOT EXISTS ${SUITESPARSE_CONFIG_INCLUDE})

MESSAGE("-- Check for UFconfig (SuiteSparse v3)")
SET(UFCONFIG_FOUND TRUE)

FIND_PATH(UFCONFIG_INCLUDE
          NAMES UFconfig.h
          PATHS ${SUITESPARSE_SEARCH_HEADERS})
IF (EXISTS ${UFCONFIG_INCLUDE})
  MESSAGE("-- Found UFconfig header in: ${UFCONFIG_INCLUDE}")
ELSE (EXISTS ${UFCONFIG_INCLUDE})
  MESSAGE("-- Did not find UFconfig header")
  SET(UFCONFIG_FOUND FALSE)
ENDIF (EXISTS ${UFCONFIG_INCLUDE})

MESSAGE("-- Check for METIS (optional)")
FIND_LIBRARY(METIS_LIB NAMES metis PATHS ${SUITESPARSE_SEARCH_LIBS})

IF (EXISTS ${METIS_LIB})
  MESSAGE("-- Found METIS library: ${METIS_LIB}")
ELSE (EXISTS ${METIS_LIB})
  MESSAGE("-- Did not find METIS library")
ENDIF (EXISTS ${METIS_LIB})

SET(BLAS_AND_LAPACK_FOUND TRUE)
IF (${APPLE})
  # Mac OS X has LAPACK/BLAS bundled in a framework called
  # "vecLib". Search for that instead of for the normal "lapack"
  # library.
  FIND_LIBRARY(LAPACK_LIB NAMES vecLib)
ELSE (${APPLE})
  FIND_LIBRARY(BLAS_LIB NAMES blas)
  IF (EXISTS ${BLAS_LIB})
    MESSAGE("-- Found BLAS library: ${BLAS_LIB}")
  ELSE (EXISTS ${BLAS_LIB})
    MESSAGE("-- Did not find BLAS library")
    SET(BLAS_AND_LAPACK_FOUND FALSE)
  ENDIF (EXISTS ${BLAS_LIB})
  FIND_LIBRARY(LAPACK_LIB NAMES lapack)
ENDIF (${APPLE})

IF (EXISTS ${LAPACK_LIB})
  MESSAGE("-- Found LAPACK library: ${LAPACK_LIB}")
ELSE (EXISTS ${LAPACK_LIB})
  SET(BLAS_AND_LAPACK_FOUND FALSE)
  MESSAGE("-- Did not find LAPACK library")
ENDIF (EXISTS ${LAPACK_LIB})

SET(SUITESPARSE_FOUND
    ${AMD_FOUND} AND
    ${CAMD_FOUND} AND
    ${COLAMD_FOUND} AND
    ${CCOLAMD_FOUND} AND
    ${CHOLMOD_FOUND} AND
    (${SUITESPARSE_CONFIG_FOUND} OR ${UFCONFIG_FOUND}) AND
    ${BLAS_AND_LAPACK_FOUND})

SET(CXSPARSE_FOUND ON)
FIND_LIBRARY(CXSPARSE_LIB NAMES cxsparse PATHS ${CXSPARSE_SEARCH_LIBS})
IF (EXISTS ${CXSPARSE_LIB})
  MESSAGE("-- Found CXSparse library in: ${CXSPARSE_LIB}")
ELSE (EXISTS ${CXSPARSE_LIB})
  MESSAGE("-- Did not find CXSparse header")
  SET(CXSPARSE_FOUND FALSE)
ENDIF (EXISTS ${CXSPARSE_LIB})

FIND_PACKAGE(OpenMP)
FIND_PACKAGE(Protobuf)
FIND_LIBRARY(GLOG_LIB NAMES glog PATHS ${SEARCH_LIBS} )
FIND_LIBRARY(GFLAGS_LIB NAMES gflags PATHS ${SEARCH_LIBS})

ENDIF(CeresSolver_FOUND)

####################################################################
# Add dependencies that were found
####################################################################

SET(CERES_LIBRARY_DEPENDENCIES ${GLOG_LIB})

IF (${SUITESPARSE_FOUND})
  LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CHOLMOD_LIB})
  LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CCOLAMD_LIB})
  LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CAMD_LIB})
  LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${COLAMD_LIB})
  LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${AMD_LIB})
  IF (EXISTS ${SUITESPARSE_CONFIG_LIB})
    LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${SUITESPARSE_CONFIG_LIB})
  ENDIF (EXISTS ${SUITESPARSE_CONFIG_LIB})

  IF (EXISTS ${METIS_LIB})
    LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${METIS_LIB})
  ENDIF (EXISTS ${METIS_LIB})

  LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${LAPACK_LIB})

  IF (EXISTS ${BLAS_LIB})
    LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${BLAS_LIB})
  ENDIF (EXISTS ${BLAS_LIB})
ENDIF (${SUITESPARSE_FOUND})

IF (${CXSPARSE_FOUND})
  LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CXSPARSE_LIB})
ENDIF (${CXSPARSE_FOUND})

IF (${OPENMP_FOUND})
  IF (NOT MSVC)
    LIST(APPEND CERES_LIBRARY_DEPENDENCIES gomp)
  ENDIF (NOT MSVC)
ENDIF (${OPENMP_FOUND})

IF (${PROTOBUF_FOUND})
  LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${PROTOBUF_LIBRARY})
ENDIF (${PROTOBUF_FOUND})

####################################################################
# Set Variables
####################################################################

LIST(APPEND CeresSolver_LIBRARIES ${CERES_LIBRARY_DEPENDENCIES})

IF(CeresSolver_FOUND)
   IF(NOT CeresSolver_FIND_QUIETLY)
      MESSAGE(STATUS "Found CeresSolver: ${CeresSolver_LIBRARIES}")
   ENDIF(NOT CeresSolver_FIND_QUIETLY)
ELSE(CeresSolver_FOUND)
   IF(CeresSolver_FIND_REQUIRED)
      MESSAGE(FATAL_ERROR "Could not find CeresSolver")
   ENDIF(CeresSolver_FIND_REQUIRED)
ENDIF(CeresSolver_FOUND)
