!# This source file is part of code Pégase.3.0.1 (2019-02-21).
!# Copyright: Michel Fioc (Michel.Fioc@iap.fr), Sorbonne université, 
!# Institut d'astrophysique de Paris/CNRS, France.
!# 
!# Pégase.3.0.1 is governed by the CeCILL license under French law and abides 
!# by the rules of distribution of free software. You can use, modify and/or 
!# redistribute this software under the terms of the CeCILL license as circulated 
!# by CEA, CNRS and INRIA at "http://www.cecill.info". The text of this license
!# is also available in French and in English in directory "doc_dir/" of this
!# code.
!# 
!# As a counterpart to the access to the source code and to the rights to copy,
!# modify and redistribute it granted by the license, users are provided only
!# with a limited warranty, and the software's author, the holder of the
!# economic rights, and the successive licensors have only limited
!# liability. 
!# 
!# The fact that you are presently reading this means that you have had
!# knowledge of the CeCILL license and that you accept its terms.
!#====================================================================== 

module mod_scenario

  use mod_types
  use mod_analyze_statement, only : get_val, file_name, line_number, unit_log
  use mod_read_reserv_infall_param
  use mod_read_SF_param
  use mod_read_outflow_param
  use mod_read_dust_evol_param
  use mod_read_dust_transfer_param
  use mod_read_cloud_neb_param
  use mod_read_cosmo_param
  use mod_read_output_param
  use mod_read_other_param
  use mod_random, only : initialize_seed

  implicit none
  public

contains

!#======================================================================

  subroutine init_proc

    implicit none
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    call reset_all

  end subroutine init_proc

!#======================================================================

  subroutine reset_all

    implicit none
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    call reset_reserv_infall
    call reset_SF
    call reset_outflow
    call reset_dust_evol
    call reset_dust_transfer
    call reset_cloud_neb
    call reset_cosmo
    call reset_output
    call reset_others

  end subroutine reset_all

!#======================================================================

  subroutine end_proc(run)

    use mod_strings, only : same_case_equal

    implicit none
    logical, intent(out) :: run
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    call infall_check
    call SF_check
    call outflow_check
    call dust_evol_check
    call dust_transfer_check
    call cloud_neb_check
    call read_other_param_check

    if (new_statement .and. .not.check_only) then
       run = .true.
    else !# No new statement since the last `return`, so nothing to run.
       run = .false.
    endif

  end subroutine end_proc

!#======================================================================

  subroutine read_spectra_input_param(key, rhs, indices_string, &
       unknown_statement, statement_type)

    use mod_strings, only : same_case_equal

    implicit none
    character(len=*), intent(in) :: key
    character(len=*), intent(in) :: rhs
    character(len=*), intent(in) :: statement_type
    character(len=*), intent(inout) :: indices_string
    logical, intent(out) :: unknown_statement
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    new_statement = .true.
    unknown_statement = .false.

    if (same_case_equal(key, "echo")) then
       call read_echo

!#----------------------------------------------------------------------
    else if (same_case_equal(key, "reset_reserv_infall")) then
       call reset_reserv_infall

    else if (same_case_equal(key, "reserv_init_mass")) then
       call read_reserv_init_mass(rhs, indices_string)

    else if (same_case_equal(key, "reserv_Z")) then
       call read_reserv_Z(rhs, indices_string)
!#----------------------------------------------------------------------
    else if (same_case_equal(key, "infall_source")) then
       call read_infall_source(rhs, indices_string)

    else if (same_case_equal(key, "infall_begin_time")) then
       call read_infall_begin_time(rhs, indices_string)

    else if (same_case_equal(key, "infall_end_time")) then
       call read_infall_end_time(rhs, indices_string)

    else if (same_case_equal(key, "infall_type")) then
       call read_infall_type(rhs, indices_string)

    else if (same_case_equal(key, "infall_file")) then
       call read_infall_file(rhs, indices_string)

    else if (same_case_equal(key, "infall_inst_mass")) then
       call read_infall_inst_mass(rhs, indices_string)

    else if (same_case_equal(key, "infall_const_mass")) then
       call read_infall_const_mass(rhs, indices_string)

    else if (same_case_equal(key, "infall_expo_timescale")) then
       call read_infall_expo_timescale(rhs, indices_string)

    else if (same_case_equal(key, "infall_expo_mass")) then
       call read_infall_expo_mass(rhs, indices_string)

    else if (same_case_equal(key, "infall_reserv_timescale")) then
       call read_infall_reserv_timescale(rhs, indices_string)

    else if (same_case_equal(key, "infall_reserv_power")) then
       call read_infall_reserv_power(rhs, indices_string)
