# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file COPYING-CMAKE-SCRIPTS or https://cmake.org/licensing for details.

#[=======================================================================[.rst:
FindSQLite3
-----------
Find the SQLite libraries, v3
IMPORTED targets
^^^^^^^^^^^^^^^^
This module defines the following :prop_tgt:`IMPORTED` target:
``SQLite::SQLite3``
Result variables
^^^^^^^^^^^^^^^^
This module will set the following variables if found:
``SQLite3_INCLUDE_DIRS``
  where to find sqlite3.h, etc.
``SQLite3_LIBRARIES``
  the libraries to link against to use SQLite3.
``SQLite3_VERSION``
  version of the SQLite3 library found
``SQLite3_FOUND``
  TRUE if found

  Copyright (c) 2008 Andreas Schneider <mail@cynapses.org>
  Copyright (c) 2016 NextGIS <info@nextgis.com>
  Copyright (c) 2018,2021 Hiroshi Miura
  Copyright (c) 2019 Chuck Atkins
#]=======================================================================]
include (CMakePushCheckState)
# Accept upper case variant for SQLite3_INCLUDE_DIR
if(SQLITE3_INCLUDE_DIR)
  if(SQLite3_INCLUDE_DIR AND NOT "${SQLite3_INCLUDE_DIR}" STREQUAL "${SQLITE3_INCLUDE_DIR}")
    message(FATAL_ERROR "Both SQLite3_INCLUDE_DIR and SQLITE3_INCLUDE_DIR are defined, but not at same value")
  endif()
  set(SQLite3_INCLUDE_DIR "${SQLITE3_INCLUDE_DIR}" CACHE STRING "Path to a file" FORCE)
  unset(SQLITE3_INCLUDE_DIR CACHE)
endif()

# Accept upper case variant for SQLite3_LIBRARY
if(SQLITE3_LIBRARY)
  if(SQLite3_LIBRARY AND NOT "${SQLite3_LIBRARY}" STREQUAL "${SQLITE3_LIBRARY}")
    message(FATAL_ERROR "Both SQLite3_LIBRARY and SQLITE3_LIBRARY are defined, but not at same value")
  endif()
  set(SQLite3_LIBRARY "${SQLITE3_LIBRARY}" CACHE FILEPATH "Path to a library" FORCE)
  unset(SQLITE3_LIBRARY CACHE)
endif()

if(SQLite3_INCLUDE_DIR AND SQLite3_LIBRARY)
  set(SQLite3_FIND_QUIETLY TRUE)
else()
  find_package(PkgConfig QUIET)
  if(PKG_CONFIG_FOUND)
      pkg_check_modules(PC_SQLITE3 QUIET sqlite3)
  endif()

  find_path(SQLite3_INCLUDE_DIR
            NAMES  sqlite3.h
            HINTS ${PC_SQLITE3_INCLUDE_DIRS})
  find_library(SQLite3_LIBRARY
               NAMES sqlite3 sqlite3_i
               NAMES_PER_DIR
               HINTS ${PC_SQLITE3_LIBRARY_DIRS})
endif()

# Extract version information from the header file
if(SQLite3_INCLUDE_DIR)
    file(STRINGS ${SQLite3_INCLUDE_DIR}/sqlite3.h _ver_line
         REGEX "^#define SQLITE_VERSION  *\"[0-9]+\\.[0-9]+\\.[0-9]+\""
         LIMIT_COUNT 1)
    string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+"
           SQLite3_VERSION "${_ver_line}")
    unset(_ver_line)
endif()

