# ============================================================================
# Tell cmake about subdirectories to look into
# ============================================================================
add_subdirectory(SFMT-src-1.4)

# ============================================================================
# Add targets add their dependencies
# ============================================================================
set(libaevol_sources
  ae_types.h
  AeTime.cpp
  AeTime.h
  aevol.h
  macros.h

  aevol_flavor.h
  aevol_version.h

  alignments/Alignment.h
  alignments/AlignmentParams.cpp
  alignments/AlignmentParams.h
  alignments/FunctionShape.h
  alignments/RecombAlignmentSearcher.cpp
  alignments/RecombAlignmentSearcher.h
  alignments/ScoreFunction.cpp
  alignments/ScoreFunction.h
  biochemistry/AnnotatedChromosome.h
  biochemistry/AnnotatedChromosome.cpp
  biochemistry/Codon.cpp
  biochemistry/Codon.h
  biochemistry/Dna.cpp
  biochemistry/Dna.h
  biochemistry/DnaFactory.cpp
  biochemistry/DnaFactory.h
  biochemistry/fuzzytypes.h
  biochemistry/GenomeLimits.h
  biochemistry/mutations/MutationEvent.cpp
  biochemistry/mutations/MutationEvent.h
  biochemistry/mutations/MutationMetrics.h
  biochemistry/mutations/MutationParams.cpp
  biochemistry/mutations/MutationParams.h
  biochemistry/mutations/mutators/DnaMutator.cpp
  biochemistry/mutations/mutators/DnaMutator.h
  biochemistry/mutations/mutators/IndividualMutator.h
  biochemistry/Promoter.cpp
  biochemistry/Promoter.h
  biochemistry/PromoterList.cpp
  biochemistry/PromoterList.h
  biochemistry/Protein.cpp
  biochemistry/Protein.h
  biochemistry/ProteinList.cpp
  biochemistry/ProteinList.h
  biochemistry/Rna.cpp
  biochemistry/Rna.h
  biochemistry/RnaList.cpp
  biochemistry/RnaList.h
  biochemistry/Strand.h
  biochemistry/TranscriptionTerminationSequence.cpp
  biochemistry/TranscriptionTerminationSequence.h
  biochemistry/TranslationInitiationSequence.cpp
  biochemistry/TranslationInitiationSequence.h
  Chrsm.h
  ExpSetup.cpp
  ExpSetup.h
  io/checkpointing/CheckpointData.h
  io/checkpointing/CheckpointHandler.cpp
  io/checkpointing/CheckpointHandler.h
  io/checkpointing/mxifstream.cpp
  io/checkpointing/mxifstream.h
  io/checkpointing/mxofstream.cpp
  io/checkpointing/mxofstream.h
  io/fasta/fasta.cpp
  io/fasta/fasta.h
  io/fasta/FastaModifiers.cpp
  io/fasta/FastaModifiers.h
  io/fasta/FastaReader.cpp
  io/fasta/FastaReader.h
  io/fasta/FastaWriter.cpp
  io/fasta/FastaWriter.h
  io/indiv_idxs_map.h
  io/last_gener.h
  io/parameters/ParamReader.cpp
  io/parameters/ParamReader.h
  io/parameters/ParamValues.cpp
  io/parameters/ParamValues.h
  io/stats/AbstractStatsHandler.h
  io/stats/AbstractSingleIndividualStatsHandler.h
  io/stats/SingleIndividualStatsHandler.h
  io/stats/MultiIndividualDataCollector.h
  io/stats/MeanStatsHandler.h
  io/stats/StatsDataConcepts.h
  io/stats/ChromosomeStatsData.h
  io/stats/DiploidChromosomeStatsData.h
  io/stats/DefaultGlobalStatsData.h
  io/stats/FitnessStatsData.h
  io/stats/MutationsStatsData.h
  io/stats/DiploidMutationsStatsData.h
  io/stats/NonCodingStatsData.h
  io/stats/DiploidNonCodingStatsData.h
  io/stats/StatsOrchestrator.cpp
  io/stats/StatsOrchestrator.h
  io/tree/mutation_report/Deletion.cpp
  io/tree/mutation_report/Deletion.h
  io/tree/mutation_report/Duplication.cpp
  io/tree/mutation_report/Duplication.h
  io/tree/mutation_report/HorizontalTransfer.h
  io/tree/mutation_report/InsertionHT.cpp
  io/tree/mutation_report/InsertionHT.h
  io/tree/mutation_report/Inversion.cpp
  io/tree/mutation_report/Inversion.h
  io/tree/mutation_report/LocalMutation.h
  io/tree/mutation_report/MutationReport.cpp
  io/tree/mutation_report/MutationReport.h
  io/tree/mutation_report/PointMutation.cpp
  io/tree/mutation_report/PointMutation.h
  io/tree/mutation_report/Rearrangement.h
  io/tree/mutation_report/ReplacementHT.cpp
  io/tree/mutation_report/ReplacementHT.h
  io/tree/mutation_report/SmallDeletion.cpp
  io/tree/mutation_report/SmallDeletion.h
  io/tree/mutation_report/SmallInsertion.cpp
  io/tree/mutation_report/SmallInsertion.h
  io/tree/mutation_report/Translocation.cpp
  io/tree/mutation_report/Translocation.h
  io/tree/PhylogeneticTreeHandler.cpp
  io/tree/PhylogeneticTreeHandler.h
  io/tree/Tree.cpp
  io/tree/Tree.h
  io/ui/UserInterfaceOutput.cpp
  io/ui/UserInterfaceOutput.h
  io/tree/DnaReplicationReport.cpp
  io/tree/DnaReplicationReport.h
  io/tree/ReplicationReport.cpp
  io/tree/ReplicationReport.h
  orchestration/CheckpointExplorer.cpp
  orchestration/CheckpointExplorer.h
  orchestration/EvolutionRunner.cpp
  orchestration/EvolutionRunner.h
  orchestration/ExperimentCreator.cpp
  orchestration/ExperimentCreator.h
  orchestration/IndividualAnalyser.cpp
  orchestration/IndividualAnalyser.h
  phenotype/fuzzy/AbstractFuzzy.h
  phenotype/fuzzy/FuzzyFactory.cpp
  phenotype/fuzzy/FuzzyFactory.h
  phenotype/fuzzy/FuzzyFlavor.h
  phenotype/fuzzy/Discrete_Double_Fuzzy.cpp
  phenotype/fuzzy/Discrete_Double_Fuzzy.h
  phenotype/fuzzy/FuzzyHelpers.cpp
  phenotype/fuzzy/FuzzyHelpers.h
  phenotype/fuzzy/Vector_Fuzzy.h
  phenotype/fuzzy/Vector_Fuzzy.cpp
  phenotype/Gaussian.h
  phenotype/PhenotypicTarget.cpp
  phenotype/PhenotypicTarget.h
  phenotype/Point.cpp
  phenotype/Point.h

  population/Grid.cpp
  population/Grid.h
  population/GridCell.cpp
  population/GridCell.h
  population/Individual.cpp
  population/Individual.h
  population/Population.cpp
  population/Population.h
  population/Selection.cpp
  population/Selection.h
  population/SelectionParams.cpp
  population/SelectionParams.h

        rng/JumpingMT.cpp
  rng/JumpingMT.h
  rng/JumpPoly.h
  #rng/MersenneTwister.cpp
  #rng/MersenneTwister.h
  utils/utils.cpp
  utils/utils.h
  utils/utility.h
  )

