


#=Satellite State=#
abstract type State end

struct SingleStates <: State
        stocks::Vector{Float32}
        debris::Vector{Float32}
end

struct MultiStates <: State
        stocks::Array{Float32}
        debris::Array{Float32}
end

#function state_to_tuple(s::State)
#        return (s.stocks ,s.debris)
#end

#=Physical Model
This contains parameters describing the physical model.
=#
abstract type PhysicalModel end
        
#=Basic implementation of a physical model=#
struct BasicPhysics <: PhysicalModel
        #rate at which debris hits satellites
        debris_collision_rate::Real
        #rate at which satellites of different constellations collide
        satellite_collision_rates::Matrix{Float64}
        #rate at which debris exits orbits
        decay_rate::Real
        #rate at which satellites
        autocatalysis_rate::Real
        #ratio at which a collision between satellites produced debris
        satellite_collision_debris_ratio::Real
        #Ratio at which launches produce debris
        launch_debris_ratio::Real
end

function state_transition(
    physics::BasicPhysics
    ,state::State 
    ,launches::Vector{Float32}
    ,survival_rate::Function
)
    #=
    Physical Transitions
    =#
    survival_rates = survival_rate(state,physics)

    # Debris transitions

    # get changes in debris from natural dynamics
    natural_debris_dynamics = (1 - physics.decay_rate + physics.autocatalysis_rate) * state.debris 
    
    # get changes in debris from satellite loss
    satellite_loss_debris = physics.satellite_collision_debris_ratio * (1 .- survival_rates)' * state.stocks 
    
    # get changes in debris from launches
    launch_debris = physics.launch_debris_ratio * sum(launches)
    
    # total debris level
    debris′ = natural_debris_dynamics .+ satellite_loss_debris .+ launch_debris


    # Stocks Transitions
    stocks′ = (LinearAlgebra.diagm(survival_rates) .- physics.decay_rate)*state.stocks + launches

    return State(stocks′,debris′)
end 

function survival_rates_1(
    #This function describes the rate at which satellites survive each period.
    state::State
    ,physical_model::BasicPhysics
)	
#TODO! get this to broadcast correctly.
    return exp.(-(physical_model.satellite_collision_rates .+ physical_model.decay_rate) * state.stocks .- (physical_model.debris_collision_rate * state.debris))
end
