package dev.isxander.yacl3.api; import dev.isxander.yacl3.impl.ImmutableStateManager; import dev.isxander.yacl3.impl.InstantStateManager; import dev.isxander.yacl3.impl.SimpleStateManager; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; import java.util.function.Supplier; public interface StateManager { static StateManager createSimple(Binding binding) { return new SimpleStateManager<>(binding); } static StateManager createSimple(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter) { return new SimpleStateManager<>(Binding.generic(def, getter, setter)); } static StateManager createInstant(Binding binding) { return new InstantStateManager<>(binding); } static StateManager createInstant(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter) { return new InstantStateManager<>(Binding.generic(def, getter, setter)); } static StateManager createImmutable(@NotNull T value) { return new ImmutableStateManager<>(value); } /** * Sets the pending value. */ void set(T value); /** * @return the pending value. */ T get(); /** * Applies the pending value to the backed binding. */ void apply(); void resetToDefault(ResetAction action); /** * Essentially "forgets" the pending value and reassigns state as backed by the binding. */ void sync(); /** * @return true if the pending value is the same as the backed binding value. */ boolean isSynced(); /** * @return true if this state manage will always be synced with the backing binding. */ default boolean isAlwaysSynced() { return false; } boolean isDefault(); void addListener(StateListener stateListener); enum ResetAction { BY_OPTION, BY_GLOBAL, } interface StateListener { static StateListener noop() { return (oldValue, newValue) -> {}; } void onStateChange(T oldValue, T newValue); default StateListener andThen(StateListener after) { return (oldValue, newValue) -> { this.onStateChange(oldValue, newValue); after.onStateChange(oldValue, newValue); }; } } }