package jetbrains.mps.kotlin.scopes.signed;

/*Generated by MPS */

import jetbrains.mps.scope.Scope;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.internal.collections.runtime.Sequence;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import org.jetbrains.mps.openapi.language.SInterfaceConcept;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;

/**
 * Simple way to get a signature scope as a scope.
 */
public class SignatureScopeAsScope extends Scope {
  private final SignatureScope wrapped;
  private final SAbstractConcept filteringConcept;

  public SignatureScopeAsScope(SignatureScope wrapped, SAbstractConcept filteringConcept) {
    this.wrapped = wrapped;
    this.filteringConcept = filteringConcept;
  }

  public SignatureScopeAsScope(SignatureScope wrapped) {
    this(wrapped, CONCEPTS.INamedConcept$Kd);
  }

  @Override
  public SNode resolve(SNode contextNode, String refText) {
    // Copy of NamedElementsScope behavior, but we do not necessarily consume the entire scope
    SNode result = null;
    for (SNode element : Sequence.fromIterable(getAvailableElements(refText))) {
      if (refText.equals(getReferenceText(contextNode, element))) {
        if (result == null) {
          result = element;
        } else {
          // ambiguity
          return null;
        }
      }
    }
    return result;
  }

  @Override
  public Iterable<SNode> getAvailableElements(@Nullable String prefix) {
    if (wrapped == null) {
      return Sequence.fromIterable(Collections.<SNode>emptyList());
    }
    return Sequence.fromIterable(SNodeOperations.ofConcept(Sequence.fromIterable(wrapped.getElements(prefix)).select((it) -> it.getSource()), SNodeOperations.asSConcept(filteringConcept))).distinct();
  }

  @Override
  public String getReferenceText(SNode contextNode, SNode node) {
    return node.getName();
  }

  @Override
  public boolean contains(SNode node) {
    if (wrapped == null) {
      return false;
    }
    return wrapped.contains(node);
  }

  private static final class CONCEPTS {
    /*package*/ static final SInterfaceConcept INamedConcept$Kd = MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, "jetbrains.mps.lang.core.structure.INamedConcept");
  }
}