!#----------------------------------------------------------------------
    else if (same_case_equal(key, "reset_SF")) then
       call reset_SF

    else if (same_case_equal(key, "SF_begin_time")) then
       call read_SF_begin_time(rhs, indices_string)

    else if (same_case_equal(key, "SF_end_time")) then
       call read_SF_end_time(rhs, indices_string)

    else if (same_case_equal(key, "SF_type")) then
       call read_SF_type(rhs, indices_string)

    else if (same_case_equal(key, "SF_inst_mass")) then
       call read_SF_inst_mass(rhs, indices_string)

    else if (same_case_equal(key, "SF_const_mass")) then
       call read_SF_const_mass(rhs, indices_string)

    else if (same_case_equal(key, "SF_expo_timescale")) then
       call read_SF_expo_timescale(rhs, indices_string)

    else if (same_case_equal(key, "SF_expo_mass")) then
       call read_SF_expo_mass(rhs, indices_string)

    else if (same_case_equal(key, "SF_peaked_timescale")) then
       call read_SF_peaked_timescale(rhs, indices_string)

    else if (same_case_equal(key, "SF_peaked_mass")) then
       call read_SF_peaked_mass(rhs, indices_string)

    else if (same_case_equal(key, "SF_ISM_timescale")) then
       call read_SF_ISM_timescale(rhs, indices_string)

    else if (same_case_equal(key, "SF_ISM_power")) then
       call read_SF_ISM_power(rhs, indices_string)

    else if (same_case_equal(key, "SF_ISM_threshold")) then
       call read_SF_ISM_threshold(rhs, indices_string)

    else if (same_case_equal(key, "SF_infall_factor")) then
       call read_SF_infall_factor(rhs, indices_string)

    else if (same_case_equal(key, "SF_file")) then
       call read_SF_file(rhs, indices_string)

    else if (same_case_equal(key, "SF_stochastic")) then
       call read_SF_stochastic(rhs, indices_string)

    else if (same_case_equal(key, "SF_stoch_fluc")) then
       call read_SF_stoch_fluc(rhs, indices_string)

    else if (same_case_equal(key, "SF_stoch_timescale")) then
       call read_SF_stoch_timescale(rhs, indices_string)

    else if (same_case_equal(key, "SF_Z_type")) then
       call read_SF_Z_type(rhs, indices_string)

    else if (same_case_equal(key, "SF_Z_const_val")) then
       call read_SF_Z_const_val(rhs, indices_string)

    else if (same_case_equal(key, "SF_Z_file")) then
       call read_SF_Z_file(rhs, indices_string)

    else if (same_case_equal(key, "SF_inert_frac")) then
       call read_SF_inert_frac(rhs, indices_string)
