package jetbrains.mps.vcs.diff.changes;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.vcs.diff.ChangeSet;
import org.jetbrains.mps.openapi.model.SNodeId;
import org.jetbrains.mps.openapi.language.SReferenceLink;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.SModelReference;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.util.SNodeOperations;
import jetbrains.mps.vcs.diff.StructChangeSet;
import java.util.Objects;
import org.jetbrains.mps.openapi.model.ResolveInfo;
import jetbrains.mps.smodel.SNodePointer;
import org.jetbrains.mps.openapi.model.SReference;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;

@GeneratedClass(node = "r:9b4a89e1-ec38-42c4-b1bd-96ab47ffcb3f(jetbrains.mps.vcs.diff.changes)/4664177994951620648", model = "r:9b4a89e1-ec38-42c4-b1bd-96ab47ffcb3f(jetbrains.mps.vcs.diff.changes)")
public class SetReferenceStructChange extends SetReferenceChange {

  public SetReferenceStructChange(@NotNull ChangeSet changeSet, @NotNull SNodeId sourceNodeId, SNodeId newSourceNodeId, @NotNull SReferenceLink role, @Nullable SModelReference targetModelReference, @Nullable SNodeId targetNodeId, @Nullable String resolveInfo) {
    super(changeSet, sourceNodeId, newSourceNodeId, role, targetModelReference, targetNodeId, resolveInfo, false);
  }
  @Override
  public void apply(@NotNull SModel model, @NotNull NodeCopier nodeCopier) {
    assert model == getChangeSet().getOldModel();

    SNode node = model.getNode(getAffectedNodeId(false));
    assert node != null;
    if (getTargetNodeId() == null && getResolveInfo() == null) {
      node.dropReference(getRoleLink());
    } else {
      SModelReference targetModelReference = (getTargetModelReference() == null ? SModelOperations.getPointer(model) : getTargetModelReference());
      if (getTargetNodeId() == null) {
        node.setReference(getRoleLink(), SNodeOperations.qualifiedResolveInfo(getRoleLink(), targetModelReference, getResolveInfo()));
      } else {
        // try to convert SNodeId
        StructChangeSet changeset = (StructChangeSet) getChangeSet();
        SNodeId targetNodeId = getTargetNodeId();
        SNodeId mapToOldId = changeset.mapToOldId(targetNodeId);
        if (mapToOldId != null && Objects.equals(targetModelReference, SModelOperations.getPointer(changeset.getNewModel()))) {
          targetNodeId = mapToOldId;
        }
        node.setReference(getRoleLink(), ResolveInfo.of(new SNodePointer(targetModelReference, targetNodeId), getResolveInfo()));
      }
    }
  }
  @NotNull
  @Override
  protected ModelChange createOppositeChange() {
    SNode node = getChangeSet().getOldModel().getNode(getAffectedNodeId(false));
    assert node != null;
    SReference ref = node.getReference(getRoleLink());
    SModelReference targetModel = check_xjb9w7_a0d0d(ref);
    if (Objects.equals(SModelOperations.getPointer(getChangeSet().getOldModel()), targetModel)) {
      // This is internal reference
      targetModel = null;
    }

    return new SetReferenceStructChange(getChangeSet().getOppositeChangeSet(), getAffectedNodeId(true), getAffectedNodeId(false), getRoleLink(), targetModel, check_xjb9w7_f0a6a3(ref), SLinkOperations.getResolveInfo(ref));
  }
  private static SModelReference check_xjb9w7_a0d0d(SReference checkedDotOperand) {
    if (null != checkedDotOperand) {
      return checkedDotOperand.getTargetSModelReference();
    }
    return null;
  }
  private static SNodeId check_xjb9w7_f0a6a3(SReference checkedDotOperand) {
    if (null != checkedDotOperand) {
      return checkedDotOperand.getTargetNodeId();
    }
    return null;
  }
}
