package jetbrains.mps.vcs.diff.changes;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import org.jetbrains.mps.openapi.model.SNodeId;
import java.util.Objects;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.List;

@GeneratedClass(node = "r:9b4a89e1-ec38-42c4-b1bd-96ab47ffcb3f(jetbrains.mps.vcs.diff.changes)/786283152089460452", model = "r:9b4a89e1-ec38-42c4-b1bd-96ab47ffcb3f(jetbrains.mps.vcs.diff.changes)")
/*package*/ class HierarchicalChangeConflictsUtil {

  private HierarchicalChangeConflictsUtil() {
  }

  /*package*/ static boolean moveConflictsWithNotMove(@NotNull NodeGroupNotMoveChange notMoveChange, @NotNull NodeGroupMoveChange moveChange, @NotNull Map<SNodeId, SNodeId> symmetricIds) {
    SNodeId moveNextId = moveChange.getGroup(true).getActualNextNodeId();
    return moveChange.hasIntersectingSourceWith(notMoveChange) || notMoveChange.containsDeletedNode(moveChange.getParentId(true)) || notMoveChange.containsDeletedNode(moveChange.getParentId(false)) || (moveNextId != null && notMoveChange.containsDeletedNode(moveNextId)) || moveChange.getGroup(true).hasCommonAnchorWith(notMoveChange.getGroup(true), symmetricIds);
  }

  /*package*/ static boolean wrapConflictsWithNotMove(NodeGroupWrapChange wrapChange, NodeGroupNotMoveChange notMoveChange, Map<SNodeId, SNodeId> symmetricIds, boolean wrapConflictsWithInternalChanges) {

    WrappingNodesGroup wrappingGroup = wrapChange.getWrappingGroup();
    if (wrapChange.isWrap()) {
      return wrappingGroupConflictsWithGroup(wrappingGroup, true, notMoveChange.getGroup(false), wrapConflictsWithInternalChanges) || notMoveChange.containsDeletedNode(wrappingGroup.getUnwrappedParentId());
    } else {
      return wrappingGroup.intersectsWith(notMoveChange.getGroup(false)) || notMoveChange.containsDeletedNode(wrappingGroup.getParentId()) || wrapChange.containsDeletedNode(notMoveChange.getParentId(false));
    }
  }

  /*package*/ static boolean wrapConflictsWithMove(NodeGroupWrapChange wrapChange, NodeGroupMoveChange moveChange, Map<SNodeId, SNodeId> symmetricIds, boolean wrapConflictsWithInternalChanges) {

    WrappingNodesGroup wrappingGroup = wrapChange.getWrappingGroup();
    if (wrapChange.isWrap()) {
      return wrappingGroupConflictsWithGroup(wrappingGroup, true, moveChange.getGroup(false), wrapConflictsWithInternalChanges) || wrappingGroupConflictsWithGroup(wrappingGroup, true, moveChange.getGroup(true), wrapConflictsWithInternalChanges) || moveChange.getGroup(true).hasCommonAnchorWith(wrappingGroup.getFirstUnwrappedGroup(), symmetricIds) || Objects.equals(moveChange.getGroup(true).getNextNodeId(), wrappingGroup.getFirstUnwrappedGroup().getFirstNodeId());
    } else {
      return wrappingGroup.intersectsWith(moveChange.getGroup(false)) || moveChange.getGroup(true).hasCommonAnchorWith(wrappingGroup, symmetricIds) || Objects.equals(moveChange.getGroup(true).getNextNodeId(), wrappingGroup.getWrappingNodeId()) || wrapChange.containsDeletedNode(moveChange.getParentId(false)) || wrapChange.containsDeletedNode(moveChange.getParentId(true));
    }
  }

  /*package*/ static boolean modifiedGroupIsInternalInWrap(WrappingNodesGroup wrappingGroup, boolean isWrap, ModifiedNodesGroup group) {

    SNodeId parentId = (isWrap ? wrappingGroup.getUnwrappedParentId() : wrappingGroup.getWrappedParentId());
    SContainmentLink link = (isWrap ? wrappingGroup.getUnwrappedLink() : wrappingGroup.getWrappedLink());

    if (!(Objects.equals(parentId, group.getParentId())) || !(Objects.equals(link, group.getLink()))) {
      return false;
    }


    SNodeId firstWrappedNodeId = ListSequence.fromList(wrappingGroup.getWrappedGroups()).where((it) -> it.isWrappedMove()).first().getFirstNodeId();

    SNodeId lastWrappedNodeId = ListSequence.fromList(ListSequence.fromList(wrappingGroup.getWrappedGroups()).where((it) -> it.isWrappedMove()).last().getIds()).last();

    List<SNodeId> siblings = group.getSiblings();

    int wrapBegin = ListSequence.fromList(siblings).indexOf(firstWrappedNodeId);
    int wrapEnd = ListSequence.fromList(siblings).indexOf(lastWrappedNodeId) + 1;

    if (wrapBegin == -1 || wrapEnd == -1) {
      return false;
    }
    int begin = group.getBegin();
    int end = group.getEnd();

    return begin > wrapBegin && end < wrapEnd;
  }


  /*package*/ static boolean wrappingGroupConflictsWithGroup(WrappingNodesGroup wrappingGroup, boolean isWrap, ModifiedNodesGroup group, boolean wrapConflictsWithInternalChanges) {

    if (!(wrapConflictsWithInternalChanges) && modifiedGroupIsInternalInWrap(wrappingGroup, isWrap, group)) {
      return false;
    }

    if (!(Objects.equals(wrappingGroup.getUnwrappedParentId(), group.getParentId())) || !(Objects.equals(wrappingGroup.getUnwrappedLink(), group.getLink()))) {
      return false;
    }

    int wrapBegin = wrappingGroup.getFirstUnwrappedGroup().getBegin();
    int wrapEnd = wrappingGroup.getLastUnwrappedGroup().getEnd();
    int begin = group.getBegin();
    int end = group.getEnd();
    return wrapBegin <= end && begin <= wrapEnd;
  }
}
