package dev.rollczi.litecommands.bind;

import dev.rollczi.litecommands.util.MapUtil;
import java.util.function.Function;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;

public class BindRegistry implements BindChainAccessor {

    private final Map<Class<?>, Function<BindChainAccessor, ?>> instanceBindings = new HashMap<>();

    public <T> void bindInstance(Class<T> on, Function<BindChainAccessor, T> bind) {
        this.instanceBindings.put(on, bind);
    }

    public <T> void bindInstance(Class<T> on, Supplier<T> bind) {
        this.instanceBindings.put(on, chainAccessor -> bind.get());
    }

    public void bindInstanceUnsafe(Class<?> on, Supplier<?> bind) {
        this.instanceBindings.put(on, chainAccessor -> bind.get());
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> BindResult<T> getInstance(Class<T> clazz) {
        Optional<Function<BindChainAccessor, ?>> option = MapUtil.findByInstanceOf(clazz, this.instanceBindings);

        if (option.isPresent()) {
            Function<BindChainAccessor, T> supplier = (Function<BindChainAccessor, T>) option.get();

            return BindResult.ok(supplier.apply(this));
        }

        return BindResult.error("Cannot find binding for " + clazz.getName());
    }

}
