list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../TangoCMakeModules)

include(GNUInstallDirs)
find_package(MySQL REQUIRED OPTIONAL_COMPONENTS exe)
find_package(Tango REQUIRED)

get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)

if(NOT CMAKE_BUILD_TYPE AND NOT IS_MULTI_CONFIG)
  message(STATUS "No build type specified - default is DEBUG")
  set(CMAKE_BUILD_TYPE DEBUG)
endif()

option(BUILD_TESTING "Build tests" OFF)
include(CTest)
if (BUILD_TESTING AND WIN32)
  message(WARNING "BUILD_TESTING not supported on Windows.  Forcing OFF")
  set(BUILD_TESTING OFF)
endif()

option(TDB_DATABASE_SCHEMA "Create the tango database schema" OFF)
if (TDB_DATABASE_SCHEMA AND WIN32)
  message(WARNING "TDB_DATABASE_SCHEMA not supported on Windows.  Forcing OFF")
  set(TDB_DATABASE_SCHEMA OFF)
endif()

set(MYSQL_ADMIN "" CACHE STRING "Database user")
set(MYSQL_ADMIN_PASSWD "" CACHE STRING "Database user password")
set(MYSQL_HOST "localhost" CACHE STRING "Database server host with optional port specification")

if(BUILD_TESTING)
  set(TANGO_DB_NAME tango_database_ci CACHE STRING "Name of the tango database" FORCE)
  message(STATUS "Forcing TANGO_DB_NAME to ${TANGO_DB_NAME} for testing")
else()
  set(TANGO_DB_NAME tango CACHE STRING "Name of the tango database")
endif()

if(NOT MYSQL)
  if(MySQL_exe_FOUND)
    message(STATUS "No MySQL client program specified using -DMYSQL - default is ${MySQL_EXECUTABLE}")
    set(MYSQL ${MySQL_EXECUTABLE})
  else()
    message(STATUS "No MySQL client program specified using -DMYSQL and we could not find one.\nDatabase schema creation will not possible.")
    set(TDB_DATABASE_SCHEMA FALSE)
 endif()
endif()

if(BUILD_TESTING AND (NOT MYSQL_ADMIN OR NOT MYSQL_ADMIN_PASSWD))
  message(FATAL_ERROR "For building and running the tests you have to supply both MYSQL_ADMIN and MYSQL_ADMIN_PASSWD.")
endif()

option(TDB_ENABLE_COVERAGE "Instrument code for coverage analysis" OFF)
if(TDB_ENABLE_COVERAGE AND NOT (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang"))
  message(WARNING "TDB_ENABLE_COVERAGE is not supported for selected compiler ${CMAKE_CXX_COMPILER_ID}. Forcing OFF")
  set(TDB_ENABLE_COVERAGE OFF)
endif()

set(DB_SCRIPTS create_db.sql
               create_db_tables.sql
               rem_history.sql
               stored_proc.sql
               update_db_from_5_to_9.3.4.sql
               update_db_from_6_to_9.3.4.sql
               update_db_from_7_to_9.3.4.sql
               update_db_from_8_to_9.3.4.sql
               update_db_from_9.2.5_to_9.3.4.sql
               update_db_from_9.3.4_to_5.22.sql
               update_db_from_5.23_to_5.24.sql
               update_stored_procedures.sql)

if (NOT WIN32)
    set(DB_SCRIPTS ${DB_SCRIPTS} create_db.sh update_stored_procedures.sh)
endif()

if(MYSQL_HOST MATCHES "^(.+):([0-9]+)$")
  set(MYSQL_HOST_WITHOUT_PORT ${CMAKE_MATCH_1})
  set(MYSQL_PORT ${CMAKE_MATCH_2})
else()
  set(MYSQL_HOST_WITHOUT_PORT ${MYSQL_HOST})
  set(MYSQL_PORT "0")
endif()

foreach(DB_SCRIPT_FILE ${DB_SCRIPTS})
  if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${DB_SCRIPT_FILE}.in)
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${DB_SCRIPT_FILE}.in
      ${CMAKE_CURRENT_BINARY_DIR}/${DB_SCRIPT_FILE})
    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DB_SCRIPT_FILE}
      DESTINATION "${CMAKE_INSTALL_DATADIR}/tango/db")
  endif()
endforeach(DB_SCRIPT_FILE)

