abstract type AbstractSesScaler end
abstract type AbstractInvSesScaler end



function get_factors(scaler::AbstractSesScaler)
    factors = softmax(scaler.factors);
    n = length(factors);

    if is_additive(scaler.mode)
        avg = sum(factors) / n;
        factors = factors .- avg;
        return factors;
    end

    return factors * n;
end



rescale(scaler::Type{S}, label::Real, factor::Real) where {S<:AbstractSesScaler} = rescale(scaler.mode, label, factor);
rescale(scaler::Type{S}, label::AbstractVecOrMat{<:Real}, factor::AbstractVecOrMat{<:Real}) where {S<:AbstractSesScaler} =
    rescale(scaler.mode, label, factor);



scale(scaler::Type{S}, label::Real, factor::Real) where {S<:AbstractSesScaler} = scale(scaler.mode, label, factor);
scale(scaler::Type{S}, label::AbstractVecOrMat{<:Real}, factor::AbstractVecOrMat{<:Real}) where {S<:AbstractSesScaler} =
    scale(scaler.mode, label, factor);



(scaler::AbstractSesScaler)(t::Tuple{<:AbstractVecOrMat{L}, <:Dict{Symbol, <:AbstractVector{I}}}) where {I, L} =
    scaler(t...);
function (scaler::AbstractSesScaler)(labels::Union{L, AbstractVecOrMat{L}}, idxs::AbstractVector{I}) where {I, L}
    factors = get_factors(scaler)[idxs];

    # println("[Scale] Factors: $factors");
    return scale(scaler.mode, labels, factors);
end



(invscaler::AbstractInvSesScaler)(t::Tuple{<:Union{L, AbstractVecOrMat{L}}, <:Dict{Symbol, <:AbstractVector{I}}}) where {I, L} =
    invscaler(t...);
function (invscaler::AbstractInvSesScaler)(labels::Union{L, AbstractVecOrMat{L}}, idxs::AbstractVector{I}) where {I, L}
    factors = get_factors(invscaler.scaler)[idxs];

    # println("[Rescale] Factors: $factors");
    return rescale(invscaler.scaler.mode, labels, factors);
end