using Oceananigans.BoundaryConditions: compute_x_bcs!, compute_y_bcs!, compute_z_bcs!
using Oceananigans.TimeSteppers: TimeSteppers

#####
##### Boundary contributions to hydrostatic free surface model
#####

function compute_flux_bcs!(Gcⁿ, c, arch, args)
    compute_x_bcs!(Gcⁿ, c, arch, args...)
    compute_y_bcs!(Gcⁿ, c, arch, args...)
    compute_z_bcs!(Gcⁿ, c, arch, args...)
    return nothing
end

@inline function compute_momentum_flux_bcs!(model::HydrostaticFreeSurfaceModel)
    Gⁿ   = model.timestepper.Gⁿ
    grid = model.grid
    arch = architecture(grid)
    args = (model.clock, fields(model), model.closure, model.buoyancy)

    compute_flux_bcs!(Gⁿ.u, model.velocities.u, arch, args)
    compute_flux_bcs!(Gⁿ.v, model.velocities.v, arch, args)

    return nothing
end

@inline function compute_tracer_flux_bcs!(model::HydrostaticFreeSurfaceModel)
    compute_tracer_flux_bcs!(model, Val(propertynames(model.tracers)))
    return nothing
end

@inline compute_tracer_flux_bcs!(model, ::Val{()}) = nothing

@inline function compute_tracer_flux_bcs!(model, ::Val{names}) where names
    name = first(names)
    args = (model.clock, fields(model), model.closure, model.buoyancy)
    compute_flux_bcs!(model.timestepper.Gⁿ[name], model.tracers[name], architecture(model.grid), args)
    compute_tracer_flux_bcs!(model, Val(Base.tail(names)))
    return nothing
end
