# function Base.getproperty(obj::Chain, sym::Symbol)
#     if sym == :layers
#         return getfield(obj, sym);
#     else
#         return getproperty(obj.cell, sym);
#     end
# end

# ^^^^^^^^^^^^^^^^^^^^^^^^^^
# ====> Main Functions <====
# ^^^^^^^^^^^^^^^^^^^^^^^^^^
function smooth(labels::AbstractVector{<:Real}, alpha::AbstractFloat = 0.3f0; trainLen::Integer = length(labels))
    preds = fill(0.0f0, trainLen);
    preds[2] = labels[1];

    for idx in 3:trainLen
        preds[idx] = alpha * labels[idx - 1] + (1 - alpha) * preds[idx - 1];
    end

    return preds;
end


predict(last::Real, horizon = 1) = fill(last, horizon);
predict(smoothed::AbstractVector{<:Real}, horizon = 1) = fill(last(smoothed), horizon);



restart!(nt::NamedTuple; kwargs...) = restart!(values(nt); kwargs...);
function restart!(t::Tuple; kwargs...)
    for elem in t
        tp = typeof(elem);
        restart_ms = methods(restart!, [tp], [Ses]);
        if !isempty(restart_ms)
            restart!(elem; kwargs...);
        end
    end
end
testmode!(nt::NamedTuple) = testmode!(values(nt));
function testmode!(t::Tuple)
    for elem in t
        tp = typeof(elem);
        testmode_ms = methods(testmode!, [tp], [Ses]);
        if !isempty(testmode_ms)
            testmode!(elem);
        end
    end
end



@forward Chain.layers restart!
@forward SkipConnection.layers restart!

Recur(cell::C) where {C<:AbstractSesCell} = Recur(cell, cell.state0);
Mapped(cell::C) where {C<:AbstractSesCell} = SesMap(Recur(cell));