#Detect (guess) values for most platform. Keep most detection logic in
#functions, to avoid poluting surrounding scope accidentally.

function( detect_platform_variables resultvarname )
  set(provided_vars "")
  macro( provide_var varname )
    list(APPEND provided_vars "${varname}" "${${varname}}")
  endmacro()

  #Check 3 major platforms:
  set( WINDOWS OFF )
  set( DARWIN OFF )
  set( LINUX OFF )
  if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
    set( WINDOWS ON )
  elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
    set( DARWIN ON )
  else()
    set( LINUX ON )
  endif()

  #Exectuable suffixes:
  set( MCCODE_EXE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}" )
  if ( MCCODE_EXE_SUFFIX  MATCHES "^\\." )
    string(SUBSTRING "${MCCODE_EXE_SUFFIX}" 1 -1 MCCODE_EXE_SUFFIX)
  endif()
  provide_var( MCCODE_EXE_SUFFIX )

  #BROWSER (a.k.a. generic "open" command):
  if ( WINDOWS )
    set( BROWSER start )
  elseif( DARWIN )
    set( BROWSER open )
  else()
    set( BROWSER "xdg-open" )
  endif()
  provide_var( BROWSER )

  #Terminal emulater:
  if ( WINDOWS )
    set( TERMINAL start )
  elseif( DARWIN )
    set( TERMINAL open )
  else()
    set( TERMINAL "")
    set( applist x-terminal-emulator gnome-terminal xterm)
    foreach( tmp ${applist} )
      find_program( progpath "${tmp}" )
      if ( progpath )
        set( TERMINAL "${tmp} -e")
        break()
      endif()
    endforeach()
  endif()
  provide_var( TERMINAL )

  #editor:
  if ( WINDOWS )
    set( EDITOR start )
  elseif( DARWIN )
    set( EDITOR open )
  else()
    set( EDITOR "")
    set( applist gedit kate leafpad subl emacs )
    foreach( tmp ${applist} )
      find_program( progpath "${tmp}" )
      if ( progpath )
        set( EDITOR "${tmp}")
        break()
      endif()
    endforeach()
  endif()
  provide_var( EDITOR )

  #idf-generator:
  if ( BUILD_MCSTAS )
    set( IDFGEN mcdisplay-mantid )
  else()
    set( IDFGEN "" )
  endif()
  provide_var( IDFGEN )

  #gsl-flags:
  set( GSLFLAGS "-lgsl -lgslcblas" )
  if ( MCCODE_BUILD_CONDA_PKG )
    set( GSLFLAGS "-I\$\{CONDA_PREFIX\}/include -Wl,-rpath,$\{CONDA_PREFIX\}/lib -L\$\{CONDA_PREFIX\}/lib -lgsl -lgslcblas" )
    if ( WINDOWS )
      if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
        set( GSLFLAGS "/I\$\{CONDA_PREFIX\}/Library/include /link /LIBPATH:\$\{CONDA_PREFIX\}/Library/lib gsl.lib gslcblas.lib" )
      else()
	set( GSLFLAGS "-I\$\{CONDA_PREFIX\}/Library/include -Wl,-rpath,$\{CONDA_PREFIX\}/Library/lib -L\$\{CONDA_PREFIX\}/Library/lib -lgsl -lgslcblas" )
      endif()
    endif()
  endif()
  provide_var( GSLFLAGS )

  #xraylib-flags:
  if ( BUILD_MCSTAS )
    set( XRLFLAGS "" )
  else()
    set( XRLFLAGS "-lxrl" )
    if ( MCCODE_BUILD_CONDA_PKG )
      set( XRLFLAGS "-I\$\{CONDA_PREFIX\}/include -Wl,-rpath,$\{CONDA_PREFIX\}/lib -L\$\{CONDA_PREFIX\}/lib -lxrl" )
      if ( WINDOWS )
	if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
          set( XRLFLAGS "/I\$\{CONDA_PREFIX\}/Library/include /link /LIBPATH:\$\{CONDA_PREFIX\}/Library/lib xrl.lib" )
	else()
	  set( XRLFLAGS "-I\$\{CONDA_PREFIX\}/Library/include -Wl,-rpath,$\{CONDA_PREFIX\}/Library/lib -L\$\{CONDA_PREFIX\}/Library/lib -lxrl" )
	endif()
      endif()
    endif()
  endif()
  provide_var( XRLFLAGS )

  #C compiler:
  set( TOOLS_CC "${CMAKE_C_COMPILER}" )
  provide_var( TOOLS_CC )

  #MPI / OACC variables (don't attempt to detect, just expose here so it is
  #clear how to change them at the CMake cfg level):

  set(OACCFLAGS "-fast -Minfo=accel -acc=gpu -gpu=managed -DOPENACC")
  provide_var( OACCFLAGS )
  set(OACC "nvc")
  provide_var( OACC )
  if ( MPILIB )
    if ( NOT WINDOWS )
      set(MPIFLAGS "-DUSE_MPI -l${MPILIB}")
    else()
      set(MPIFLAGS "-DUSE_MPI -l${MPILIB}")
      if ( MCCODE_BUILD_CONDA_PKG )
	if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
	  set(MPIFLAGS "/DUSE_MPI /link /DYNAMICBASE ${MPILIB}")
	endif()
      endif()
    endif()
  else()
    if ( NOT WINDOWS )
      set(MPILIB "mpi")
      set(MPIFLAGS "-DUSE_MPI -l${MPILIB}")
    else()
      set(MPILIB "msmpi")
      set(MPIFLAGS "-DUSE_MPI -l${MPILIB}")
      if ( MCCODE_BUILD_CONDA_PKG )
	if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
	  set(MPILIB "msmpi.lib")
	  set(MPIFLAGS "/DUSE_MPI /link /DYNAMICBASE ${MPILIB}")
	endif()
      endif()
    endif()
  endif()
  provide_var( MPILIB )
  if ( MPILIBDIR )
     if ( NOT WINDOWS )
       set(MPIFLAGS "-Wl,-rpath,${MPILIBDIR} -L${MPILIBDIR} ${MPIFLAGS}")
     else()
       set(MPIFLAGS "-L${MPILIBDIR} ${MPIFLAGS}")
       if ( MCCODE_BUILD_CONDA_PKG )
	 if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
	   set(MPIFLAGS "${MPIFLAGS} /LIBPATH:${MPILIBDIR}")
	 endif()
       endif()
     endif()
  endif()
  if ( MPIINCLUDEDIR )
    if ( NOT WINDOWS )
      set(MPIFLAGS "-I${MPIINCLUDEDIR} ${MPIFLAGS}")
    else()
      set(MPIFLAGS "-I${MPIINCLUDEDIR} ${MPIFLAGS}")
      if ( MCCODE_BUILD_CONDA_PKG )
	if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
	  set(MPIFLAGS "/I${MPIINCLUDEDIR} ${MPIFLAGS}")
	endif()
      endif()
    endif()
  endif()
  provide_var( MPIFLAGS )
  if ( NOT WINDOWS )
    set(MPIRUN "mpirun")
    set(MPICC "mpicc")
  else()
    set(MPIRUN "mpiexec")
    set(MPICC "${CMAKE_C_COMPILER}")
  endif()
  provide_var( MPIRUN )
  provide_var( MPICC )
  if ( NOT WINDOWS )
    set(NEXUSFLAGS "-DUSE_NEXUS -lNeXus")#?? should probably have another value
  else()
    set(NEXUSFLAGS "-DUSE_NEXUS -lNeXus-0")
    if ( MCCODE_BUILD_CONDA_PKG )
      if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
        set(NEXUSFLAGS "/DUSE_NEXUS NeXus.lib")
      endif()
    endif()
  endif()
  if ( NEXUSLIB )
    set(NEXUSFLAGS "-Wl,-rpath,${NEXUSLIB} -L${NEXUSLIB} ${NEXUSFLAGS}")
  endif()
  if ( NEXUSINCLUDE )
    set(NEXUSFLAGS "${NEXUSFLAGS} -I${NEXUSINCLUDE}")
  endif()
  provide_var( NEXUSFLAGS )

  #C flags:
  include (CheckCCompilerFlag)
  set(MCCODE_CFLAGS "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
  if ( DARWIN AND DEFINED CMAKE_OSX_SYSROOT AND NOT "x${CMAKE_OSX_SYSROOT}" STREQUAL "x" )
    #Attempt to provide the relevant -isysroot on macOS, possibly found by cmake
    set(MCCODE_CFLAGS "${MCCODE_CFLAGS} -isysroot ${CMAKE_OSX_SYSROOT}")
  endif()
  if ( MCCODE_BUILD_CONDA_PKG )
    if ( WINDOWS )
      if ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
        set( MCCODE_CFLAGS "${MCCODE_CFLAGS} /I\$\{CONDA_PREFIX\}/Library/include /link /LIBPATH:\$\{CONDA_PREFIX\}/Library/lib" )
      else()
	set( MCCODE_CFLAGS "${MCCODE_CFLAGS} -I\$\{CONDA_PREFIX\}/Library/include -Wl,-rpath,$\{CONDA_PREFIX\}/Library/lib -L\$\{CONDA_PREFIX\}/Library/lib" )
      endif()
    else()
      set( MCCODE_CFLAGS "${MCCODE_CFLAGS} -I\$\{CONDA_PREFIX\}/include -Wl,-rpath,\$\{CONDA_PREFIX\}/lib -L\$\{CONDA_PREFIX\}/lib" )
    endif()
  endif()
  foreach( flag "-fno-PIC" "-fPIE" "-flto" "-O3" "-mtune=native" "-march=native" "-fno-math-errno" "-ftree-vectorize" "-g" "-DNDEBUG" "-D_POSIX_SOURCE" "-std=c99" "-lm")
    #NB: plethora of "unset(tmp_test_c_flag_result ...)" statements below is
    #added for safety, to prevent CMake's CACHE system to give unpredictable
    #results.
    unset(tmp_test_c_flag_result CACHE)
    unset(tmp_test_c_flag_result )
    check_c_compiler_flag("${flag}" tmp_test_c_flag_result)
    if ( tmp_test_c_flag_result )
      set(MCCODE_CFLAGS "${MCCODE_CFLAGS} ${flag}")
    endif()
    unset(tmp_test_c_flag_result CACHE)
    unset(tmp_test_c_flag_result )
  endforeach()
  provide_var(MCCODE_CFLAGS)

  set(${resultvarname} "${provided_vars}" PARENT_SCOPE)
endfunction()

function( apply_platform_variables detected_var_list )
  while( detected_var_list )
    list( POP_FRONT detected_var_list detected_varname detected_varval)
    if ( NOT DEFINED "${detected_varname}" )
      message("McCode variable: ${detected_varname}=\"${detected_varval}\" (detected)")
      set(${detected_varname} "${detected_varval}" PARENT_SCOPE)
    elseif( "${${detected_varname}}" STREQUAL "${detected_varval}" )
      message("McCode variable: ${detected_varname}=\"${${detected_varname}}\" (provided, but same as detected)")
    else()
      message("McCode variable: ${detected_varname}=\"${${detected_varname}}\"  (provided, ignoring detected \"${detected_varval}\")")
    endif()
  endwhile()
endfunction()

###############################################################

detect_platform_variables( tmp_detected_var_list )
apply_platform_variables( "${tmp_detected_var_list}" )
unset( tmp_detected_var_list )

#A bit of derived variable logic:
set( MCCODE_EXE_SUFFIX_NEVEREMPTY "${MCCODE_EXE_SUFFIX}" )
if ( NOT MCCODE_EXE_SUFFIX_NEVEREMPTY )
  set( MCCODE_EXE_SUFFIX_NEVEREMPTY "out" )
endif()
if ( NOT TERMINAL )
  set( TERMINAL "x-terminal-emulator -e" )
  message(WARNING "Could not detect suitable terminal emulator. Will continue assuming TERMINAL=\"${TERMINAL}\" (set TERMINAL to suitable value to avoid this warning.)")
endif()
if ( NOT EDITOR )
  set( EDITOR "gedit" )
  message(WARNING "Could not detect suitable editor. Will continue assuming EDITOR=\"${editor}\" (set EDITOR to suitable value to avoid this warning.)")
endif()
