# disable in source builds to protect against overwriting other Makefiles
#set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
if( NOT DEFINED ENV{CC} )
  find_path( crayComp "ftn" )
  find_path( wcossIntel "mpfort" )
  find_path( intelComp "ifort" )
  find_path( pgiComp "pgf90" )
  if( crayComp )
    message("Setting CrayLinuxEnvironment")
    set(CMAKE_SYSTEM_NAME "CrayLinuxEnvironment")
    set(CMAKE_C_COMPILER "${crayComp}/cc")
    set(CMAKE_CXX_COMPILER "${crayComp}/CC")
    set(CMAKE_Fortran_COMPILER "${crayComp}/ftn")
  endif()
  if( intelComp )
    set(ENV{CC} "icc")
    set(ENV{CXX} "icpc")
    set(ENV{FC} "ifort")
  endif()
  if( wcossIntel )
    message("Setting env for wcoss intel")
    set(ENV{CC} "mpcc")
    set(ENV{CXX} "mpCC")
    set(ENV{FC} "mpfort")
  endif()
  if( pgiComp )
    set(ENV{CC} "pgcc")
    set(ENV{CXX} "pgCC")
    set(ENV{FC} "pgf90")
  endif()
endif()

project(GSI)
  enable_language (Fortran)
  option(USE_WRF "Find WRF object files and build regional GSI model" ON)
  option(USE_BASELIBS "Look for and use GMAO Baselibs" OFF)
  option(BUILD_GLOBAL "Build GSI without WRF (regional) module " OFF)
  option(BUILD_ENKF "Build the Enkf executable " ON)
  option(USE_BASELINE "Use baseline control runs" ON)
  SET(ENKF_MODE "GFS" CACHE STRING "EnKF build mode: GFS, WRF, NMMB")
  string(TOUPPER ${ENKF_MODE} ENKF_MODE)
  if (ENKF_MODE MATCHES "^GFS$")
    message("Build the EnKF with GFS module")
    option(BUILD_GFS "Build the Enkf with GFS module " ON)
    option(BUILD_NMMB "Build the Enkf with NMMB module " OFF)
    option(BUILD_WRF "Build the Enkf with WRF module " OFF)
  elseif (ENKF_MODE MATCHES "^WRF$")
    message("Build the EnKF with WRF module")
    option(BUILD_GFS "Build the Enkf with GFS module " OFF)
    option(BUILD_NMMB "Build the Enkf with NMMB module " OFF)
    option(BUILD_WRF "Build the Enkf with WRF module " ON)
  elseif (ENKF_MODE MATCHES "^NMMB$")
    message("Build the EnKF with NMMB module")
    option(BUILD_GFS "Build the Enkf with GFS module " OFF)
    option(BUILD_NMMB "Build the Enkf with NMMB module " ON)
    option(BUILD_WRF "Build the Enkf with WRF module " OFF)
  else()
    message("unkown ENKF_MODE: ${ENKF_MODE} !\nBuild the EnKF with GFS module by default")
    option(BUILD_GFS "Build the Enkf with GFS module " ON)
    option(BUILD_NMMB "Build the Enkf with NMMB module " OFF)
    option(BUILD_WRF "Build the Enkf with WRF module " OFF)
  endif()
  option(BUILD_UTIL "Build the Enkf utilities " OFF)

  option(BUILD_UTIL_COM "Build community utilities " OFF)
  option(BUILD_ENKF_PREPROCESS_ARW "Build enkf preprocess for ARW " OFF)
  option(BUILD_COV_CALC "Build the Desroziers utility" OFF)
  option(BUILD_NCDIAG "Build the NCDIAG libraries" ON)
  option(BUILD_FV3GFS_NCIO "Build the FV3GFS_NCIO library" ON)
  option(BUILD_NCIO_UTIL "Build the NCIO Utilities" ON)
  option(BUILD_NCDIAG_SERIAL "Build the serial NCDIAG libraries" ON)
  option(BUILD_REG_TESTING "Build the Regression Testing Suite" ON)
  option(BUILD_UNIT_TESTING "Build the Unit Testing Suite" OFF)
  option(BUILD_GSDCLOUD_ARW "Build the GSD cloud analysis " OFF)
  option(BUILD_GSDCLOUD_NMMB "Build the GSD cloud analysis " OFF)
  cmake_minimum_required(VERSION 2.8)
  set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
  SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
  SET(ARCHIVE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
  set(CMAKE_INCLUDE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/include")
  set(CMAKE_INCLUDE_4_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/include4")
  set(Fortran_MODULE_DIRECTORY "${PROJECT_BINARY_DIR}/include")
  set(CMAKE_Fortran_MODULE_DIRECTORY "${PROJECT_BINARY_DIR}/include")
  file(MAKE_DIRECTORY ${CMAKE_INCLUDE_OUTPUT_DIRECTORY})
  file(MAKE_DIRECTORY ${CMAKE_INCLUDE_4_OUTPUT_DIRECTORY})
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/setPlatformVariables.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/setIntelFlags.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/setGNUFlags.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/setPGIFlags.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/setHOST.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Acorn.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Cheyenne.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Discover.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Generic.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Gaea.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Jet.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/S4.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Hera.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Orion.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/WCOSS-C.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/WCOSS-D.cmake)
  include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/WCOSS.cmake)
  if(BUILD_REG_TESTING)
    set(CTEST_TEST_TIMEOUT 86400 )
    find_package(GSICONTROL)
    include( CTest )
  endif(BUILD_REG_TESTING)

  cmake_policy(SET CMP0009 NEW)
  find_package(OpenMP)
  message("found openmp with flag ${OPENMP_Fortran_FLAGS}")

# Set Host specific flags and options
  setHOST()

  MESSAGE(${CMAKE_CURRENT_SOURCE_DIR})
  # make sure that the default is a RELEASE
  if (NOT CMAKE_BUILD_TYPE)
    set (CMAKE_BUILD_TYPE RELEASE CACHE STRING
        "Choose the type of build, options are: PRODUCTION Debug Release."
        FORCE)
  endif (NOT CMAKE_BUILD_TYPE)
  
  STRING(COMPARE EQUAL ${CMAKE_BUILD_TYPE} "RelWithDebInfo" BUILD_RELEASE)
  STRING(COMPARE EQUAL ${CMAKE_BUILD_TYPE} "PRODUCTION" BUILD_PRODUCTION)
  STRING(COMPARE EQUAL ${CMAKE_BUILD_TYPE} "PROFILE" BUILD_PROFILE)
  if( BUILD_PRODUCTION )
    set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/exec )
  endif()
  if( BUILD_PROFILE )
    set(CMAKE_SKIP_RPATH "TRUE")
    if(NOT ENV{TAU_MAKEFILE}) 
      message("Must set TAU MAKEFILE environment variable to build in profiling mode")
      exit()
    endif()
  endif()

  if(BUILD_GSDCLOUD_ARW)
    set(GSDCLOUDOPT "-DRR_CLOUDANALYSIS" CACHE INTERNAL "" )
  else(BUILD_GSDCLOUD_ARW)
    set( GSDCLOUDOPT "" CACHE INTERNAL "" )
  endif(BUILD_GSDCLOUD_ARW)

  if(BUILD_GSDCLOUD_NMMB)
    set(GSDCLOUDOPT "-DNMMB_CLOUDANALYSIS" CACHE INTERNAL "" )
  else(BUILD_GSDCLOUD_NMMB)
    set( GSDCLOUDOPT "" CACHE INTERNAL "" )
  endif(BUILD_GSDCLOUD_NMMB)

  set(CMAKE_Fortran_FLAGS_RELEASE "")  
  if (CMAKE_CXX_COMPILER_ID MATCHES "GNU*")
    message("Setting GNU flags")
    setGNU()
  elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
    message("Setting Intel flags")
    setIntel()
  elseif(CMAKE_C_COMPILER MATCHES "pgc*")
    message("Setting PGI flags")
    setPGI()
  endif()


  find_package(MPI REQUIRED)
  message("MPI version is ${MPI_Fortran_VERSION}")
  message("MPI f90 version is ${MPI_Fortran_HAVE_F90_MODULE}")
  message("MPI f08 version is ${MPI_Fortran_HAVE_F08_MODULE}")

  add_definitions(${MPI_Fortran_COMPILE_FLAGS})
  include_directories(${MPI_Fortran_INCLUDE_DIRS} ${MPI_INCLUDE_PATH} "./" ${CMAKE_INCLUDE_OUTPUT_DIRECTORY})
  link_directories(${MPI_Fortran_LIBRARIES} ${ARCHIVE_OUTPUT_PATH} )
