cmake_minimum_required(VERSION 3.7)
# Use test target on CMake 3.11+
cmake_policy(SET CMP0037 OLD)

project(libtransport)

set(CMAKE_CXX_STANDARD 11)
if(WIN32)
	set(CMAKE_CXX_STANDARD 17)
endif(WIN32)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include(GNUInstallDirs)

include(CPack)
message(STATUS "Variables to override default places where to find libraries:")
message(STATUS "|- cppunit : -DCPPUNIT_INCLUDE_DIR,  -DCPPUNIT_LIBRARY")
message(STATUS "|- swiften : -DSWIFTEN_INCLUDE_DIR,  -DSWIFTEN_LIBRARY")
message(STATUS "  |- zlib  :                         -DZLIB_LIBRARY")
message(STATUS "  |- expat :                         -DEXPAT_LIBRARY")
message(STATUS "  |-libidn :                         -DLIBIDN_LIBRARY")
message(STATUS "  |-libxml :                         -DLIBXML_LIBRARY")
message(STATUS "|- boost   : -DBOOST_INCLUDEDIR,     -DBOOST_LIBRARYDIR")
message(STATUS "|- protobuf: -DPROTOBUF_INCLUDE_DIR, -DPROTOBUF_LIBRARY")
message(STATUS "           : -DPROTOBUF_PROTOC_EXECUTABLE")
message(STATUS "|- log4cxx : -DLOG4CXX_INCLUDE_DIR,  -DLOG4CXX_LIBRARIES")
message(STATUS "|- purple  : -DPURPLE_INCLUDE_DIR,   -DPURPLE_LIBRARY")
message(STATUS "           : -DPURPLE_NOT_RUNTIME - enables compilation with libpurple.lib")
message(STATUS "|- pgxx    : -DPQXX_INCLUDE_DIR,     -DPQXX_LIBRARY")
message(STATUS "|- irc     : -DIRC_INCLUDE_DIR,      -DIRC_LIBRARY")

option(ENABLE_SQLITE3 "Build with SQLite3 support" ON)
option(ENABLE_MYSQL "Build with MySQL support" ON)
option(ENABLE_PQXX "Build with Postgres supoort" ON)

option(ENABLE_FROTZ "Build Frotz plugin" ON)
option(ENABLE_IRC "Build IRC plugin" ON)
option(ENABLE_PURPLE "Build Libpurple plugin" ON)
option(ENABLE_SMSTOOLS3 "Build SMSTools3 plugin" ON)
option(ENABLE_XMPP "Build XMPP plugin" ON)
option(ENABLE_TWITTER "Build Twitter plugin" ON)
option(ENABLE_WEBUI "Build Web UI" ON)

option(ENABLE_DOCS "Build Docs" ON)
# option(ENABLE_LOG "Build with logging using Log4cxx" ON)
option(ENABLE_TESTS "Build Tests using CppUnit" OFF)

macro(LIST_CONTAINS var value)
	set(${var})
	foreach(value2 ${ARGN})
		if(${value} STREQUAL ${value2})
			set(${var} TRUE)
		endif(${value} STREQUAL ${value2})
	endforeach(value2)
endmacro(LIST_CONTAINS)

if(NOT LIB_INSTALL_DIR)
	set(LIB_INSTALL_DIR "lib")
endif()

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules")

###### Prerequisites ######

# FIND SWIFTEN

find_package(Swiften)

if(NOT SWIFTEN_FOUND)
	if(ZLIB_LIBRARY)
		set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${ZLIB_LIBRARY})
	endif()
	if(EXPAT_LIBRARY)
		set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${EXPAT_LIBRARY})
	endif()
	if(LIBIDN_LIBRARY)
		set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${LIBIDN_LIBRARY})
	endif()
	if(LIBXML_LIBRARY)
		set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} ${LIBXML_LIBRARY})
	endif()
	
	set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Dnsapi")
	set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Crypt32")
	set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Secur32")
	set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Iphlpapi")
	set(SWIFTEN_LIBRARY ${SWIFTEN_LIBRARY} "Winscard")
	message(STATUS "Using swiften: ${SWIFTEN_INCLUDE_DIR} ${SWIFTEN_LIBRARY}")