# Eukaryote/Prokaryote specifics
set(libaevol_prokaryote_sources
    biochemistry/mutations/mutators/ProkaryoteIndividualMutator.cpp
    biochemistry/mutations/mutators/ProkaryoteIndividualMutator.h
)
set(libaevol_eukaryote_sources
    biochemistry/mutations/mutators/EukaryoteIndividualMutator.cpp
    biochemistry/mutations/mutators/EukaryoteIndividualMutator.h
)

# Aevol_4b specifics
set(libaevol_4b_specific_sources
    aevol_4b/biochemistry/AminoAcid.h
    aevol_4b/biochemistry/AA_2_MWH_Value_Mapping.cpp
    aevol_4b/biochemistry/AA_2_MWH_Value_Mapping.h)

# Combine 2b/4b with eukaryote/prokaryote
set(libaevol_2b_sources           ${libaevol_sources} ${libaevol_prokaryote_sources})
set(libaevol_eukaryote_2b_sources ${libaevol_sources} ${libaevol_eukaryote_sources})
set(libaevol_4b_sources           ${libaevol_sources} ${libaevol_prokaryote_sources}  ${libaevol_4b_specific_sources})
set(libaevol_eukaryote_4b_sources ${libaevol_sources} ${libaevol_eukaryote_sources}   ${libaevol_4b_specific_sources})

