package jetbrains.mps.lang.migration.runtime.base;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import jetbrains.mps.logging.Logger;
import org.jetbrains.mps.openapi.module.SModuleReference;
import jetbrains.mps.smodel.Language;
import org.jetbrains.mps.openapi.module.SModule;
import org.jetbrains.mps.openapi.module.SRepository;
import jetbrains.mps.project.Project;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModuleOperations;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.refactoring.participant.RefactoringParticipant;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.smodel.structure.ExtensionPoint;
import java.util.List;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.smodel.behaviour.BHReflection;
import jetbrains.mps.core.aspects.behaviour.SMethodIdV2;
import java.util.Objects;
import org.jetbrains.mps.openapi.language.SConcept;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SProperty;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import org.jetbrains.mps.openapi.language.SReferenceLink;

@GeneratedClass(node = "528ff3b9-5fc4-40dd-931f-c6ce3650640e/r:f69c3fa1-0e30-4980-84e2-190ae44e4c3d(jetbrains.mps.lang.migration.runtime/jetbrains.mps.lang.migration.runtime.base)/5168866961623738063", model = "528ff3b9-5fc4-40dd-931f-c6ce3650640e/r:f69c3fa1-0e30-4980-84e2-190ae44e4c3d(jetbrains.mps.lang.migration.runtime/jetbrains.mps.lang.migration.runtime.base)")
public class RefactoringScriptReference implements BaseScriptReference<RefactoringScript> {
  private static final Logger LOG = Logger.getLogger(RefactoringScriptReference.class);
  private final SModuleReference myModule;
  private final int fromVersion;
  private final int myModuleActualVersion;

  public RefactoringScriptReference(Language module, int fromVersion) {
    this.myModule = module.getModuleReference();
    this.fromVersion = fromVersion;
    this.myModuleActualVersion = module.getModuleVersion();
  }
  public SModule getModule(SRepository repository) {
    return myModule.resolve(repository);
  }
  public SModuleReference getModuleReference() {
    return myModule;
  }
  public int getFromVersion() {
    return fromVersion;
  }
  public int getModuleActualVersion() {
    // XXX no idea if this has to be part of equals/hashCode; was not prior to extraction of this logic.
    return myModuleActualVersion;
  }
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || this.getClass() != o.getClass()) {
      return false;
    }
    RefactoringScriptReference that = (RefactoringScriptReference) o;
    if (!(myModule.equals(that.myModule))) {
      return false;
    }
    if (fromVersion != that.fromVersion) {
      return false;
    }
    return true;
  }
  @Override
  public int hashCode() {
    return myModule.hashCode() + 31 * fromVersion;
  }
  @Override
  public String toString() {
    return "Refactoring[" + myModule.getModuleName() + ";" + fromVersion + "]";
  }

  /**
   * 
   * 
   * @deprecated use {@link jetbrains.mps.lang.migration.runtime.base.RefactoringScriptReference#resolve(SRepository, RefactoringScriptReference) } instead
   */
  @Override
  @Deprecated(forRemoval = true, since = "2023.1")
  public RefactoringScript resolve(Project p, boolean silent) {
    return RefactoringScriptReference.resolve(p.getRepository(), this);
    // todo store ModuleRef instead of SModule
  }

  public static RefactoringScript resolve(final SRepository repo, final RefactoringScriptReference sr) {
    final Wrappers._T<RefactoringScript> implementation = new Wrappers._T<RefactoringScript>(null);
    repo.getModelAccess().runReadAction(() -> {
      // FIXME once the only use in RefactoringScriptCollector, don't need read action here
      //      besides, perhaps can go w/o module resolution, just keep instance in RefactoringScriptCollector until result()
      SModule module = sr.getModule(repo);
      if (module instanceof Language) {
        Language depModule = (Language) module;
        final int current = sr.getFromVersion();
        SModel migrationModel = SModuleOperations.getAspect(depModule, "migration");
        final SNode log = ListSequence.fromList(SModelOperations.roots(migrationModel, CONCEPTS.RefactoringLog$xp)).where((it) -> SPropertyOperations.getInteger(it, PROPS.fromVersion$clQh) == current).first();
        if (log == null) {
          if (LOG.isWarningLevel()) {
            LOG.warning("Could not load refactoring log for module " + depModule + ", version " + current + ".");
          }
          return;
        }
        Iterable<RefactoringParticipant.PersistentRefactoringParticipant<?, ?, ?, ?>> participants = Sequence.fromIterable(new ExtensionPoint<Iterable<RefactoringParticipant.PersistentRefactoringParticipant<?, ?, ?, ?>>>("jetbrains.mps.refactoring.participant.PersistentRefactoringParticipantsEP").getObjects()).translate((it) -> it);
        List<RefactoringScriptReference> executeAfter = Sequence.fromIterable(SLinkOperations.collect(SLinkOperations.getChildren(log, LINKS.executeAfter$clBg), LINKS.refactoring$cu5K)).select((it) -> ((RefactoringScriptReference) (RefactoringScriptReference) BHReflection.invoke0(it, CONCEPTS.RefactoringLog$xp, SMethodIdV2.create("getDescriptor", 5168866961623837055L, 0x7a1d72ee255558fL)))).toList();
        List<RefactoringPartImpl> parts = Sequence.fromIterable(participants).select((final RefactoringParticipant.PersistentRefactoringParticipant<?, ?, ?, ?> participant) -> {
          List<SNode> participantParts = ListSequence.fromList(SLinkOperations.getChildren(log, LINKS.part$cm5i)).where((it) -> Objects.equals(SPropertyOperations.getString(it, PROPS.participant$1LmE), participant.getId())).toList();
          return new RefactoringPartImpl(SLinkOperations.getTarget(log, LINKS.options$KIbw), participantParts, participant);
        }).toList();
        implementation.value = new BaseRefactoringScript(SPropertyOperations.getString(log, PROPS.name$MnvL), ((RefactoringScriptReference) BHReflection.invoke0(log, CONCEPTS.RefactoringLog$xp, SMethodIdV2.create("getDescriptor", 5168866961623837055L, 0x7a1d72ee255558fL))), executeAfter, parts);
      }
    });
    return implementation.value;
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept RefactoringLog$xp = MetaAdapterFactory.getConcept(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x1bf9eb43276b6d8fL, "jetbrains.mps.lang.migration.structure.RefactoringLog");
  }

  private static final class PROPS {
    /*package*/ static final SProperty fromVersion$clQh = MetaAdapterFactory.getProperty(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x1bf9eb43276b6d8fL, 0x1bf9eb43276b6d91L, "fromVersion");
    /*package*/ static final SProperty participant$1LmE = MetaAdapterFactory.getProperty(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x2b3f57492c163158L, 0x325b97b223b9e3aaL, "participant");
    /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name");
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink executeAfter$clBg = MetaAdapterFactory.getContainmentLink(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x1bf9eb43276b6d8fL, 0x1bf9eb43276b6d90L, "executeAfter");
    /*package*/ static final SReferenceLink refactoring$cu5K = MetaAdapterFactory.getReferenceLink(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x1bf9eb43276b6d9dL, 0x1bf9eb43276b6d9eL, "refactoring");
    /*package*/ static final SContainmentLink part$cm5i = MetaAdapterFactory.getContainmentLink(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x1bf9eb43276b6d8fL, 0x1bf9eb43276b6d92L, "part");
    /*package*/ static final SContainmentLink options$KIbw = MetaAdapterFactory.getContainmentLink(0x9074634404fd4286L, 0x97d5b46ae6a81709L, 0x1bf9eb43276b6d8fL, 0x31ee543051f2333cL, "options");
  }
}
