"""
    DEOptions

Mutable container of resolved common solver options, stored on a running
integrator as `integrator.opts`.

# Fields

- `abstol`, `reltol`, `internalnorm`, and `internalopnorm` control error tests.
- `dtmin`, `dtmax`, `failfactor`, `force_dtmin`, `advance_to_tstop`, and
  `stop_at_next_tstop` control time-step selection.
- `tstops`, `saveat`, `d_discontinuities`, and their corresponding caches manage
  scheduled times.
- `save_everystep`, `save_idxs`, `dense`, `save_on`, `save_start`, `save_end`,
  `save_noise`, `save_discretes`, and `save_end_user` control output.
- `callback`, `isoutofdomain`, and `unstable_check` configure step checks.
- `maxiters`, `verbose`, and the `progress` fields configure reporting.

# Rules

Solver implementations may read or update these fields while stepping, but must
preserve the queue invariants maintained by the initialization and time-stop
hooks. Application code should configure these options through `solve` or
`init`, rather than constructing `DEOptions` directly.

!!! warning "Developer API"
    `DEOptions` is a versioned interface for solver implementations. It is not a
    user-facing solver configuration type.
"""
mutable struct DEOptions{
        absType, relType, QT, tType, F1, F2, F3, F4, F5, F6,
        F7, tstopsType, discType, ECType, SType, MI, tcache, savecache,
        disccache, verbType, DType, StageLimiter, StepLimiter,
    }
    maxiters::MI
    save_everystep::Bool
    adaptive::Bool
    abstol::absType
    reltol::relType
    failfactor::QT
    dtmax::tType
    dtmin::tType
    internalnorm::F1
    internalopnorm::F2
    save_idxs::SType
    tstops::tstopsType
    saveat::tstopsType
    d_discontinuities::discType
    tstops_cache::tcache
    saveat_cache::savecache
    d_discontinuities_cache::disccache
    userdata::ECType
    progress::Bool
    progress_steps::Int
    progress_name::String
    progress_message::F6
    progress_id::Symbol
    timeseries_errors::Bool
    dense_errors::Bool
    delta::DType
    stage_limiter!::StageLimiter
    step_limiter!::StepLimiter
    dense::Bool
    save_on::Bool
    save_start::Bool
    save_end::Bool
    save_noise::Bool
    save_discretes::Bool
    save_end_user::F3
    callback::F4
    isoutofdomain::F5
    unstable_check::F7
    verbose::verbType
    calck::Bool
    force_dtmin::Bool
    advance_to_tstop::Bool
    stop_at_next_tstop::Bool
end

# Legacy constructor for backwards compatibility with packages (e.g. DelayDiffEq)
# that construct DEOptions without the delta, save_noise, stage_limiter!, and step_limiter!
# fields and without the DType/StageLimiter/StepLimiter type parameters. Accepts 21 type
# params and 46 positional args.
function DEOptions{
        absType, relType, QT, tType, Controller, F1, F2, F3, F4, F5, F6,
        F7, tstopsType, discType, ECType, SType, MI, tcache, savecache,
        disccache, verbType,
    }(
        maxiters, save_everystep, adaptive, abstol, reltol,
        gamma, qmax, qmin, qsteady_max, qsteady_min, qoldinit,
        failfactor, dtmax, dtmin, controller, internalnorm, internalopnorm,
        save_idxs, tstops, saveat, d_discontinuities,
        tstops_cache, saveat_cache, d_discontinuities_cache, userdata,
        progress, progress_steps, progress_name, progress_message, progress_id,
        timeseries_errors, dense_errors,
        dense, save_on, save_start, save_end, save_discretes,
        save_end_user, callback, isoutofdomain, unstable_check,
        verbose, calck, force_dtmin, advance_to_tstop, stop_at_next_tstop,
    ) where {
        absType, relType, QT, tType, Controller, F1, F2, F3, F4, F5, F6,
        F7, tstopsType, discType, ECType, SType, MI, tcache, savecache,
        disccache, verbType,
    }
    return DEOptions{
        absType, relType, QT, tType, Controller, F1, F2, F3, F4, F5, F6,
        F7, tstopsType, discType, ECType, SType, MI, tcache, savecache,
        disccache, verbType, typeof(nothing), typeof(trivial_limiter!),
        typeof(trivial_limiter!),
    }(
        maxiters, save_everystep, adaptive, abstol, reltol,
        gamma, qmax, qmin, qsteady_max, qsteady_min, qoldinit,
        failfactor, dtmax, dtmin, controller, internalnorm, internalopnorm,
        save_idxs, tstops, saveat, d_discontinuities,
        tstops_cache, saveat_cache, d_discontinuities_cache, userdata,
        progress, progress_steps, progress_name, progress_message, progress_id,
        timeseries_errors, dense_errors,
        nothing, trivial_limiter!, trivial_limiter!, dense, save_on, save_start, save_end,
        false, save_discretes, save_end_user, callback, isoutofdomain, unstable_check,
        verbose, calck, force_dtmin, advance_to_tstop, stop_at_next_tstop,
    )