!#----------------------------------------------------------------------
    else if (same_case_equal(key, "reset_outflow")) then
       call reset_outflow

    else if (same_case_equal(key, "outflow_begin_time")) then
       call read_outflow_begin_time(rhs, indices_string)

    else if (same_case_equal(key, "outflow_end_time")) then
       call read_outflow_end_time(rhs, indices_string)

    else if (same_case_equal(key, "outflow_type")) then
       call read_outflow_type(rhs, indices_string)

    else if (same_case_equal(key, "outflow_inst_mass")) then
       call read_outflow_inst_mass(rhs, indices_string)

    else if (same_case_equal(key, "outflow_const_mass")) then
       call read_outflow_const_mass(rhs, indices_string)

    else if (same_case_equal(key, "outflow_SF_factor")) then
       call read_outflow_SF_factor(rhs, indices_string)

    else if (same_case_equal(key, "outflow_SN_mass")) then
       call read_outflow_SN_mass(rhs, indices_string)

    else if (same_case_equal(key, "outflow_SN_power")) then
       call read_outflow_SN_power(rhs, indices_string)

    else if (same_case_equal(key, "outflow_CCSN_mass")) then
       call read_outflow_CCSN_mass(rhs, indices_string)

    else if (same_case_equal(key, "outflow_CCSN_power")) then
       call read_outflow_CCSN_power(rhs, indices_string)

    else if (same_case_equal(key, "outflow_SNIa_mass")) then
       call read_outflow_SNIa_mass(rhs, indices_string)

    else if (same_case_equal(key, "outflow_SNIa_power")) then
       call read_outflow_SNIa_power(rhs, indices_string)

    else if (same_case_equal(key, "outflow_ejec_threshold")) then
       call read_outflow_ejec_threshold(rhs, indices_string)

    else if (same_case_equal(key, "outflow_ejec_factor")) then
       call read_outflow_ejec_factor(rhs, indices_string)

    else if (same_case_equal(key, "outflow_file")) then
       call read_outflow_file(rhs, indices_string)
!#----------------------------------------------------------------------
    else if (same_case_equal(key, "reset_dust_evol")) then
       call reset_dust_evol

    else if (same_case_equal(key, "dust_evolution")) then
       call read_dust_evolution(rhs)

    else if (same_case_equal(key, "O_sil_ratio")) then
       call read_O_sil_ratio(rhs)

    else if (same_case_equal(key, "ISM_carb_deplet")) then
       call read_ISM_carb_deplet(rhs)

    else if (same_case_equal(key, "ISM_sil_deplet")) then
       call read_ISM_sil_deplet(rhs)

    else if (same_case_equal(key, "CCSN_carb_deplet")) then
       call read_CCSN_carb_deplet(rhs)

    else if (same_case_equal(key, "SNIa_carb_deplet")) then
       call read_SNIa_carb_deplet(rhs)

    else if (same_case_equal(key, "HMW_carb_deplet")) then
       call read_HMW_carb_deplet(rhs)

    else if (same_case_equal(key, "LMW_carb_deplet")) then
       call read_LMW_carb_deplet(rhs)

    else if (same_case_equal(key, "CCSN_sil_deplet")) then
       call read_CCSN_sil_deplet(rhs)

    else if (same_case_equal(key, "SNIa_sil_deplet")) then
       call read_SNIa_sil_deplet(rhs)

    else if (same_case_equal(key, "HMW_sil_deplet")) then
       call read_HMW_sil_deplet(rhs)

    else if (same_case_equal(key, "LMW_sil_deplet")) then
       call read_LMW_sil_deplet(rhs)

    else if (same_case_equal(key, "SN_swept_mass")) then
       call read_SN_swept_mass(rhs)

    else if (same_case_equal(key, "carb_accr_timescale")) then
       call read_carb_accr_timescale(rhs)

    else if (same_case_equal(key, "sil_accr_timescale")) then
       call read_sil_accr_timescale(rhs)