if(SQLite3_INCLUDE_DIR AND SQLite3_LIBRARY)
    include(CheckSymbolExists)
    cmake_push_check_state(RESET)
    # check column metadata
    set(CMAKE_REQUIRED_INCLUDES ${SQLite3_INCLUDE_DIR})
    if( ${SQLite3_LIBRARY} MATCHES "libsqlite3.a")
      if(PC_SQLITE3_STATIC_LDFLAGS)
        set(CMAKE_REQUIRED_LIBRARIES ${PC_SQLITE3_STATIC_LDFLAGS})
      else()
        # Manually try likely additional private libraries
        set(CMAKE_REQUIRED_LIBRARIES ${SQLite3_LIBRARY})
        check_symbol_exists(sqlite3_open sqlite3.h SQLite3_HAS_OPEN)
        if(NOT SQLite3_HAS_OPEN)
            unset(SQLite3_HAS_OPEN)
            unset(SQLite3_HAS_OPEN CACHE)
            set(CMAKE_REQUIRED_LIBRARIES ${SQLite3_LIBRARY} -lz)
            check_symbol_exists(sqlite3_open sqlite3.h SQLite3_HAS_OPEN)
        endif()
        if(NOT SQLite3_HAS_OPEN)
            unset(SQLite3_HAS_OPEN)
            unset(SQLite3_HAS_OPEN CACHE)
            set(CMAKE_REQUIRED_LIBRARIES ${SQLite3_LIBRARY} -lm)
            check_symbol_exists(sqlite3_open sqlite3.h SQLite3_HAS_OPEN)
        endif()
        if(NOT SQLite3_HAS_OPEN)
            unset(SQLite3_HAS_OPEN)
            unset(SQLite3_HAS_OPEN CACHE)
            set(CMAKE_REQUIRED_LIBRARIES ${SQLite3_LIBRARY} -lz -lm)
            check_symbol_exists(sqlite3_open sqlite3.h SQLite3_HAS_OPEN)
        endif()
        if(NOT SQLite3_HAS_OPEN)
            unset(SQLite3_HAS_OPEN)
            unset(SQLite3_HAS_OPEN CACHE)
            set(CMAKE_REQUIRED_LIBRARIES ${SQLite3_LIBRARY} -lz -lm -lpthread -ldl)
            check_symbol_exists(sqlite3_open sqlite3.h SQLite3_HAS_OPEN)
        endif()
      endif()
    else()
        set(CMAKE_REQUIRED_LIBRARIES ${SQLite3_LIBRARY})
    endif()

    # Trick to force CMake to re-run if SQLite3_LIBRARY changes
    # Useful in development situations when switching/refreshing the library
    set_property(
        DIRECTORY
        APPEND
        PROPERTY CMAKE_CONFIGURE_DEPENDS "${SQLite3_LIBRARY}"
    )
    # Invalidate cached variables if SQLite3_LIBRARY changes
    file(TIMESTAMP "${SQLite3_LIBRARY}" SQLite3_LIBRARY_TIMESTAMP)
    if( SQLite3_LIBRARY_TIMESTAMP_OLD_VAL AND
        NOT "${SQLite3_LIBRARY_TIMESTAMP_OLD_VAL}" STREQUAL "${SQLite3_LIBRARY_TIMESTAMP}")
        get_cmake_property(_cache_variables CACHE_VARIABLES)
        foreach(opt IN LISTS _cache_variables)
            if ("${opt}" MATCHES "SQLite3_HAS_")
                message(STATUS "Invalidating ${opt}")
                unset(${opt} CACHE)
            endif()
        endforeach()
    endif()
    set(SQLite3_LIBRARY_TIMESTAMP_OLD_VAL "${SQLite3_LIBRARY_TIMESTAMP}" CACHE INTERNAL "Old value of option SQLite3_LIBRARY_TIMESTAMP")

    check_symbol_exists(sqlite3_mutex_alloc sqlite3.h SQLite3_HAS_MUTEX_ALLOC)
    check_symbol_exists(sqlite3_column_table_name sqlite3.h SQLite3_HAS_COLUMN_METADATA)
    check_symbol_exists(sqlite3_rtree_query_callback sqlite3.h SQLite3_HAS_RTREE)
    check_symbol_exists(sqlite3_load_extension sqlite3.h SQLite3_HAS_LOAD_EXTENSION)
    # https://www.sqlite.org/compile.html recommends to build with -DSQLITE_OMIT_PROGRESS_CALLBACK
    # "for applications that are able to use them"... This is sometimes wrongly
    # understood as recommended in all situations.
    check_symbol_exists(sqlite3_progress_handler sqlite3.h SQLite3_HAS_PROGRESS_HANDLER)

    if (MSVC)
        set(CMAKE_REQUIRED_FLAGS "/WX")
      else ()
        set(CMAKE_REQUIRED_FLAGS "-Werror")
      endif ()
    set(SQLITE3_AUTO_EXTENSION_CHECK
        "#include <sqlite3.h>
         int main(){
          return sqlite3_auto_extension ((void (*)(void)) 0);
         }")
    if(CMAKE_C_COMPILER_LOADED)
        check_c_source_compiles("${SQLITE3_AUTO_EXTENSION_CHECK}" SQLite3_HAS_NON_DEPRECATED_AUTO_EXTENSION)
    elseif(CMAKE_CXX_COMPILER_LOADED)
        check_cxx_source_compiles("${SQLITE3_AUTO_EXTENSION_CHECK}" SQLite3_HAS_NON_DEPRECATED_AUTO_EXTENSION)
    else()
        message(AUTHOR_WARNING "C and CXX languages not enabled: Skipping detection of sqlite3_auto_extension.")
    endif()
    cmake_pop_check_state()
endif()
mark_as_advanced(SQLite3_LIBRARY SQLite3_INCLUDE_DIR SQLite3_HAS_COLUMN_METADATA SQLite3_HAS_RTREE SQLite3_HAS_LOAD_EXTENSION)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SQLite3
                                  FOUND_VAR SQLite3_FOUND
                                  REQUIRED_VARS SQLite3_LIBRARY SQLite3_INCLUDE_DIR
                                  VERSION_VAR SQLite3_VERSION)

if(SQLite3_FOUND)
  set(SQLite3_LIBRARIES ${SQLite3_LIBRARY})
  set(SQLite3_INCLUDE_DIRS ${SQLite3_INCLUDE_DIR})
  if(NOT TARGET SQLite::SQLite3)
    add_library(SQLite::SQLite3 UNKNOWN IMPORTED)
    set_target_properties(SQLite::SQLite3 PROPERTIES
                          INTERFACE_INCLUDE_DIRECTORIES "${SQLite3_INCLUDE_DIRS}"
                          IMPORTED_LINK_INTERFACE_LANGUAGES "C"
                          IMPORTED_LOCATION "${SQLite3_LIBRARY}")
    if(SQLite3_HAS_COLUMN_METADATA)
        set_property(TARGET SQLite::SQLite3 APPEND PROPERTY
                     INTERFACE_COMPILE_DEFINITIONS "SQLite3_HAS_COLUMN_METADATA")
    endif()
    if(SQLite3_HAS_RTREE)
        set_property(TARGET SQLite::SQLite3 APPEND PROPERTY
                     INTERFACE_COMPILE_DEFINITIONS "SQLite3_HAS_RTREE")
    endif()
  endif()
endif()