if (WIN32)
  install(
    FILES
      ${CMAKE_CURRENT_SOURCE_DIR}/create_db.bat
      ${CMAKE_CURRENT_SOURCE_DIR}/update_stored_procedures.bat
    DESTINATION
    "${CMAKE_INSTALL_DATADIR}/tango/db")
endif()

if(MYSQL)
  execute_process(COMMAND ${MYSQL} "--execute=SELECT * FROM ENGINES;" --user=${MYSQL_ADMIN}
    --password=${MYSQL_ADMIN_PASSWD} --host=${MYSQL_HOST_WITHOUT_PORT} --port=${MYSQL_PORT} --protocol=tcp information_schema
                  RESULT_VARIABLE DB_CONNECTION_RESULT
                  OUTPUT_VARIABLE DB_CONNECTION_CHECK_OUTPUT
                  ERROR_VARIABLE DB_CONNECTION_CHECK_ERROR)

  if(NOT DB_CONNECTION_RESULT EQUAL 0)
    message(WARNING "DB Connection check failed with: ${DB_CONNECTION_CHECK_ERROR}")
  else()
    message(STATUS "DB Connection check was successfull")
  endif()

  execute_process(COMMAND ${MYSQL} "--execute=SELECT VERSION();" --user=${MYSQL_ADMIN}
    --password=${MYSQL_ADMIN_PASSWD} --host=${MYSQL_HOST_WITHOUT_PORT} --port=${MYSQL_PORT} --protocol=tcp information_schema
                  RESULT_VARIABLE DB_VERSION_RESULT
                  OUTPUT_VARIABLE DB_VERSION_CHECK_OUTPUT
                  ERROR_VARIABLE DB_VERSION_CHECK_ERROR)

  if(NOT DB_VERSION_RESULT EQUAL 0)
    message(WARNING "DB version check failed with: ${DB_VERSION_CHECK_ERROR}")
  else()
    message(STATUS "DB version check was successfull")
  endif()

  if(TDB_DATABASE_SCHEMA)
    execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/create_db.sh
                    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
                    RESULT_VARIABLE DB_CREATE_SCHEMA_RESULT
                    OUTPUT_VARIABLE DB_CREATE_SCHEMA_OUTPUT
                    ERROR_VARIABLE DB_CREATE_SCHEMA_ERROR)

    if(NOT DB_CREATE_SCHEMA_RESULT EQUAL 0)
      message(FATAL_ERROR "DB schema creation failed with: ${DB_CREATE_SCHEMA_ERROR}")
    else()
      message(STATUS "DB schema creation was successfull.")
    endif()
  endif()
else()
  set(DB_CONNECTION_RESULT 1)
  set(DB_VERSION_RESULT 1)
endif()

# From https://stackoverflow.com/a/41773727
function(invert varName varValue)
  if(${varValue})
    set(${varName} FALSE PARENT_SCOPE)
  else()
    set(${varName} TRUE PARENT_SCOPE)
  endif()
endfunction()

invert("DB_CONNECTION_RESULT" ${DB_CONNECTION_RESULT})
set(TDB_DB_CONNECTION_RESULT ${DB_CONNECTION_RESULT} CACHE INTERNAL "Result of the database connection test")

if(DB_VERSION_RESULT EQUAL 0)
  string(REPLACE "VERSION()" "" DB_VERSION_CHECK_OUTPUT ${DB_VERSION_CHECK_OUTPUT})
  string(STRIP ${DB_VERSION_CHECK_OUTPUT} DB_VERSION_CHECK_OUTPUT)
  set(TDB_DB_VERSION ${DB_VERSION_CHECK_OUTPUT} CACHE INTERNAL "Database server version")
else()
  set(TDB_DB_VERSION "unknown" CACHE INTERNAL "Database server version")
endif()

include(CheckSymbolExists)
check_symbol_exists("explicit_bzero" "string.h" TANGO_EXPLICIT_BZERO)
check_symbol_exists("SecureZeroMemory" "windows.h" TANGO_SECURE_ZERO_MEMORY)
set(CMAKE_REQUIRED_DEFINITIONS "-D__STDC_WANT_LIB_EXT1__=1")
check_symbol_exists("memset_s" "string.h" TANGO_MEMSET_S)
# unset again, prefer block() once 3.25 is required
set(CMAKE_REQUIRED_DEFINITIONS "")
check_symbol_exists("bzero" "strings.h" TANGO_BZERO)