!#----------------------------------------------------------------------
    else if (same_case_equal(key, "reset_dust_transfer")) then
       call reset_dust_transfer

    else if (same_case_equal(key, "extinction")) then
       call read_extinction(rhs)

    else if (same_case_equal(key, "extinction_SFC")) then
       call read_extinction_SFC(rhs)

    else if (same_case_equal(key, "extinction_DISM")) then
       call read_extinction_DISM(rhs)

    else if (same_case_equal(key, "grains_file")) then
       call read_grains_file(rhs)

    else if (same_case_equal(key, "grains_file_SFC")) then
       call read_grains_file_SFC(rhs)

    else if (same_case_equal(key, "grains_file_DISM")) then
       call read_grains_file_DISM(rhs)

    else if (same_case_equal(key, "carb_sublim_temp")) then
       call read_carb_sublim_temp(rhs)

    else if (same_case_equal(key, "carb_sublim_temp_SFC")) then
       call read_carb_sublim_temp_SFC(rhs)

    else if (same_case_equal(key, "carb_sublim_temp_DISM")) then
       call read_carb_sublim_temp_DISM(rhs)

    else if (same_case_equal(key, "sil_sublim_temp")) then
       call read_sil_sublim_temp(rhs)

    else if (same_case_equal(key, "sil_sublim_temp_SFC")) then
       call read_sil_sublim_temp_SFC(rhs)

    else if (same_case_equal(key, "sil_sublim_temp_DISM")) then
       call read_sil_sublim_temp_DISM(rhs)

    else if (same_case_equal(key, "bulge_tot_ratio")) then
       call read_bulge_tot_ratio(rhs)

    else if (same_case_equal(key, "M_sys_spiral")) then
       call read_M_sys_spiral(rhs)

    else if (same_case_equal(key, "expo_radius")) then
       call read_expo_radius(rhs)

    else if (same_case_equal(key, "M_sys_spher")) then
       call read_M_sys_spher(rhs)

    else if (same_case_equal(key, "core_radius")) then
       call read_core_radius(rhs)

    else if (same_case_equal(key, "geometry")) then
       call read_geometry(rhs)

    else if (same_case_equal(key, "inclin_averaged")) then
       call read_inclin_averaged(rhs)

    else if (same_case_equal(key, "inclination")) then
       call read_inclination(rhs)

    else if (same_case_equal(key, "slab_factor")) then
       call read_slab_factor(rhs)

    else if (same_case_equal(key, "dust_emission")) then
       call read_dust_emission(rhs)

    else if (same_case_equal(key, "dust_emission_SFC")) then
       call read_dust_emission_SFC(rhs)

    else if (same_case_equal(key, "dust_emission_DISM")) then
       call read_dust_emission_DISM(rhs)

    else if (same_case_equal(key, "self_abs_power")) then
       call read_self_abs_power(rhs)

    else if (same_case_equal(key, "self_abs_power_SFC")) then
       call read_self_abs_power_SFC(rhs)

    else if (same_case_equal(key, "self_abs_power_DISM")) then
       call read_self_abs_power_DISM(rhs)

    else if (same_case_equal(key, "stoch_heating")) then
       call read_stoch_heating(rhs)

    else if (same_case_equal(key, "stoch_heating_SFC")) then
       call read_stoch_heating_SFC(rhs)

    else if (same_case_equal(key, "stoch_heating_DISM")) then
       call read_stoch_heating_DISM(rhs)

!#----------------------------------------------------------------------
    else if (same_case_equal(key, "reset_others")) then
       call  reset_others

    else if (same_case_equal(key, "SSPs_set")) then
       call read_SSPs_set_name(rhs)

    else if (same_case_equal(key, "ISM_init_Z")) then
       call read_ISM_init_Z(rhs)

    else if (same_case_equal(key, "close_bin_frac")) then
       call read_close_bin_frac(rhs)

    else if (same_case_equal(key, "spectra_output")) then
       call read_spectra_output(rhs)

    else if (same_case_equal(key, "RF_output")) then
       call read_RF_output(rhs)

    else if (same_case_equal(key, "sublim_output")) then
       call read_sublim_output(rhs)

    else if (same_case_equal(key, "grain_temp_output")) then
       call read_grain_temp_output(rhs)

    else if (same_case_equal(key, "grain_temp_file")) then
       call read_grain_temp_file(rhs)

    else if (same_case_equal(key, "grain_SED_output")) then
       call read_grain_SED_output(rhs)

    else if (same_case_equal(key, "grain_SED_file")) then
       call read_grain_SED_file(rhs)

    else if (same_case_equal(key, "grain_output_min_age")) then
       call read_grain_output_min_age(rhs)

    else if (same_case_equal(key, "grain_output_max_age")) then
       call read_grain_output_max_age(rhs)

    else if (same_case_equal(key, "grain_output_SFC")) then
       call read_grain_output_SFC(rhs)

    else if (same_case_equal(key, "grain_output_DISM")) then
       call read_grain_output_DISM(rhs)

    else if (same_case_equal(key, "grain_output_min_size")) then
       call read_grain_output_min_size(rhs)

    else if (same_case_equal(key, "grain_output_max_size")) then
       call read_grain_output_max_size(rhs)

    else if (same_case_equal(key, "ages_file")) then
       call read_ages_file(rhs)

    else if (same_case_equal(key, "spectra_file")) then
       call read_spectra_file(rhs)

    else if (same_case_equal(key, "prefix")) then
       call read_prefix(rhs)

    else if (same_case_equal(key, "stamp_time")) then
       call read_stamp_time(rhs)

    else if (same_case_equal(key, "overwrite")) then
       call read_overwrite(rhs)

    else if (same_case_equal(key, "check_only")) then
       call read_check_only(rhs)

    else if (same_case_equal(key, "erase_text")) then
       call erase_text

    else if (same_case_equal(key, "add_text")) then
       call read_add_text(rhs, statement_type)

    else if (same_case_equal(key, "verbosity")) then
       call read_verbosity(rhs)

    else if (same_case_equal(key, "seed")) then
       call read_seed(rhs, indices_string)

    else if (same_case_equal(key, "initialize_seed")) then
       call initialize_seed
