package ru.yandex.qe.dispenser.domain.util;

import java.util.Arrays;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

/**
 * Should be used only in those places, where beans can't be injected.
 * For example, in classes that are not initialized by Spring.
 */
@Component
@SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
public final class ApplicationContextProvider {
    private static volatile ApplicationContext context = null;

    @NotNull
    public static ApplicationContext getContext() {
        return context;
    }

    public static boolean containsBean(@NotNull final Class<?> type) {
        return context.getBeanNamesForType(type).length > 0;
    }

    @Nullable
    public static <T> T getBean(@NotNull final Class<T> type) {
        return containsBean(type) ? demandBean(type) : null;
    }

    @Nullable
    public static <T> T getBean(@NotNull final String name, @NotNull final Class<T> type) {
        return Arrays.asList(context.getBeanNamesForType(type)).contains(name) ? context.getBean(name, type) : null;
    }

    @NotNull
    public static <T> T demandBean(@NotNull final Class<T> type) {
        return getContext().getBean(type);
    }

    @Autowired
    public void setContext(@NotNull final ApplicationContext context) {
        this.context = context;
    }
}