foreach (AEVOL_FLAVOR IN LISTS AEVOL_FLAVORS)
  set(lib${AEVOL_FLAVOR}_sources ${lib${AEVOL_FLAVOR}_sources} ${AEVOL_FLAVOR}_flavor.cpp)
  configure_file(aevol_flavor.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/${AEVOL_FLAVOR}_flavor.cpp)
endforeach ()

# ============================================================================
# Generate version file aevol_version.cpp
# ============================================================================
configure_file(aevol_version.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/aevol_version.cpp.in @ONLY)

# Configure further at build time
add_custom_target(generate-aevol-version
  BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/aevol_version.cpp
  COMMAND ${CMAKE_COMMAND}
      -DAEVOL_SOURCE_DIR=${aevol_SOURCE_DIR}
      -P ${aevol_SOURCE_DIR}/CMakeScripts/aevol_version.cmake
  COMMENT "Generating ${CMAKE_CURRENT_BINARY_DIR}/aevol_version.cpp"
)
add_library(libaevol-version ${CMAKE_CURRENT_BINARY_DIR}/aevol_version.cpp)
add_dependencies(libaevol-version generate-aevol-version)
set_target_properties(libaevol-version PROPERTIES PREFIX "")

# ============================================================================
# Add libaevol for each flavor of aevol
# ============================================================================
foreach (AEVOL_FLAVOR IN LISTS AEVOL_FLAVORS)
  add_library(lib${AEVOL_FLAVOR} ${lib${AEVOL_FLAVOR}_sources})
  set_target_properties(lib${AEVOL_FLAVOR} PROPERTIES PREFIX "")
  target_link_libraries(lib${AEVOL_FLAVOR} PUBLIC libaevol-version)
  target_link_libraries(lib${AEVOL_FLAVOR} PRIVATE OpenMP::OpenMP_CXX)
  target_link_libraries(lib${AEVOL_FLAVOR} PRIVATE nlohmann_json::nlohmann_json)
  add_dependencies(${AEVOL_FLAVOR} lib${AEVOL_FLAVOR})
endforeach(AEVOL_FLAVOR)

# Additional flavor-specific settings
if (TARGET libaevol_2b)
  target_compile_definitions(libaevol_2b PUBLIC BASE_2)
endif ()
if (TARGET libaevol_4b)
  target_compile_definitions(libaevol_4b PUBLIC BASE_4)
endif ()
if (TARGET libaevol_eukaryote_2b)
  target_compile_definitions(libaevol_eukaryote_2b PUBLIC BASE_2)
  target_compile_definitions(libaevol_eukaryote_2b PUBLIC LINEAR_CHRSM DIPLOID SEX)
endif ()
if (TARGET libaevol_eukaryote_4b)
  target_compile_definitions(libaevol_eukaryote_4b PUBLIC BASE_4)
  target_compile_definitions(libaevol_eukaryote_4b PUBLIC LINEAR_CHRSM DIPLOID SEX)
endif ()

# ============================================================================
# Include directories
# ============================================================================
foreach (AEVOL_FLAVOR IN LISTS AEVOL_FLAVORS)
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC ".")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./alignments")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./biochemistry")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./biochemistry/mutations")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./gui")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./io")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "io/tree/mutation_report")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./phenotype")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./population")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./rng")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./SFMT-src-1.4")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "legacy/stats")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./utils")
  target_include_directories(lib${AEVOL_FLAVOR} PUBLIC "./world")
endforeach(AEVOL_FLAVOR)


# ============================================================================
# Use GSL and zlib
# ============================================================================
foreach (AEVOL_FLAVOR IN LISTS AEVOL_FLAVORS)
  target_link_libraries(lib${AEVOL_FLAVOR} PRIVATE ZLIB::ZLIB)
  target_link_libraries(lib${AEVOL_FLAVOR} PUBLIC sfmt)
endforeach(AEVOL_FLAVOR)


# ============================================================================
# Make STDC MACROS available (for fixed width integers)
# ============================================================================
foreach (AEVOL_FLAVOR IN LISTS AEVOL_FLAVORS)
  target_compile_definitions(lib${AEVOL_FLAVOR}
    PUBLIC __STDC_FORMAT_MACROS
    PUBLIC __STDC_CONSTANT_MACROS)
endforeach(AEVOL_FLAVOR)
