package org.metaborg.core.language;

import java.util.Collection;
import java.util.Set;

import javax.annotation.Nullable;

import org.metaborg.util.log.ILogger;
import org.metaborg.util.log.LoggerUtils;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class LanguageUtils {
    private static final ILogger logger = LoggerUtils.logger(LanguageUtils.class);


    public static Set<ILanguageImpl> toImpls(Iterable<? extends ILanguageComponent> components) {
        final Set<ILanguageImpl> impls = Sets.newHashSet();
        for(ILanguageComponent component : components) {
            Iterables.addAll(impls, component.contributesTo());
        }
        return impls;
    }

    public static @Nullable ILanguageImpl active(Iterable<? extends ILanguageImpl> impls) {
        ILanguageImpl active = null;
        for(ILanguageImpl impl : impls) {
            if(active == null || isGreater(impl, active)) {
                active = impl;
            }

        }
        return active;
    }

    public static Iterable<ILanguageImpl> allActiveImpls(ILanguageService languageService) {
        final Iterable<? extends ILanguage> languages = languageService.getAllLanguages();
        final Collection<ILanguageImpl> activeImpls = Lists.newLinkedList();
        for(ILanguage language : languages) {
            final ILanguageImpl impl = language.activeImpl();
            if(impl == null) {
                logger.debug(
                    "Unexpected null for active implementation of language {}, skipping in active language implementations",
                    language);
                continue;
            }
            activeImpls.add(impl);
        }
        return activeImpls;
    }

    public static Iterable<ILanguageComponent> allActiveComponents(ILanguageService languageService) {
        final Iterable<ILanguageImpl> activeImpls = allActiveImpls(languageService);
        final Collection<ILanguageComponent> activeComponents = Lists.newLinkedList();
        for(ILanguageImpl impl : activeImpls) {
            Iterables.addAll(activeComponents, impl.components());
        }
        return activeComponents;
    }


    private static boolean isGreater(ILanguageImpl impl, ILanguageImpl other) {
        int compareVersion = impl.id().version.compareTo(other.id().version);
        if(compareVersion > 0 || (compareVersion == 0 && impl.sequenceId() > other.sequenceId())) {
            return true;
        }
        return false;
    }
}

@@ -745,32 +745,356 @@
 rn impls;%0A    %7D%0A
+    %0A    public static Set%3CILanguageComponent%3E toComponents(Iterable%3C? extends ILanguageImpl%3E impls) %7B%0A        final Set%3CILanguageComponent%3E components = Sets.newHashSet();%0A        for(ILanguageImpl impl : impls) %7B%0A            Iterables.addAll(components, impl.components());%0A        %7D%0A        return components;%0A    %7D%0A%0A    
 %0A    public stat

Add toComponents method to LanguageUtils.