!#----------------------------------------------------------------------
    else if (same_case_equal(key, "reset_cloud_neb")) then
       call  reset_cloud_neb

    else if (same_case_equal(key, "nebular_emission")) then
       call read_nebular_emission(rhs)

    else if (same_case_equal(key, "nebular_emission_SFC")) then
       call read_nebular_emission_SFC(rhs)

    else if (same_case_equal(key, "nebular_emission_DISM")) then
       call read_nebular_emission_DISM(rhs)

    else if (same_case_equal(key, "neb_emis_type")) then
       call read_neb_emis_type(rhs)

    else if (same_case_equal(key, "neb_emis_type_SFC")) then
       call read_neb_emis_type_SFC(rhs)

    else if (same_case_equal(key, "neb_emis_type_DISM")) then
       call read_neb_emis_type_DISM(rhs)

    else if (same_case_equal(key, "neb_emis_const_frac")) then
       call read_neb_emis_const_frac(rhs)

    else if (same_case_equal(key, "neb_emis_const_frac_SFC")) then
       call read_neb_emis_const_frac_SFC(rhs)

    else if (same_case_equal(key, "neb_emis_const_frac_DISM")) then
       call read_neb_emis_const_frac_DISM(rhs)

    else if (same_case_equal(key, "l10_mean_U_DISM")) then
       call read_l10_mean_U_DISM(rhs)

    else if (same_case_equal(key, "cluster_stel_mass")) then
       call read_cluster_stel_mass(rhs)

    else if (same_case_equal(key, "cloud_init_frac")) then
       call read_cloud_init_frac(rhs)

    else if (same_case_equal(key, "cloud_power")) then
       call read_cloud_power(rhs)

    else if (same_case_equal(key, "cloud_duration")) then
       call read_cloud_duration(rhs)
!#----------------------------------------------------------------------
    else if (same_case_equal(key, "reset_cosmo")) then
       call  reset_cosmo

    else if (same_case_equal(key, "Omega_m")) then
       call  read_Omega_m(rhs)

    else if (same_case_equal(key, "H_0")) then
       call  read_H_0(rhs)

    else if (same_case_equal(key, "form_redshift")) then
       call  read_form_redshift(rhs)

    else if (same_case_equal(key, "CBR")) then
       call  read_CBR(rhs)

!#----------------------------------------------------------------------
    else
       unknown_statement = .true.
    end if

  end subroutine read_spectra_input_param

!#======================================================================

  subroutine read_check_only(rhs)

    implicit none
    character(len=*), intent(in) :: rhs
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    call get_val(check_only, rhs)

  end subroutine read_check_only

!#======================================================================

  subroutine read_echo

    use mod_write_scenario_param, only : write_scenario_param
    implicit none
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    write(*, "(a)") repeat("=",80)
    write(*, "(a, i0, a)") "File """ // trim(file_name) // """, line ", &
         line_number, ":"
    write(unit_log, "(/a, i0, a)") "File """ // trim(file_name) // """, line ", &
         line_number, ":"
    call write_scenario_param(unit = -1, &
         line_prefix = "")
    call write_scenario_param(unit = unit_log, &
         line_prefix = "")
    write(*, "(a)") repeat("=",80)

  end subroutine read_echo

end module mod_scenario