# if( (HOST-Discover) AND (NOT HOST-Generic))
  if( USE_BASELIBS )
    find_package(Baselibs REQUIRED)
  else()
    find_package( NetCDF COMPONENTS C Fortran REQUIRED)
  endif()
  if(( NOT HOST-WCOSS_D ) AND ( NOT HOST-WCOSS_C ) AND ( NOT HOST-Gaea ) ) 
    message(" trying to find lapack, ${host}")
    find_package( LAPACK )
  endif()
# build the WRF I/O libraries
  if(DEFINED ENV{GSIWRF_LIB})
    set(wrflib "$ENV{GSIWRF_LIB}" CACHE INTERNAL "WRFIO library" )
  elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/libsrc/wrflib)
    add_subdirectory(libsrc/wrflib)
  else()
    message("libsrc/wrflib not pulled from git, looking for WRF dependencies locally")
    message("libsrc/wrflib not pulled from git, looking for WRF dependencies locally")
    find_package( WRF )
  endif()

  # default installation
  get_filename_component (default_prefix ".." ABSOLUTE)
# set (CMAKE_INSTALL_PREFIX ${default_prefix} CACHE STRING "set prefix"
#       FORCE)


  # FFLAGS depend on the compiler
  get_filename_component (Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME)
  set(CFLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -O3  -Dfunder")
  set (CMAKE_Fortran_INC_FLAGS "-I ./ -I ${CORE_INCS} -I ${NETCDF_INCLUDE_DIRS} ")
  set (CFLAGS_N "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long'  -O3  -Dfunder")


  if(BUILD_CORELIBS )
    message("setting values for corelibs")
    set(BUILD_BACIO "ON" CACHE STRING "Build the BACIO library" )
    set(BUILD_BUFR "ON" CACHE STRING "Build the BUFR library" )
    set(BUILD_SFCIO "ON" CACHE STRING "Build the SFCIO library" )
    set(BUILD_SIGIO "ON" CACHE STRING "Build the SIGIO library" )
    set(BUILD_NEMSIO "ON" CACHE STRING "Build the NEMSIO library" )
    set(BUILD_SP "ON" CACHE STRING "Build the SP library" )
    set(BUILD_CRTM "ON" CACHE STRING "Build the CRTM library" )
    set(BUILD_W3EMC "ON" CACHE STRING "Build the EMC library" )
    set(BUILD_NCO "ON" CACHE STRING "Build the NCO library" )
  endif()
  find_package( BACIO )
  find_package( BUFR )
  find_package( SIGIO )
  find_package( NEMSIO )
  find_package( CRTM )
  find_package( SP )
  find_package( SFCIO )
  find_package( W3EMC )
  find_package( W3NCO )
  find_package( IP )

  if(BUILD_NCDIAG)
    set(NCDIAG_INCS "${PROJECT_BINARY_DIR}/src/ncdiag/include")
    add_subdirectory(src/ncdiag)
    set(NCDIAG_LIBRARIES ncdiag )
  endif(BUILD_NCDIAG)
  if(BUILD_FV3GFS_NCIO)
    set(FV3GFS_NCIO_INCS "${PROJECT_BINARY_DIR}/src/fv3gfs_ncio/include")
    add_subdirectory(src/fv3gfs_ncio)
    set(FV3GFS_NCIO_LIBRARIES fv3gfs_ncio )
  endif(BUILD_FV3GFS_NCIO)
  if(BUILD_NCIO_UTIL)
    add_subdirectory(util/netcdf_io)
  endif(BUILD_NCIO_UTIL)

  find_package( BACIO )
  find_package( BUFR )
  find_package( SIGIO )
  find_package( NEMSIO )
  find_package( CRTM )
  find_package( SP )
  find_package( SFCIO )
  find_package( W3EMC )
  find_package( W3NCO )
  find_package( IP )

  if(BUILD_GSDCLOUD_ARW)
    set(GSDCLOUD_DIR "${CMAKE_SOURCE_DIR}/src/GSD/gsdcloud")
    set(gsdcloud gsdcloud_arw)
    add_subdirectory(src/GSD/gsdcloud)
    set(GSDCLOUD_LIBRARY ${gsdcloud} )
  else(BUILD_GSDCLOUD_ARW)
    set(GSDCLOUD_LIBRARY "")
  endif(BUILD_GSDCLOUD_ARW)

  if(BUILD_GSDCLOUD_NMMB)
    set(gsdcloud gsdcloud_nmmb)
    set(GSDCLOUD_LIBRARY "")
  endif(BUILD_GSDCLOUD_NMMB)

  add_subdirectory(src/gsi)
  if(BUILD_ENKF)
    add_subdirectory(src/enkf)
  endif(BUILD_ENKF) 
  if(BUILD_UTIL)
    add_subdirectory(util/EnKF/gfs/src)
    add_subdirectory(util/Ozone_Monitor/nwprod/oznmon_shared.v2.0.0/sorc/oznmon_horiz.fd)
    add_subdirectory(util/Ozone_Monitor/nwprod/oznmon_shared.v2.0.0/sorc/oznmon_time.fd)
    add_subdirectory(util/Radiance_Monitor/nwprod/radmon_shared.v3.0.0/sorc/verf_radang.fd)
    add_subdirectory(util/Radiance_Monitor/nwprod/radmon_shared.v3.0.0/sorc/verf_radbcoef.fd)
    add_subdirectory(util/Radiance_Monitor/nwprod/radmon_shared.v3.0.0/sorc/verf_radbcor.fd)
    add_subdirectory(util/Radiance_Monitor/nwprod/radmon_shared.v3.0.0/sorc/verf_radtime.fd)
  endif(BUILD_UTIL) 
  find_package( NDATE )
  if( NOT NDATE )
     add_subdirectory(util/ndate)
  endif()
  if(BUILD_ENKF_PREPROCESS_ARW)
    add_subdirectory(util/EnKF/arw/src)
  endif(BUILD_ENKF_PREPROCESS_ARW)
  if(BUILD_UTIL_COM)
    add_subdirectory(util/Analysis_Utilities/read_diag)
    add_subdirectory(util/radar_process/radialwind)
    add_subdirectory(util/radar_process/reflectivity)
    add_subdirectory(util/bufr_tools)
  endif(BUILD_UTIL_COM)
  if(BUILD_COV_CALC)
    add_subdirectory(util/Correlated_Obs)
  endif (BUILD_COV_CALC)
  if(BUILD_UNIT_TESTING)
    set(CTEST_TEST_TIMEOUT 400 )
    find_package(GSICONTROL)
    include( CTest )
    add_subdirectory(unit-tests)
  endif(BUILD_UNIT_TESTING)
  if(BUILD_REG_TESTING)
    if(USE_BASELINE) 
      set(BASELINE_FLAG "1")
    else()      
      set(BASELINE_FLAG "0")
    endif(USE_BASELINE)
    if(USE_WRF)
      file(WRITE "${PROJECT_BINARY_DIR}/regression_var.out" "${CMAKE_SOURCE_DIR}/regression/regression_var.sh ${host} ${CMAKE_SOURCE_DIR}/.. ${PROJECT_BINARY_DIR} ${CMAKE_SOURCE_DIR} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${GSIEXEC} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${ENKFEXEC} ${GSICONTROL} ${ENKFCONTROL} ${BASELINE_FLAG} ")
      set( REG_TEST_NAMES "global_T62;global_T62_ozonly;global_4dvar_T62;global_4denvar_T126;global_fv3_4denvar_T126;;global_fv3_4denvar_C192;global_lanczos_T62;arw_netcdf;
          arw_binary;nmm_binary;nmm_netcdf;nmmb_nems_4denvar;hwrf_nmm_d2;hwrf_nmm_d3;rtma;global_enkf_T62;netcdf_fv3_regional;global_C96_fv3aero;global_C96_fv3aerorad")
    else()
      file(WRITE "${PROJECT_BINARY_DIR}/regression_var.out" "${CMAKE_SOURCE_DIR}/regression/regression_var.sh ${host} ${CMAKE_SOURCE_DIR}/.. ${PROJECT_BINARY_DIR} ${CMAKE_SOURCE_DIR} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${GSIEXEC} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${ENKFEXEC} ${GSICONTROL} ${ENKFCONTROL} ${BASELINE_FLAG} ")
      set( REG_TEST_NAMES "global_T62;global_T62_ozonly;global_4dvar_T62;global_lanczos_T62;global_nemsio_T62;global_C96_fv3aero;global_C96_fv3aerorad")
    endif()
    foreach( REG_TEST ${REG_TEST_NAMES} )
      add_test(NAME ${REG_TEST} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/regression COMMAND regression_driver.sh ${REG_TEST} ${PROJECT_BINARY_DIR})
    endforeach( REG_TEST )
    set_tests_properties( ${REG_TEST_NAMES} PROPERTIES TIMEOUT 86400 )
  endif()