package jetbrains.mps.make.facet.constraints;

/*Generated by MPS */

import jetbrains.mps.lang.scopes.runtime.SimpleScope;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.module.SModule;
import jetbrains.mps.project.SModuleOperations;
import java.util.Set;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import jetbrains.mps.internal.collections.runtime.CollectionSequence;
import jetbrains.mps.project.dependency.GlobalModuleDependenciesManager;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.lang.core.behavior.INamedConcept__BehaviorDescriptor;
import org.jetbrains.mps.openapi.language.SConcept;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;

public class FacetsScope extends SimpleScope {
  public FacetsScope(SNode contextNode) {
    super(getAvailableFacets(contextNode));
  }


  /**
   * TODO reorganize facets in the project: we must not look at SolutionKind here
   * probably it makes sense to declare all facets only in languages
   */
  private static boolean hackCondition(SModule module) {
    return SModuleOperations.canSupplyExtensionsForMPS(module);
  }

  public static Iterable<SNode> getAvailableFacets(SNode contextNode) {
    SModule contextModule = contextNode.getModel().getModule();

    Set<SModule> contextModules = SetSequence.fromSet(new HashSet<SModule>());
    for (SModule module : CollectionSequence.fromCollection(new GlobalModuleDependenciesManager(contextModule).getModules(GlobalModuleDependenciesManager.Deptype.VISIBLE))) {
      if (hackCondition(module)) {
        SetSequence.fromSet(contextModules).addElement(module);
      }
    }
    SetSequence.fromSet(contextModules).addElement(contextModule);

    // collect models
    Iterable<SModel> models = SetSequence.fromSet(contextModules).translate((it) -> it.getModels());

    // collect facets
    return SNodeOperations.ofConcept(Sequence.fromIterable(models).where(new NotNullWhereFilter()).translate((it) -> it.getRootNodes()), CONCEPTS.FacetDeclaration$Nd);
  }

  @Nullable
  @Override
  public String getReferenceText(@NotNull SNode target) {
    return (String) INamedConcept__BehaviorDescriptor.getFqName_idhEwIO9y.invoke(SNodeOperations.cast(target, CONCEPTS.AbstractConceptDeclaration$KA));
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept FacetDeclaration$Nd = MetaAdapterFactory.getConcept(0x696c11654a59463bL, 0xbc5d902caab85dd0L, 0x5912a2ab1cd24c13L, "jetbrains.mps.make.facet.structure.FacetDeclaration");
    /*package*/ static final SConcept AbstractConceptDeclaration$KA = MetaAdapterFactory.getConcept(0xc72da2b97cce4447L, 0x8389f407dc1158b7L, 0x1103553c5ffL, "jetbrains.mps.lang.structure.structure.AbstractConceptDeclaration");
  }
}
