package jetbrains.mps.vcs.mergehints.plugin.plugin;

/*Generated by MPS */

import jetbrains.mps.plugins.relations.RelationDescriptor;
import javax.swing.Icon;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.ArrayList;
import org.jetbrains.mps.openapi.module.SModule;
import jetbrains.mps.smodel.Language;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModuleOperations;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import org.jetbrains.mps.openapi.language.SConcept;
import jetbrains.mps.plugins.relations.CreateAspectContext;
import jetbrains.mps.smodel.language.LanguageAspectDescriptor;
import jetbrains.mps.smodel.language.LanguageAspectSupport;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import org.jetbrains.mps.openapi.language.SReferenceLink;
import org.jetbrains.mps.openapi.language.SProperty;

public class Version_Control_TabDescriptor extends RelationDescriptor {
  private static final Icon ICON = IconContainer.ICON_a0;

  public Version_Control_TabDescriptor() {
  }
  public String getTitle() {
    return "Version Control";
  }
  public int compareTo(RelationDescriptor descriptor) {
    return new VersionControl_Order().compare(this, descriptor);
  }
  public void startListening() {
  }
  public SNode getBaseNode(SNode node) {
    return null;
  }
  public boolean isApplicable(SNode node) {
    return SNodeOperations.isInstanceOf(node, CONCEPTS.AbstractConceptDeclaration$KA);
  }
  @Nullable
  public Icon getIcon() {
    return ICON;
  }
  public List<SNode> getNodes(SNode node) {
    List<SNode> nodes = new ArrayList<SNode>();
    SModule module = SNodeOperations.getModel(node).getModule();
    if (!(module instanceof Language)) {
      return nodes;
    }

    SModel vcsModel = SModuleOperations.getAspect(module, "vcs");
    if (vcsModel == null) {
      return nodes;
    }

    ListSequence.fromList(nodes).addSequence(ListSequence.fromList(SModelOperations.roots(vcsModel, CONCEPTS.VCSHints$kA)).where((it) -> {
      return ListSequence.fromList(SLinkOperations.getChildren(it, LINKS.concepts$nb$7)).any(new _FunctionTypes._return_P1_E0<Boolean, SNode>() {
        public Boolean invoke(SNode it) {
          return SLinkOperations.getTarget(it, LINKS.cncpt$ubC$) == node;
        }
      });
    }));
    return nodes;
  }
  public boolean isSingle() {
    return false;
  }
  public Iterable<SConcept> getAspectConcepts(final SNode node) {
    return ListSequence.fromListAndArray(new ArrayList<SConcept>(), CONCEPTS.VCSHints$kA);
  }
  protected SNode doCreateAspect(final CreateAspectContext _context) {
    SModule module = SNodeOperations.getModel(_context.getBaseNode()).getModule();
    SModel aspectModel = SModuleOperations.getAspect(module, "vcs");
    if (aspectModel == null) {
      // XXX Similar to other places, like LanguageProducer.createMainLanguageAspects(), would be great to unify
      LanguageAspectDescriptor vcsAD = LanguageAspectSupport.getAspectDescriptorById("vcs");
      jetbrains.mps.smodel.language.CreateAspectContext cac = jetbrains.mps.smodel.language.CreateAspectContext.create(module, _context.getProject().getPlatform(), null);
      if (vcsAD == null || !(vcsAD.canCreate(cac))) {
        return null;
      }
      vcsAD.create(cac);
      // can get result through CreateAspectContext, but can tolerate the other way 
      aspectModel = vcsAD.getAspectModels(module).stream().findAny().orElse(null);
    }

    assert aspectModel != null;
    SNode hints = SModelOperations.createNewRootNode(aspectModel, MetaAdapterFactory.getConcept(0x37e03aa1728949bcL, 0x826930de5eceec76L, 0x39744cf955c648f9L, "jetbrains.mps.vcs.mergehints.structure.VCSHints"));
    SPropertyOperations.assign(hints, PROPS.name$MnvL, SPropertyOperations.getString(_context.getBaseNode(), PROPS.name$MnvL) + "_Hints");
    SNode conceptHint = SLinkOperations.addNewChild(hints, LINKS.concepts$nb$7, null);
    // FIXME once nodePointer has property type (node-ptr<EditorTab.baseNodeConcept>), can use set-ptr here
    SLinkOperations.setTarget(conceptHint, LINKS.cncpt$ubC$, _context.getBaseNode());

    return hints;
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept AbstractConceptDeclaration$KA = MetaAdapterFactory.getConcept(0xc72da2b97cce4447L, 0x8389f407dc1158b7L, 0x1103553c5ffL, "jetbrains.mps.lang.structure.structure.AbstractConceptDeclaration");
    /*package*/ static final SConcept VCSHints$kA = MetaAdapterFactory.getConcept(0x37e03aa1728949bcL, 0x826930de5eceec76L, 0x39744cf955c648f9L, "jetbrains.mps.vcs.mergehints.structure.VCSHints");
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink concepts$nb$7 = MetaAdapterFactory.getContainmentLink(0x37e03aa1728949bcL, 0x826930de5eceec76L, 0x39744cf955c648f9L, 0x39744cf955c648faL, "concepts");
    /*package*/ static final SReferenceLink cncpt$ubC$ = MetaAdapterFactory.getReferenceLink(0x37e03aa1728949bcL, 0x826930de5eceec76L, 0x39744cf955c648fcL, 0x39744cf955c649b5L, "cncpt");
  }

  private static final class PROPS {
    /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name");
  }
}
