using YAML

# Define a mutable struct for parameters, loaded from YAML
mutable struct Params
    L::Float64  # Length of cylinder [m]
    R_solid::Float64  # Inner radius of pipe [m]
    R_pipe::Float64  # Inner radius of pipe [m]
    v::Float64  # Flow velocity [m/s]

    rho_oil::Float64  # kg/m³
    cp_oil::Float64  # J/(kg·K)
    k_oil::Float64
    nu_oil::Float64
    # Solid
    rho_s::Float64
    cp_s::Float64
    k_s::Float64
    # HTC
    h::Union{Float64, Nothing}  # if nothing -> compute once from correlation
    # Numerics
    Nr_solid::Int64
    Nz_solid::Int64
    Nz_fluid::Int64
    grad::Float64
    bump::Float64
    cfl_target::Float64
    alpha_f::Float64               # axial diffusion [m^2/s]
    T_cold::Float64  # K
    T_hot::Float64  # K
    T_initial::Float64  # [K] initial temperature
    tau_heater::Int
    dT_max::Float64
    dT_min::Float64
    Kp::Float64
    # Sequence of phases: (:charge, duration), (:discharge, duration), (:steady, duration)
    phases::Vector{Tuple{Symbol, Float64}}
    t_end::Float64  # Computed end time [s]
    save_every::Float64

    # Constructor to load from YAML file
    function Params(config_file::String)
        function video_len(minutes::Float64, t_end::Float64)
            fr = 48.0
            videon_kesto = 60.0*minutes
            N_kuvat = videon_kesto*fr
            kuvaväli = t_end/N_kuvat
            return kuvaväli
        end

        config = YAML.load_file(config_file)

        # Geometry
        L        = get(config["geometry"], "L", 50.0)
        R_pipe   = get(config["geometry"], "R_pipe", 0.074)
        R_solid   = get(config["geometry"], "R_solid", 0.5)
        v        = get(config["fluid"], "v", 1.0)
        rho_oil  = get(config["fluid"], "rho", 860.0)
        cp_oil   = get(config["fluid"], "cp", 2000.0)
        k_oil   = get(config["fluid"], "k", 0.12)
        nu_oil   = get(config["fluid"], "nu", 5.0e-6)
        rho_s  = get(config["solid"], "rho", 7800.0)
        cp_s   = get(config["solid"], "cp", 500.0)
        k_s   = get(config["solid"], "k", 15.0)
        h = get(config["htc"], "h", nothing)
        Nr_solid = get(config["mesh"], "Nr_solid", 50)
        Nz_solid = get(config["mesh"], "Nz_solid", 100)
        Nz_fluid = Nz_solid
        grad = get(config["mesh"], "grad", 1.5)
        bump = get(config["mesh"], "bump", 1.0)
        cfl_target = get(config["numerics"], "cfl_target", 0.5)
        alpha_f = get(config["numerics"], "alpha_f", 0.0)
        T_cold = get(config["operating_conditions"], "T_cold", 293.15)
        T_hot = get(config["operating_conditions"], "T_hot", 698.15)
        T_initial = get(config["operating_conditions"], "T_initial", 293.15)
        tau_heater = get(config["controller_parameters"], "tau_heater", 1800.0)
        dT_max = get(config["controller_parameters"], "dT_max", 1.0e+6)
        dT_min = get(config["controller_parameters"], "dT_min", 1.0e+6)
        Kp = get(config["controller_parameters"], "Kp", 0.0)
        # Phases: Parse sequence from config, e.g., phases: [ {type: "charge", duration: 3600}, ... ]
        phases = Tuple{Symbol, Float64}[]
        for phase in get(config["controller_parameters"], "phases", [])
            push!(phases, (Symbol(phase["type"]), 3600*phase["duration"]))
        end
        t_end = sum(d for (_, d) in phases)
        save_every = video_len(get(config["animation"], "video_duration", 1), t_end)

        new(L, R_solid, R_pipe, v,  rho_oil, cp_oil, k_oil, nu_oil, rho_s, cp_s, k_s, h, Nr_solid, Nz_solid, Nz_fluid, grad, bump, cfl_target, alpha_f, T_cold, T_hot, T_initial, tau_heater, dT_max, dT_min, Kp, phases, t_end, save_every)
    end
end