import QEDbase.mass
import QEDbase.AbstractParticle

"""
    AbstractPhysicsModel

Base type for a model, e.g. ABC-Model or QED. This is used to dispatch many functions.
"""
abstract type AbstractPhysicsModel end

"""
    ParticleValue{ParticleType <: AbstractParticle}

A struct describing a particle during a calculation of a Feynman Diagram, together with the value that's being calculated. `AbstractParticle` is the type from the QEDbase package.

`sizeof(ParticleValue())` = 48 Byte
"""
struct ParticleValue{ParticleType <: AbstractParticle, ValueType}
    p::ParticleType
    v::ValueType
end

"""
    AbstractProcessDescription

Base type for process descriptions. An object of this type of a corresponding [`AbstractPhysicsModel`](@ref) should uniquely identify a process in that model.

See also: [`parse_process`](@ref)
"""
abstract type AbstractProcessDescription end

"""
    AbstractProcessInput

Base type for process inputs. An object of this type contains the input values (e.g. momenta) of the particles in a process.

See also: [`gen_process_input`](@ref)
"""
abstract type AbstractProcessInput end

"""
    interaction_result(t1::Type{T1}, t2::Type{T2}) where {T1 <: AbstractParticle, T2 <: AbstractParticle}

Interface function that must be implemented for every subtype of [`AbstractParticle`](@ref), returning the result particle type when the two given particles interact.
"""
function interaction_result end

"""
    types(::AbstractPhysicsModel)

Interface function that must be implemented for every subtype of [`AbstractPhysicsModel`](@ref), returning a `Vector` of the available particle types in the model.
"""
function types end

"""
    in_particles(::AbstractProcessDescription)

Interface function that must be implemented for every subtype of [`AbstractProcessDescription`](@ref).
Returns a `<: Dict{Type{AbstractParticle}, Int}` object, representing the number of incoming particles for the process per particle type.


    in_particles(::AbstractProcessInput)

Interface function that must be implemented for every subtype of [`AbstractProcessInput`](@ref).
Returns a `<: Vector{AbstractParticle}` object with the values of all incoming particles for the corresponding `ProcessDescription`.
"""
function in_particles end

"""
    out_particles(::AbstractProcessDescription)

Interface function that must be implemented for every subtype of [`AbstractProcessDescription`](@ref).
Returns a `<: Dict{Type{AbstractParticle}, Int}` object, representing the number of outgoing particles for the process per particle type.


    out_particles(::AbstractProcessInput)

Interface function that must be implemented for every subtype of [`AbstractProcessInput`](@ref).
Returns a `<: Vector{AbstractParticle}` object with the values of all outgoing particles for the corresponding `ProcessDescription`.
"""
function out_particles end

"""
    parse_process(::AbstractString, ::AbstractPhysicsModel)

Interface function that must be implemented for every subtype of [`AbstractPhysicsModel`](@ref).
Returns a `ProcessDescription` object.
"""
function parse_process end

"""
    gen_process_input(::AbstractProcessDescription)

Interface function that must be implemented for every specific [`AbstractProcessDescription`](@ref).
Returns a randomly generated and valid corresponding `ProcessInput`.
"""
function gen_process_input end