endif()

# FIND BOOST
if(WIN32)
	set(Boost_USE_STATIC_LIBS      OFF)
	set(Boost_USE_MULTITHREADED      ON)
	set(Boost_USE_STATIC_RUNTIME    OFF)
	add_definitions(-DBOOST_ALL_DYN_LINK)
	add_definitions(-DBOOST_ALL_NO_LIB)
	link_directories("$ENV{CMAKE_PREFIX_PATH}/lib")
endif(WIN32)

set(Boost_FIND_QUIETLY ON)
find_package(Boost COMPONENTS program_options date_time system filesystem regex thread locale REQUIRED)

message( STATUS "Found Boost: ${Boost_VERSION}, ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")

if(${Boost_VERSION} GREATER 104999)
	message( STATUS "Using BOOST_FILESYSTEM_VERSION=3")
	add_definitions(-DBOOST_FILESYSTEM_VERSION=3)
endif()
add_definitions(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)

# FIND POPT
if(NOT WIN32)
	find_package(popt REQUIRED)
endif()

###### Database ######

# FIND SQLITE3
if(ENABLE_SQLITE3)
	find_package(sqlite3)
endif()

# FIND MYSQL
if(ENABLE_MYSQL)
	find_package(mysql)
endif()

# FIND PQXX
if(ENABLE_PQXX)
	find_package(pqxx)
endif()

###### Plugins ######

# FIND LIBPURPLE
if(ENABLE_PURPLE)
	find_package(purple)

	if(WIN32)
		if(PURPLE_NOT_RUNTIME)
			add_definitions(-DPURPLE_RUNTIME=0)
		else(PURPLE_NOT_RUNTIME)
			add_definitions(-DPURPLE_RUNTIME=1)
		endif(PURPLE_NOT_RUNTIME)
	else()
		add_definitions(-DPURPLE_RUNTIME=0)
	endif()

	# FIND LIBEVENT
	find_package(event)
endif()

# FIND GLIB
if(ENABLE_PURPLE)
		find_package(GLIB2)
endif()

# FIND LIBXML2
# find_package(libxml2)

# FIND PROTOBUF
find_package(PROTOBUF REQUIRED)

if(NOT PROTOBUF_FOUND AND PROTOBUF_INCLUDE_DIR AND PROTOBUF_LIBRARY)
	set(PROTOBUF_FOUND 1)
	set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
	if(PROTOBUF_PROTOC_EXECUTABLE)
	else()
		set(PROTOBUF_PROTOC_EXECUTABLE protoc)
	endif()
	message(STATUS "Using protobuf: ${PROTOBUF_INCLUDE_DIRS} ${PROTOBUF_LIBRARY}")
endif()

find_package(JsonCpp REQUIRED)

if(WIN32)
	add_definitions(-DSWIFTEN_STATIC=1)
	add_definitions(-D_WIN32_WINNT=0x0600)
	add_definitions(-DWIN32_LEAN_AND_MEAN)
	add_definitions(-DBOOST_USE_WINDOWS_H)
	add_definitions(-D_UNICODE)
	add_definitions(-DUNICODE)
endif()

if(CMAKE_COMPILER_IS_GNUCXX)
	find_package(openssl)
endif()

add_definitions(-DSUPPORT_LEGACY_CAPS)

if(ENABLE_IRC)
	find_package(Communi)
	find_package(Qt5 COMPONENTS Core Network)
endif()

find_package(event)

####### Miscallanous ######

if(ENABLE_DOCS)
	find_package(Doxygen)
endif()

set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(log4cxx)

# FIND CPPUNIT
if(ENABLE_TESTS)
	find_package(CppUnit)

	if(NOT CPPUNIT_FOUND AND CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY)
		set(CCPUNIT_LIBRARIES ${CPPUNIT_LIBRARY})
		set(CPPUNIT_FOUND 1)
		message(STATUS "Using cppunit: ${CPPUNIT_INCLUDE_DIR} ${CPPUNIT_LIBRARIES}")
	endif()
endif()

message("  Supported features")
message("-----------------------")

