phi_include_guard()

include(Functions)

# Detect information about the build environment

# Detect Platform
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
  phi_set_cache_value(NAME PHI_PLATFORM_WINDOWS VALUE 1)
  phi_trace("Platform: Windows")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
  phi_set_cache_value(NAME PHI_PLATFORM_UNIX VALUE 1)
  phi_trace("Platform: Unix")

  if(ANDROID)
    phi_set_cache_value(NAME PHI_PLATFORM_ANDROID VALUE 1)
    phi_trace("Platform: Android")
  else()
    phi_set_cache_value(NAME PHI_PLATFORM_LINUX VALUE 1)
    phi_trace("Platform: Linux")
  endif()
elseif(CMAKE_SYSTEM_NAME MATCHES "^k?FreeBSD$")
  phi_set_cache_value(NAME PHI_PLATFORM_FREEBSD VALUE 1)
  phi_trace("Platform: FreeBSD")
elseif(CMAKE_SYSTEM_NAME MATCHES "^OpenBSD$")
  phi_set_cache_value(NAME PHI_PLATFORM_OPENBSD VALUE 1)
  phi_trace("Platform: OpenBSD")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
  if(IOS)
    phi_set_cache_value(NAME PHI_PLATFORM_IOS VALUE 1)
    phi_trace("Platform: IOS")
  else()
    phi_set_cache_value(NAME PHI_PLATFORM_MACOSX VALUE 1)
    phi_trace("Platform: MacOS")
  endif()
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
  phi_set_cache_value(NAME PHI_PLATFORM_ANDROID VALUE 1)
  phi_trace("Platform: Android")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
  phi_set_cache_value(NAME PHI_PLATFORM_EMSCRIPTEN VALUE 1)
  phi_trace("Platform: Emscripten")
else()
  phi_warn("Unsupported operating system or environment: ${CMAKE_SYSTEM_NAME}")
endif()

# Detect the architecture (note: this test won't work for cross-compilation)
include(CheckTypeSize)
check_type_size(void* SIZEOF_VOID_PTR BUILTIN_TYPES_ONLY LANGUAGE CXX)
if(${SIZEOF_VOID_PTR} STREQUAL "4")
  phi_set_cache_value(NAME PHI_ARCH_32BITS VALUE 1)
  phi_set_cache_value(NAME PHI_SIZEOF_VOID_PTR VALUE 4)

  phi_trace("Arch: 32bits")
elseif(${SIZEOF_VOID_PTR} STREQUAL "8")
  phi_set_cache_value(NAME PHI_ARCH_64BITS VALUE 1)
  phi_set_cache_value(NAME PHI_SIZEOF_VOID_PTR VALUE 8)

  phi_trace("Arch: 64bits")
else()
  phi_warn("Unsupported architecture of size ${SIZEOF_VOID_PTR}")
endif()

# Detect compiler
if(CMAKE_CXX_COMPILER MATCHES "clang[+][+]" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  # CMAKE_CXX_COMPILER_ID is an internal CMake variable subject to change, but there is no other way
  # to detect CLang at the moment
  phi_set_cache_value(NAME PHI_COMPILER_CLANG VALUE 1)
  execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE CLANG_VERSION_OUTPUT)
  string(REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" PHI_CLANG_VERSION
                       "${CLANG_VERSION_OUTPUT}")

  phi_trace("Compiler: Clang-${PHI_CLANG_VERSION}")

  # Test for AppleClang
  if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
    phi_set_cache_value(NAME PHI_COMPILER_APPLECLANG VALUE 1)
    phi_trace("Compiler: AppleClang")
  endif()
elseif(CMAKE_COMPILER_IS_GNUCXX)
  phi_set_cache_value(NAME PHI_COMPILER_GCC VALUE 1)

  execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-dumpversion" OUTPUT_VARIABLE GCC_VERSION_OUTPUT)
  string(REGEX REPLACE "([0-9]+\\.[0-9]+).*" "\\1" PHI_GCC_VERSION "${GCC_VERSION_OUTPUT}")
  execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE GCC_COMPILER_VERSION)
  string(REGEX MATCHALL ".*(tdm[64]*-[1-9]).*" PHI_COMPILER_GCC_TDM "${GCC_COMPILER_VERSION}")
  execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-dumpmachine" OUTPUT_VARIABLE GCC_MACHINE)
  string(STRIP "${GCC_MACHINE}" GCC_MACHINE)

  phi_trace("Compiler: gcc")

  if(GCC_MACHINE MATCHES ".*w64.*")
    phi_set_cache_value(NAME PHI_COMPILER_GCC_W64 VALUE 1)
  endif()
elseif(MSVC)
  phi_set_cache_value(NAME PHI_COMPILER_MSVC VALUE 1)

  if(MSVC_VERSION EQUAL 1400)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 8)
  elseif(MSVC_VERSION EQUAL 1500)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 9)
  elseif(MSVC_VERSION EQUAL 1600)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 10)
  elseif(MSVC_VERSION EQUAL 1700)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 11)
  elseif(MSVC_VERSION EQUAL 1800)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 12)
  elseif(MSVC_VERSION EQUAL 1900)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14)
  elseif(MSVC_VERSION EQUAL 1910)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.1)
  elseif(MSVC_VERSION EQUAL 1911)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.11)
  elseif(MSVC_VERSION EQUAL 1912)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.12)
  elseif(MSVC_VERSION EQUAL 1913)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.13)
  elseif(MSVC_VERSION EQUAL 1914)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.14)
  elseif(MSVC_VERSION EQUAL 1915)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.15)
  elseif(MSVC_VERSION EQUAL 1916)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.16)
  elseif(MSVC_VERSION EQUAL 1920)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.2)
  elseif(MSVC_VERSION EQUAL 1921)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.21)
  elseif(MSVC_VERSION EQUAL 1922)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.22)
  elseif(MSVC_VERSION EQUAL 1923)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.23)
  elseif(MSVC_VERSION EQUAL 1924)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.24)
  elseif(MSVC_VERSION EQUAL 1925)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.25)
  elseif(MSVC_VERSION EQUAL 1926)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.26)
  elseif(MSVC_VERSION EQUAL 1927)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.27)
  elseif(MSVC_VERSION EQUAL 1928)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.28)
  elseif(MSVC_VERSION EQUAL 1929)
    phi_set_cache_value(NAME PHI_MSVC_VERSION VALUE 14.29)
  else()
    phi_warn("Unknown version of MSVC used. MSVC_VERSION=${MSVC_VERSION}")
  endif()

  if(PHI_MSVC_VERSION)
    phi_log("Compiler: MSVC ${PHI_MSVC_VERSION}")
  endif()
else()
  phi_warn("Unsupported compiler ${CMAKE_CXX_COMPILER_ID}")
endif()

# Check if CI Build
if(DEFINED ENV{CI})
  phi_set_cache_value(NAME PHI_CI_BUILD VALUE TRUE)
else()
  phi_set_cache_value(NAME PHI_CI_BUILD VALUE FALSE)
endif()

include(ProcessorCount)
ProcessorCount(ProcCount)
if(NOT ProcCount EQUAL 0)
  phi_set_cache_value(NAME PHI_PROCESSOR_COUNT VALUE ${ProcCount})
else()
  phi_warn("Failed to get processor count")

  # We always assume to have atleast one processor
  phi_set_cache_value(NAME PHI_PROCESSOR_COUNT VALUE 1)
  set(PHI_PROCESSOR_COUNT 1)
endif()

phi_trace("Processor Count: ${PHI_PROCESSOR_COUNT}")