end

"""
    ODEIntegrator

Fundamental `struct` allowing interactively stepping through the numerical solving of a differential equation.
The full documentation is hosted here:
[https://docs.sciml.ai/DiffEqDocs/stable/basics/integrator/](https://docs.sciml.ai/DiffEqDocs/stable/basics/integrator/).
This docstring describes basic functionality only!

Initialize using `integrator = init(prob::ODEProblem, alg; kwargs...)`. The keyword args which are accepted are the same
[common solver options](https://docs.sciml.ai/DiffEqDocs/stable/basics/common_solver_opts/)
used by `solve`.

For reference, relevant fields of the `ODEIntegrator` are:

  - `t` - time of the proposed step
  - `u` - value at the proposed step
  - `opts` - common solver options
  - `alg` - the algorithm associated with the solution
  - `f` - the function being solved
  - `sol` - the current state of the solution
  - `tprev` - the last timepoint
  - `uprev` - the value at the last timepoint

`opts` holds all of the common solver options, and can be mutated to change the solver characteristics.
For example, to modify the absolute tolerance for the future timesteps, one can do:

```julia
integrator.opts.abstol = 1e-9
```

For more info see the linked documentation page.
"""
mutable struct ODEIntegrator{
        algType, IIP,
        uType, duType, tType, pType, eigenType, tdirType,
        ksEltype, SolType, F, CacheType, O, FSALType, EventErrorType,
        CallbackCacheType, IA, DV, CC, RNGType, WType, PType, SqdtType,
        NoiseType, CType, RCType,
    } <:
    SciMLBase.AbstractODEIntegrator{algType, IIP, uType, tType}
    sol::SolType
    u::uType
    du::duType
    k::ksEltype
    t::tType
    dt::tType
    f::F
    p::pType
    uprev::uType
    uprev2::uType
    duprev::duType
    tprev::tType
    alg::algType
    dtcache::tType
    dtchangeable::Bool
    dtpropose::tType
    tdir::tdirType
    eigen_est::eigenType
    controller_cache::CC
    success_iter::Int
    iter::Int
    saveiter::Int
    saveiter_dense::Int
    cache::CacheType
    callback_cache::CallbackCacheType
    kshortsize::Int
    force_stepfail::Bool
    last_stepfail::Bool
    just_hit_tstop::Bool
    next_step_tstop::Bool
    tstop_target::tType
    do_error_check::Bool
    event_last_time::Int
    vector_event_last_time::Int
    last_event_error::EventErrorType
    accept_step::Bool
    isout::Bool
    reeval_fsal::Bool
    derivative_discontinuity::Bool
    reinitialize::Bool
    isdae::Bool
    opts::O
    stats::SciMLBase.DEStats
    initializealg::IA
    differential_vars::DV
    fsalfirst::FSALType
    fsallast::FSALType
    rng::RNGType
    is_disco_step::Bool
    disco_checkpoint::tType
    W::WType
    P::PType
    sqdt::SqdtType
    # SDE/RODE fields: populated by SDE packages, Nothing for pure ODE.
    noise::NoiseType
    c::CType
    rate_constants::RCType
end