if(SPECTRUM_VERSION)
	add_definitions(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
else(SPECTRUM_VERSION)
	if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
		if(NOT GIT_EXECUTABLE)
		set (GIT_EXECUTABLE git)
		endif()
		execute_process(COMMAND ${GIT_EXECUTABLE} "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD
						OUTPUT_VARIABLE GIT_REVISION
						OUTPUT_STRIP_TRAILING_WHITESPACE
		)
		set(SPECTRUM_VERSION 2.2.x-git-${GIT_REVISION})
		add_definitions(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
	else(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
		set(SPECTRUM_VERSION 2.2.1)
		add_definitions(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
	endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
endif(SPECTRUM_VERSION)

message("Version           : " ${SPECTRUM_VERSION})

if(SQLITE3_FOUND)
	add_definitions(-DWITH_SQLITE)
	include_directories(${SQLITE3_INCLUDE_DIR})
	message("SQLite3           : yes")
else(SQLITE3_FOUND)
	set(SQLITE3_LIBRARIES "")
	if(ENABLE_SQLITE3)
		message("SQLite3           : no (install sqlite3)")
	else(ENABLE_SQLITE3)
		message("SQLite3           : no (user disabled)")
	endif()
endif(SQLITE3_FOUND)

if(MYSQL_FOUND)
	add_definitions(-DWITH_MYSQL)
	include_directories(${MYSQL_INCLUDE_DIR})
	message("MySQL             : yes")
else(MYSQL_FOUND)
	set(MYSQL_LIBRARIES "")
	if(ENABLE_MYSQL)
		message("MySQL             : no (install mysql-devel)")
	else(ENABLE_MYSQL)
		message("MySQL             : no (user disabled)")
	endif()
endif(MYSQL_FOUND)

if(PQXX_FOUND)
	add_definitions(-DWITH_PQXX -DPQXX_HIDE_EXP_OPTIONAL)
	include_directories(${PQXX_INCLUDE_DIR})
	message("PostgreSQL        : yes")
else(PQXX_FOUND)
	set(PQXX_LIBRARY "")
	set(PQ_LIBRARY "")
	if(ENABLE_PQXX)
		message("PostgreSQL        : no (install libpqxx-devel)")
	else(ENABLE_PQXX)
		message("PostgreSQL        : no (user disabled)")
	endif()
endif(PQXX_FOUND)

if(PROTOBUF_FOUND)
	add_definitions(-DWITH_PROTOBUF)
	include_directories(${PROTOBUF_INCLUDE_DIRS})
	message("Network plugins   : yes")

	if(PURPLE_FOUND)
		message("Libpurple plugin  : yes")
		include_directories(${PURPLE_INCLUDE_DIR})
		include_directories(${GLIB2_INCLUDE_DIR})
	else()
		if(ENABLE_PURPLE)
			message("Libpurple plugin  : no (install libpurple)")
		else(ENABLE_PURPLE)
			message("Libpurple plugin  : no (user disabled)")
		endif()
	endif()

	if(HAVE_EVENT)
		add_definitions(-DWITH_LIBEVENT)
		include_directories(${EVENT_INCLUDE_DIRS})
		message("  libev eventloop : yes")
	else()
		if(ENABLE_PURPLE)
			message("  libev eventloop : no (install libev-devel)")
		endif()
	endif()

	if(IRC_FOUND)
		add_definitions(-DIRC_SHARED)
		message("IRC plugin        : yes")
		include_directories(${QT_QTNETWORK_INCLUDE_DIR})
		include_directories(${IRC_INCLUDE_DIR})
	else()
		if(ENABLE_IRC)
			message("IRC plugin        : no (install libCommuni and libprotobuf-dev)")
		else(ENABLE_IRC)
			message("IRC plugin        : no (user disabled)")
		endif()
	endif()
	if(ENABLE_TWITTER)
		message("Twitter plugin    : yes")
	else(ENABLE_TWITTER)
		message("Twitter plugin    : no (user disabled)")
	endif()
	if(NOT WIN32)
		if(ENABLE_FROTZ)
			message("Frotz plugin      : yes")
		else()
			message("Frotz plugin      : no (user disabled)")
		endif()
		if(ENABLE_SMSTOOLS3)
			message("SMSTools3 plugin  : yes")
		else()
			message("SMSTools3 plugin  : no (user disabled)")
		endif()
	else()
		message("Frotz plugin      : no (does not run on Win32)")
		message("SMSTools3 plugin  : no (does not run on Win32)")
		message("Skype plugin      : no (does not run on Win32)")
	endif()

	if(ENABLE_XMPP)
		message("Swiften plugin    : yes")
	else()
		message("Swiften plugin    : no (user disabled)")
	endif()
else()
	message("Network plugins   : no (install libprotobuf-dev)")
	message("Libpurple plugin  : no (install libpurple and libprotobuf-dev)")
	message("IRC plugin        : no (install libircclient-qt and libprotobuf-dev)")
	message("Frotz plugin      : no (install libprotobuf-dev)")
	message("SMSTools3 plugin  : no (install libprotobuf-dev)")
	message("Swiften plugin    : no (install libprotobuf-dev)")
	message("Twitter plugin    : no (install libprotobuf-dev)")
endif()

if(LOG4CXX_FOUND)
	message("Log4cxx           : yes")
	include_directories(${LOG4CXX_INCLUDE_DIR})
	add_definitions(-DWITH_LOG4CXX)
else()
	set(LOG4CXX_LIBRARIES "")
	if(WIN32)
		message("Log4cxx           : no (install log4cxx-devel)")
	else()
		message(FATAL_ERROR "Log4cxx           : no (install log4cxx-devel)")
	endif()
endif()

if(WIN32)
	add_definitions(-DLOG4CXX_STATIC)
endif()

if(CMAKE_BUILD_TYPE MATCHES Debug)
	if(CMAKE_COMPILER_IS_GNUCXX)
		add_definitions(-O0)
		add_definitions(-ggdb)
	endif()
	add_definitions(-DDEBUG)
	message("Debug             : yes")
else(CMAKE_BUILD_TYPE MATCHES Debug)
	message("Debug             : no (run \"cmake . -DCMAKE_BUILD_TYPE=Debug\")")
endif(CMAKE_BUILD_TYPE MATCHES Debug)

set(TRANSPORT_VERSION 2.0)
set(PROJECT_VERSION 2.0)
include_directories(include)

include_directories(${EVENT_INCLUDE_DIRS})
include_directories(${SWIFTEN_INCLUDE_DIR})
include_directories(${Boost_INCLUDE_DIRS})

if(CMAKE_COMPILER_IS_GNUCXX)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()

add_subdirectory(libtransport)
add_subdirectory(plugin)
add_subdirectory(include)
add_subdirectory(spectrum)
add_subdirectory(backends)
add_subdirectory(tests)
if(NOT WIN32)
	add_subdirectory(spectrum_manager)
#	add_subdirectory(spectrum2_send_message)
endif()

if(CPPUNIT_FOUND)
	message("Tests             : yes")
	include_directories(${CPPUNIT_INCLUDE_DIR})
else()
	if(ENABLE_TESTS)
		message("Tests             : no (install CPPUnit)")
	else(ENABLE_TESTS)
		message("Tests             : no (user disabled)")
	endif()
endif()

if(DOXYGEN_FOUND)
	message("Documentation     : yes")
	add_subdirectory(docs)
else(DOXYGEN_FOUND)
	if(ENABLE_DOCS)
		message("Documentation     : no (install doxygen)")
	else(ENABLE_DOCS)
		message("Documentation     : no (user disabled)")
	endif()
endif(DOXYGEN_FOUND)

message("----------------------")

if(NOT SQLITE3_FOUND AND NOT MYSQL_FOUND AND NOT PQXX_FOUND)
	if(ENABLE_SQLITE3 OR ENABLE_MYSQL OR ENABLE_PQXX)
		message("Could not find any database - Please install at least one of sqlite3-devel, mysql-devel or pqxx-devel if you want to use transport mode.")
	else(ENABLE_SQLITE3 OR ENABLE_MYSQL OR ENABLE_PQXX)
		message("Please enable at least one of SQLITE3, MYSQL, PQXX databases to use transport mode.")
	endif()
endif()
