/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.psi.codeStyle.arrangement.engine;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.arrangement.*;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
import com.intellij.util.containers.*;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.Stack;
import com.intellij.util.text.CharArrayUtil;
import gnu.trove.TIntArrayList;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Section.END_SECTION;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Section.START_SECTION;

/**
 * Encapsulates generic functionality of arranging file elements by the predefined rules.
 * <p/>
 * I.e. the general idea is to have a language-specific rules hidden by generic arrangement API and common arrangement
 * engine which works on top of that API and performs the arrangement.
 *
 * @author Denis Zhdanov
 * @since 7/20/12 1:56 PM
 */
public class ArrangementEngine {

  /**
   * Arranges given PSI root contents that belong to the given ranges.
   * <b>Note:</b> After arrangement editor foldings we'll be preserved.
   *
   * @param editor
   * @param file   target PSI root
   * @param ranges target ranges to use within the given root
   */
  public void arrange(@NotNull final Editor editor, @NotNull PsiFile file, Collection<TextRange> ranges) {
    arrange(file, ranges, new RestoreFoldArrangementCallback(editor));
  }

  /**
   * Arranges given PSI root contents that belong to the given ranges.
   * <b>Note:</b> Editor foldings are not expected to be preserved.
   *
   * @param file   target PSI root
   * @param ranges target ranges to use within the given root
   */
  public void arrange(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges) {
    arrange(file, ranges, null);
  }
  
  /**
   * Arranges given PSI root contents that belong to the given ranges.
   *
   * @param file    target PSI root
   * @param ranges  target ranges to use within the given root
   */
  @SuppressWarnings("MethodMayBeStatic")
  public void arrange(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges, @Nullable final ArrangementCallback callback) {
    final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
    if (document == null) {
      return;
    }

    final Rearranger<?> rearranger = Rearranger.EXTENSION.forLanguage(file.getLanguage());
    if (rearranger == null) {
      return;
    }

    final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(file.getProject()).getCurrentSettings();
    ArrangementSettings arrangementSettings = settings.getCommonSettings(file.getLanguage()).getArrangementSettings();
    if (arrangementSettings == null && rearranger instanceof ArrangementStandardSettingsAware) {
      arrangementSettings = ((ArrangementStandardSettingsAware)rearranger).getDefaultSettings();
    }
    
    if (arrangementSettings == null) {
      return;
    }

    final DocumentEx documentEx;
    if (document instanceof DocumentEx && !((DocumentEx)document).isInBulkUpdate()) {
      documentEx = (DocumentEx)document;
    }
    else {
      documentEx = null;
    }

    final Context<? extends ArrangementEntry> context = Context.from(
      rearranger, document, file, ranges, arrangementSettings, settings
    );

    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        if (documentEx != null) {
          //documentEx.setInBulkUpdate(true);
        }
        try {
          doArrange(context);
          if (callback != null) {
            callback.afterArrangement(context.moveInfos);
          }
        }
        finally {
          if (documentEx != null) {
            //documentEx.setInBulkUpdate(false);
          }
        }
      }
    });
  }

  @SuppressWarnings("unchecked")
  private static <E extends ArrangementEntry> void doArrange(Context<E> context) {
    // The general idea is to process entries bottom-up where every processed group belongs to the same parent. We may not bother
    // with entries text ranges then. We use a list and a stack for achieving that than.
    //
    // Example:
    //            Entry1              Entry2
    //            /    \              /    \
    //      Entry11   Entry12    Entry21  Entry22
    //
    //    --------------------------
    //    Stage 1:
    //      list: Entry1 Entry2    <-- entries to process
    //      stack: [0, 0, 2]       <-- holds current iteration info at the following format:
    //                                 (start entry index at the auxiliary list (inclusive); current index; end index (exclusive))
    //    --------------------------
    //    Stage 2:
    //      list: Entry1 Entry2 Entry11 Entry12
    //      stack: [0, 1, 2]
    //             [2, 2, 4]
    //    --------------------------
    //    Stage 3:
    //      list: Entry1 Entry2 Entry11 Entry12
    //      stack: [0, 1, 2]
    //             [2, 3, 4]
    //    --------------------------
    //    Stage 4:
    //      list: Entry1 Entry2 Entry11 Entry12
    //      stack: [0, 1, 2]
    //             [2, 4, 4]
    //    --------------------------
    //      arrange 'Entry11 Entry12'
    //    --------------------------
    //    Stage 5:
    //      list: Entry1 Entry2 
    //      stack: [0, 1, 2]
    //    --------------------------
    //    Stage 6:
    //      list: Entry1 Entry2 Entry21 Entry22
    //      stack: [0, 2, 2]
    //             [2, 2, 4]
    //    --------------------------
    //    Stage 7:
    //      list: Entry1 Entry2 Entry21 Entry22
    //      stack: [0, 2, 2]
    //             [2, 3, 4]
    //    --------------------------
    //    Stage 8:
    //      list: Entry1 Entry2 Entry21 Entry22
    //      stack: [0, 2, 2]
    //             [2, 4, 4]
    //    --------------------------
    //      arrange 'Entry21 Entry22'
    //    --------------------------
    //    Stage 9:
    //      list: Entry1 Entry2
    //      stack: [0, 2, 2]
    //    --------------------------
    //      arrange 'Entry1 Entry2'

    List<ArrangementEntryWrapper<E>> entries = new ArrayList<ArrangementEntryWrapper<E>>();
    Stack<StackEntry> stack = new Stack<StackEntry>();
    entries.addAll(context.wrappers);
    stack.push(new StackEntry(0, context.wrappers.size()));
    while (!stack.isEmpty()) {
      StackEntry stackEntry = stack.peek();
      if (stackEntry.current >= stackEntry.end) {
        List<ArrangementEntryWrapper<E>> subEntries = entries.subList(stackEntry.start, stackEntry.end);
        // arrange entries even if subEntries.size() == 1, because we don't want to miss new section comments here
        doArrange(subEntries, context);
        subEntries.clear();
        stack.pop();
      }
      else {
        ArrangementEntryWrapper<E> wrapper = entries.get(stackEntry.current++);
        List<ArrangementEntryWrapper<E>> children = wrapper.getChildren();
        if (!children.isEmpty()) {
          entries.addAll(children);
          stack.push(new StackEntry(stackEntry.end, children.size()));
        }
      }
    }
  }

  /**
   * Arranges (re-orders) given entries according to the given rules.
   *
   * @param entries            entries to arrange
   * @param sectionRules       rules to use for arrangement
   * @param rulesByPriority    rules sorted by priority ('public static' rule will have higher priority than 'public')
   * @param entryToSection     mapping from arrangement entry to the parent section
   * @return                   arranged list of the given rules
   */
  @SuppressWarnings("AssignmentToForLoopParameter")
  @NotNull
  public static <E extends ArrangementEntry> List<E> arrange(@NotNull Collection<E> entries,
                                                             @NotNull List<ArrangementSectionRule> sectionRules,
                                                             @NotNull List<? extends ArrangementMatchRule> rulesByPriority,
                                                             @Nullable Map<E, ArrangementSectionRule> entryToSection)
  {
    List<E> arranged = ContainerUtilRt.newArrayList();
    Set<E> unprocessed = ContainerUtilRt.newLinkedHashSet();
    List<Pair<Set<ArrangementEntry>, E>> dependent = ContainerUtilRt.newArrayList();
    for (E entry : entries) {
      List<? extends ArrangementEntry> dependencies = entry.getDependencies();
      if (dependencies == null) {
        unprocessed.add(entry);
      }
      else {
        if (dependencies.size() == 1 && dependencies.get(0) == entry.getParent()) {
          // Handle a situation when the entry is configured to be at the first parent's children.
          arranged.add(entry);
        }
        else {
          Set<ArrangementEntry> first = new HashSet<ArrangementEntry>(dependencies);
          dependent.add(Pair.create(first, entry));
        }
      }
    }

    Set<E> matched = new HashSet<E>();

    MultiMap<ArrangementMatchRule, E> elementsByRule = new MultiMap<ArrangementMatchRule, E>();
    for (ArrangementMatchRule rule : rulesByPriority) {
      matched.clear();
      for (E entry : unprocessed) {
        if (entry.canBeMatched() && rule.getMatcher().isMatched(entry)) {
          elementsByRule.putValue(rule, entry);
          matched.add(entry);
        }
      }
      unprocessed.removeAll(matched);
    }

    for (ArrangementSectionRule sectionRule : sectionRules) {
      for (ArrangementMatchRule rule : sectionRule.getMatchRules()) {
        final Collection<E> arrangedEntries = arrangeByRule(arranged, elementsByRule, rule);

        if (entryToSection != null && arrangedEntries != null) {
          for (E entry : arrangedEntries) {
            entryToSection.put(entry, sectionRule);
          }
        }
      }
    }
    arranged.addAll(unprocessed);

    for (int i = 0; i < arranged.size() && !dependent.isEmpty(); i++) {
      E e = arranged.get(i);
      List<E> shouldBeAddedAfterCurrentElement = ContainerUtil.newArrayList();

      for (Iterator<Pair<Set<ArrangementEntry>, E>> iterator = dependent.iterator(); iterator.hasNext(); ) {
        Pair<Set<ArrangementEntry>, E> pair = iterator.next();
        pair.first.remove(e);
        if (pair.first.isEmpty()) {
          iterator.remove();
          shouldBeAddedAfterCurrentElement.add(pair.second);
        }
      }

      // add dependent entries to the same section as main entry
      if (entryToSection != null && entryToSection.containsKey(e)) {
        final ArrangementSectionRule rule = entryToSection.get(e);
        for (E e1 : shouldBeAddedAfterCurrentElement) {
          entryToSection.put(e1, rule);
        }
      }
      arranged.addAll(i + 1, shouldBeAddedAfterCurrentElement);
    }

    return arranged;
  }

  @Nullable
  private static <E extends ArrangementEntry> Collection<E> arrangeByRule(@NotNull List<E> arranged,
                                                                          @NotNull MultiMap<ArrangementMatchRule, E> elementsByRule,
                                                                          @NotNull ArrangementMatchRule rule) {
    if (elementsByRule.containsKey(rule)) {
      final Collection<E> arrangedEntries = elementsByRule.remove(rule);

      // Sort by name if necessary.
      if (StdArrangementTokens.Order.BY_NAME.equals(rule.getOrderType())) {
        sortByName((List<E>)arrangedEntries);
      }
      arranged.addAll(arrangedEntries);
      return arrangedEntries;
    }
    return null;
  }

  private static <E extends ArrangementEntry> void sortByName(@NotNull List<E> entries) {
    if (entries.size() < 2) {
      return;
    }
    final TObjectIntHashMap<E> weights = new TObjectIntHashMap<E>();
    int i = 0;
    for (E e : entries) {
      weights.put(e, ++i);
    }
    ContainerUtil.sort(entries, new Comparator<E>() {
      @Override
      public int compare(E e1, E e2) {
        String name1 = e1 instanceof NameAwareArrangementEntry ? ((NameAwareArrangementEntry)e1).getName() : null;
        String name2 = e2 instanceof NameAwareArrangementEntry ? ((NameAwareArrangementEntry)e2).getName() : null;
        if (name1 != null && name2 != null) {
          return name1.compareTo(name2);
        }
        else if (name1 == null && name2 == null) {
          return weights.get(e1) - weights.get(e2);
        }
        else if (name2 == null) {
          return -1;
        }
        else {
          return 1;
        }
      }
    });
  }

  @SuppressWarnings("unchecked")
  private static <E extends ArrangementEntry> void doArrange(@NotNull List<ArrangementEntryWrapper<E>> wrappers,
                                                             @NotNull Context<E> context) {
    if (wrappers.isEmpty()) {
      return;
    }

    Map<E, ArrangementSectionRule> entryToSection = ContainerUtilRt.newHashMap();
    Map<E, ArrangementEntryWrapper<E>> map = ContainerUtilRt.newHashMap();
    List<E> arranged = ContainerUtilRt.newArrayList();
    List<E> toArrange = ContainerUtilRt.newArrayList(); 
    for (ArrangementEntryWrapper<E> wrapper : wrappers) {
      E entry = wrapper.getEntry();
      map.put(wrapper.getEntry(), wrapper);
      if (!entry.canBeMatched()) {
        // Split entries to arrange by 'can not be matched' rules.
        // See IDEA-104046 for a problem use-case example.
        if (toArrange.isEmpty()) {
          arranged.addAll(arrange(toArrange, context.sectionRules, context.rulesByPriority, entryToSection));
        }
        arranged.add(entry);
        toArrange.clear();
      }
      else {
        toArrange.add(entry);
      }
    }
    if (!toArrange.isEmpty()) {
      arranged.addAll(arrange(toArrange, context.sectionRules, context.rulesByPriority, entryToSection));
    }

    final NewSectionInfo<E> newSectionsInfo = NewSectionInfo.create(arranged, entryToSection);
    context.changer.prepare(wrappers, context);
    // We apply changes from the last position to the first position in order not to bother with offsets shifts.
    for (int i = arranged.size() - 1; i >= 0; i--) {
      ArrangementEntryWrapper<E> arrangedWrapper = map.get(arranged.get(i));
      ArrangementEntryWrapper<E> initialWrapper = wrappers.get(i);

      ArrangementEntryWrapper<E> previous = i > 0 ? map.get(arranged.get(i - 1)) : null;
      ArrangementEntryWrapper<E> previousInitial = i > 0 ? wrappers.get(i - 1) : null;

      final ArrangementEntryWrapper<E> parentWrapper = initialWrapper.getParent();
      if (arrangedWrapper.equals(initialWrapper)) {
        if (previous != null && previous.equals(previousInitial) || previous == null && previousInitial == null) {
          final int beforeOffset = arrangedWrapper.getStartOffset();
          final int afterOffset = arrangedWrapper.getEndOffset();
          context.changer.insertSection(context, arranged.get(i), newSectionsInfo, parentWrapper, beforeOffset, afterOffset);
          continue;
        }
      }

      ArrangementEntryWrapper<E> next = i < arranged.size() - 1 ? map.get(arranged.get(i + 1)) : null;
      context.changer.replace(arrangedWrapper, initialWrapper, previous, next, context);
      context.changer.insertSection(context, arranged.get(i), newSectionsInfo, arrangedWrapper, initialWrapper, parentWrapper);
    }
  }

  private static class NewSectionInfo<E extends ArrangementEntry> {
    private final Map<E, String> mySectionStarts = ContainerUtil.newHashMap();
    private final Map<E, String> mySectionEnds = ContainerUtil.newHashMap();

    private static <E extends ArrangementEntry> NewSectionInfo create(@NotNull List<E> arranged,
                                                                      @NotNull Map<E, ArrangementSectionRule> entryToSection) {
      final NewSectionInfo<E> info = new NewSectionInfo<E>();

      boolean sectionIsOpen = false;
      ArrangementSectionRule prevSection = null;
      E prev = null;
      for (E e : arranged) {
        final ArrangementSectionRule section = entryToSection.get(e);
        if (section != prevSection) {
          closeSection(prevSection, prev, info, sectionIsOpen);
          sectionIsOpen = false;

          if (section != null) {
            final String startComment = section.getStartComment();
            if (StringUtil.isNotEmpty(startComment) && !isSectionEntry(e, startComment)) {
              sectionIsOpen = true;
              info.addSectionStart(e, startComment);
            }
          }
          prevSection = section;
        }
        prev = e;
      }

      closeSection(prevSection, prev, info, sectionIsOpen);
      return info;
    }

    public static boolean isSectionEntry(@NotNull ArrangementEntry entry, @NotNull String sectionText) {
      if (entry instanceof TypeAwareArrangementEntry && entry instanceof TextAwareArrangementEntry) {
        final Set<ArrangementSettingsToken> types = ((TypeAwareArrangementEntry)entry).getTypes();
        if (types.size() == 1) {
          final ArrangementSettingsToken type = types.iterator().next();
          if (type.equals(START_SECTION) || type.equals(END_SECTION)) {
            return StringUtil.equals(((TextAwareArrangementEntry)entry).getText(), sectionText);
          }
        }
      }
      return false;
    }

    private static <E extends ArrangementEntry> void closeSection(@Nullable ArrangementSectionRule section,
                                                                  @Nullable E entry,
                                                                  @NotNull NewSectionInfo<E> info,
                                                                  boolean sectionIsOpen) {
      if (sectionIsOpen) {
        assert section != null && entry != null;
        if (StringUtil.isNotEmpty(section.getEndComment())) {
          info.addSectionEnd(entry, section.getEndComment());
        }
      }
    }

    private void addSectionStart(E entry, String comment) {
      mySectionStarts.put(entry, comment);
    }

    private void addSectionEnd(E entry, String comment) {
      mySectionEnds.put(entry, comment);
    }

    @Nullable
    public String getStartComment(E entry) {
      return mySectionStarts.get(entry);
    }

    @Nullable
    public String getEndComment(E entry) {
      return mySectionEnds.get(entry);
    }
  }

  private static class Context<E extends ArrangementEntry> {

    @NotNull public final List<ArrangementMoveInfo> moveInfos = ContainerUtilRt.newArrayList();

    @NotNull public final Rearranger<E>                          rearranger;
    @NotNull public final Collection<ArrangementEntryWrapper<E>> wrappers;
    @NotNull public final Document                               document;
    @NotNull public final List<? extends ArrangementMatchRule>   rulesByPriority;
    @NotNull public final CodeStyleSettings                      settings;
    @NotNull public final Changer                                changer;
    @NotNull public final List<ArrangementSectionRule>           sectionRules;

    private Context(@NotNull Rearranger<E> rearranger,
                    @NotNull Collection<ArrangementEntryWrapper<E>> wrappers,
                    @NotNull Document document,
                    @NotNull List<ArrangementSectionRule> sectionRules,
                    @NotNull List<? extends ArrangementMatchRule> rulesByPriority,
                    @NotNull CodeStyleSettings settings, @NotNull Changer changer)
    {
      this.rearranger = rearranger;
      this.wrappers = wrappers;
      this.document = document;
      this.sectionRules = sectionRules;
      this.rulesByPriority = rulesByPriority;
      this.settings = settings;
      this.changer = changer;
    }

    public void addMoveInfo(int oldStart, int oldEnd, int newStart) {
      moveInfos.add(new ArrangementMoveInfo(oldStart, oldEnd, newStart));
    }
    
    public static <T extends ArrangementEntry> Context<T> from(@NotNull Rearranger<T> rearranger,
                                                               @NotNull Document document,
                                                               @NotNull PsiElement root,
                                                               @NotNull Collection<TextRange> ranges,
                                                               @NotNull ArrangementSettings arrangementSettings,
                                                               @NotNull CodeStyleSettings codeStyleSettings)
    {
      Collection<T> entries = rearranger.parse(root, document, ranges, arrangementSettings);
      Collection<ArrangementEntryWrapper<T>> wrappers = new ArrayList<ArrangementEntryWrapper<T>>();
      ArrangementEntryWrapper<T> previous = null;
      for (T entry : entries) {
        ArrangementEntryWrapper<T> wrapper = new ArrangementEntryWrapper<T>(entry);
        if (previous != null) {
          previous.setNext(wrapper);
          wrapper.setPrevious(previous);
        }
        wrappers.add(wrapper);
        previous = wrapper;
      }
      Changer changer;
      if (document instanceof DocumentEx) {
        changer = new RangeMarkerAwareChanger<T>((DocumentEx)document);
      }
      else {
        changer = new DefaultChanger();
      }
      final List<? extends ArrangementMatchRule> rulesByPriority = arrangementSettings.getRulesSortedByPriority();
      final List<ArrangementSectionRule> sectionRules = arrangementSettings.getSections();
      return new Context<T>(rearranger, wrappers, document, sectionRules, rulesByPriority, codeStyleSettings, changer);
    }
  }

  private static class StackEntry {

    public int start;
    public int current;
    public int end;

    StackEntry(int start, int count) {
      this.start = start;
      current = start;
      end = start + count;
    }
  }

  private abstract static class Changer<E extends ArrangementEntry> {
    public abstract void prepare(@NotNull List<ArrangementEntryWrapper<E>> toArrange, @NotNull Context<E> context);

    /**
     * Replaces given 'old entry' by the given 'new entry'.
     *
     * @param newWrapper  wrapper for an entry which text should replace given 'old entry' range
     * @param oldWrapper  wrapper for an entry which range should be replaced by the given 'new entry'
     * @param previous    wrapper which will be previous for the entry referenced via the given 'new wrapper'
     * @param next        wrapper which will be next for the entry referenced via the given 'new wrapper'
     * @param context     current context
     */
    public abstract void replace(@NotNull ArrangementEntryWrapper<E> newWrapper,
                                 @NotNull ArrangementEntryWrapper<E> oldWrapper,
                                 @Nullable ArrangementEntryWrapper<E> previous,
                                 @Nullable ArrangementEntryWrapper<E> next,
                                 @NotNull Context<E> context);

    public abstract void insert(@NotNull Context<E> context, int startOffset, @NotNull String text);

    public abstract void insertSection(@NotNull Context<E> context,
                                       @NotNull E entry,
                                       @NotNull NewSectionInfo<E> newSectionsInfo,
                                       @NotNull ArrangementEntryWrapper<E> arranged,
                                       @NotNull ArrangementEntryWrapper<E> initial,
                                       @Nullable ArrangementEntryWrapper<E> parent);

    protected abstract void insertSection(@NotNull Context<E> context,
                                          @NotNull E entry,
                                          @NotNull NewSectionInfo<E> newSectionsInfo,
                                          @Nullable ArrangementEntryWrapper<E> parent, int beforeOffset, int afterOffset);

    protected int getBlankLines(@NotNull Context<E> context,
                                @Nullable ArrangementEntryWrapper<E> parentWrapper,
                                @NotNull ArrangementEntryWrapper<E> targetWrapper,
                                @Nullable ArrangementEntryWrapper<E> previousWrapper,
                                @Nullable ArrangementEntryWrapper<E> nextWrapper) {
      final E target = targetWrapper.getEntry();
      final E previous = previousWrapper == null ? null : previousWrapper.getEntry();
      if (isTypeOf(target, END_SECTION) || isTypeOf(previous, START_SECTION)) {
        return 0;
      }
      final E next = nextWrapper == null ? null : nextWrapper.getEntry();
      if (next != null && isTypeOf(target, START_SECTION)) {
        return context.rearranger.getBlankLines(context.settings, parentWrapper == null ? null : parentWrapper.getEntry(), previous, next);
      }
      return context.rearranger.getBlankLines(context.settings, parentWrapper == null ? null : parentWrapper.getEntry(), previous, target);
    }

    private boolean isTypeOf(@Nullable E element, @NotNull ArrangementSettingsToken token) {
      if (element instanceof TypeAwareArrangementEntry) {
        Set<ArrangementSettingsToken> types = ((TypeAwareArrangementEntry)element).getTypes();
        return types.size() == 1 && token.equals(types.iterator().next());
      }
      return false;
    }
  }

  private static class DefaultChanger<E extends ArrangementEntry> extends Changer<E> {
    @NotNull private String myParentText;
    private          int    myParentShift;

    @Override
    public void prepare(@NotNull List<ArrangementEntryWrapper<E>> toArrange, @NotNull Context<E> context) {
      ArrangementEntryWrapper<E> parent = toArrange.get(0).getParent();
      if (parent == null) {
        myParentText = context.document.getText();
        myParentShift = 0;
      }
      else {
        myParentText = context.document.getCharsSequence().subSequence(parent.getStartOffset(), parent.getEndOffset()).toString();
        myParentShift = parent.getStartOffset();
      }
    }

    @SuppressWarnings("AssignmentToForLoopParameter")
    @Override
    public void replace(@NotNull ArrangementEntryWrapper<E> newWrapper,
                        @NotNull ArrangementEntryWrapper<E> oldWrapper,
                        @Nullable ArrangementEntryWrapper<E> previous,
                        @Nullable ArrangementEntryWrapper<E> next,
                        @NotNull Context<E> context)
    {
      // Calculate blank lines before the arrangement.
      int blankLinesBefore = 0;
      TIntArrayList lineFeedOffsets = new TIntArrayList();
      int oldStartLine = context.document.getLineNumber(oldWrapper.getStartOffset());
      if (oldStartLine > 0) {
        int lastLineFeed = context.document.getLineStartOffset(oldStartLine) - 1;
        lineFeedOffsets.add(lastLineFeed);
        for (int i = lastLineFeed - 1 - myParentShift; i >= 0; i--) {
          i = CharArrayUtil.shiftBackward(myParentText, i, " \t");
          if (myParentText.charAt(i) == '\n') {
            blankLinesBefore++;
            lineFeedOffsets.add(i + myParentShift);
          }
          else {
            break;
          }
        }
      }

      ArrangementEntryWrapper<E> parentWrapper = oldWrapper.getParent();
      int desiredBlankLinesNumber = getBlankLines(context, parentWrapper, newWrapper, previous, next);
      if (desiredBlankLinesNumber == blankLinesBefore && newWrapper.equals(oldWrapper)) {
        return;
      }

      String newEntryText = myParentText.substring(newWrapper.getStartOffset() - myParentShift, newWrapper.getEndOffset() - myParentShift);
      int lineFeedsDiff = desiredBlankLinesNumber - blankLinesBefore;
      if (lineFeedsDiff == 0 || desiredBlankLinesNumber < 0) {
        context.addMoveInfo(newWrapper.getStartOffset() - myParentShift,
                            newWrapper.getEndOffset() - myParentShift,
                            oldWrapper.getStartOffset());
        context.document.replaceString(oldWrapper.getStartOffset(), oldWrapper.getEndOffset(), newEntryText);
        return;
      }

      if (lineFeedsDiff > 0) {
        // Insert necessary number of blank lines.
        StringBuilder buffer = new StringBuilder(StringUtil.repeat("\n", lineFeedsDiff));
        buffer.append(newEntryText);
        context.document.replaceString(oldWrapper.getStartOffset(), oldWrapper.getEndOffset(), buffer);
      }
      else {
        // Cut exceeding blank lines.
        int replacementStartOffset = lineFeedOffsets.get(-lineFeedsDiff) + 1;
        context.document.replaceString(replacementStartOffset, oldWrapper.getEndOffset(), newEntryText);
      }

      // Update wrapper ranges.
      ArrangementEntryWrapper<E> parent = oldWrapper.getParent();
      if (parent == null) {
        return;
      }

      Deque<ArrangementEntryWrapper<E>> parents = new ArrayDeque<ArrangementEntryWrapper<E>>();
      do {
        parents.add(parent);
        parent.setEndOffset(parent.getEndOffset() + lineFeedsDiff);
        parent = parent.getParent();
      }
      while (parent != null);


      while (!parents.isEmpty()) {

        for (ArrangementEntryWrapper<E> wrapper = parents.removeLast().getNext(); wrapper != null; wrapper = wrapper.getNext()) {
          wrapper.applyShift(lineFeedsDiff);
        }
      }
    }

    @Override
    public void insert(@NotNull Context<E> context, int startOffset, @NotNull String text) {
      context.document.insertString(startOffset, text);
    }

    @Override
    public void insertSection(@NotNull Context<E> context,
                              @NotNull E entry,
                              @NotNull NewSectionInfo<E> newSectionsInfo,
                              @NotNull ArrangementEntryWrapper<E> arrangedWrapper,
                              @NotNull ArrangementEntryWrapper<E> initialWrapper,
                              @Nullable ArrangementEntryWrapper<E> parent) {
      final int beforeOffset = arrangedWrapper.equals(initialWrapper) ? arrangedWrapper.getStartOffset() : initialWrapper.getStartOffset();
      final int length = arrangedWrapper.getEndOffset() - arrangedWrapper.getStartOffset();
      int afterOffset = arrangedWrapper.equals(initialWrapper) ? arrangedWrapper.getEndOffset() : beforeOffset + length;

      insertSection(context, entry, newSectionsInfo, parent, beforeOffset, afterOffset);
    }

    @Override
    protected void insertSection(@NotNull Context<E> context,
                                 @NotNull E entry,
                                 @NotNull NewSectionInfo<E> newSectionsInfo,
                                 ArrangementEntryWrapper<E> parent, int beforeOffset, int afterOffset) {
      final String afterComment = newSectionsInfo.getEndComment(entry);
      if (afterComment != null) {
        insert(context, afterOffset, "\n" + afterComment);
      }
      final String beforeComment = newSectionsInfo.getStartComment(entry);
      if (beforeComment != null) {
        insert(context, beforeOffset, beforeComment + "\n");
      }
    }
  }

  private static class RangeMarkerAwareChanger<E extends ArrangementEntry> extends Changer<E> {

    @NotNull private final List<ArrangementEntryWrapper<E>> myWrappers = new ArrayList<ArrangementEntryWrapper<E>>();
    @NotNull private final DocumentEx myDocument;

    RangeMarkerAwareChanger(@NotNull DocumentEx document) {
      myDocument = document;
    }

    @Override
    public void prepare(@NotNull List<ArrangementEntryWrapper<E>> toArrange, @NotNull Context<E> context) {
      myWrappers.clear();
      myWrappers.addAll(toArrange);
      for (ArrangementEntryWrapper<E> wrapper : toArrange) {
        wrapper.updateBlankLines(myDocument);
      }
    }

    @SuppressWarnings("AssignmentToForLoopParameter")
    @Override
    public void replace(@NotNull ArrangementEntryWrapper<E> newWrapper,
                        @NotNull ArrangementEntryWrapper<E> oldWrapper,
                        @Nullable ArrangementEntryWrapper<E> previous,
                        @Nullable ArrangementEntryWrapper<E> next,
                        @NotNull Context<E> context)
    {
      // Calculate blank lines before the arrangement.
      int blankLinesBefore = oldWrapper.getBlankLinesBefore();

      ArrangementEntryWrapper<E> parentWrapper = oldWrapper.getParent();
      int desiredBlankLinesNumber = getBlankLines(context, parentWrapper, newWrapper, previous, next);
      if ((desiredBlankLinesNumber < 0 || desiredBlankLinesNumber == blankLinesBefore) && newWrapper.equals(oldWrapper)) {
        return;
      }

      int lineFeedsDiff = desiredBlankLinesNumber - blankLinesBefore;
      int insertionOffset = oldWrapper.getStartOffset();
      if (oldWrapper.getStartOffset() > newWrapper.getStartOffset()) {
        insertionOffset -= newWrapper.getEndOffset() - newWrapper.getStartOffset();
      }
      if (newWrapper.getStartOffset() != oldWrapper.getStartOffset() || !newWrapper.equals(oldWrapper)) {
        context.addMoveInfo(newWrapper.getStartOffset(), newWrapper.getEndOffset(), oldWrapper.getStartOffset());
        myDocument.moveText(newWrapper.getStartOffset(), newWrapper.getEndOffset(), oldWrapper.getStartOffset());
        for (int i = myWrappers.size() - 1; i >= 0; i--) {
          ArrangementEntryWrapper<E> w = myWrappers.get(i);
          if (w == newWrapper) {
            continue;
          }
          if (w.getStartOffset() >= oldWrapper.getStartOffset() && w.getStartOffset() < newWrapper.getStartOffset()) {
            w.applyShift(newWrapper.getEndOffset() - newWrapper.getStartOffset());
          }
          else if (oldWrapper != w && w.getStartOffset() <= oldWrapper.getStartOffset() &&
                   w.getStartOffset() > newWrapper.getStartOffset()) {
            w.applyShift(newWrapper.getStartOffset() - newWrapper.getEndOffset());
          }
        }
      }

      if (desiredBlankLinesNumber >= 0 && lineFeedsDiff > 0) {
        myDocument.insertString(insertionOffset, StringUtil.repeat("\n", lineFeedsDiff));
        shiftOffsets(lineFeedsDiff, insertionOffset);
      }

      if (desiredBlankLinesNumber >= 0 && lineFeedsDiff < 0) {
        // Cut exceeding blank lines.
        int replacementStartOffset = getBlankLineOffset(-lineFeedsDiff, insertionOffset);
        myDocument.deleteString(replacementStartOffset, insertionOffset);
        shiftOffsets(replacementStartOffset - insertionOffset, insertionOffset);
      }

      if (desiredBlankLinesNumber < 0) {
        return;
      }

      updateAllWrapperRanges(parentWrapper, lineFeedsDiff);
    }

    protected void updateAllWrapperRanges(@Nullable ArrangementEntryWrapper<E> parentWrapper, int lineFeedsDiff) {
      // Update wrapper ranges.
      if (lineFeedsDiff == 0 || parentWrapper == null) {
        return;
      }

      Deque<ArrangementEntryWrapper<E>> parents = new ArrayDeque<ArrangementEntryWrapper<E>>();
      do {
        parents.add(parentWrapper);
        parentWrapper.setEndOffset(parentWrapper.getEndOffset() + lineFeedsDiff);
        parentWrapper = parentWrapper.getParent();
      }
      while (parentWrapper != null);


      while (!parents.isEmpty()) {
        for (ArrangementEntryWrapper<E> wrapper = parents.removeLast().getNext(); wrapper != null; wrapper = wrapper.getNext()) {
          wrapper.applyShift(lineFeedsDiff);
        }
      }
    }

    @Override
    public void insert(@NotNull Context<E> context, int startOffset, @NotNull String text) {
      myDocument.insertString(startOffset, text);
      int shift = text.length();
      for (int i = myWrappers.size() - 1; i >= 0; i--) {
        ArrangementEntryWrapper<E> wrapper = myWrappers.get(i);
        if (wrapper.getStartOffset() >= startOffset) {
          wrapper.applyShift(shift);
        }
      }
    }

    @Override
    public void insertSection(@NotNull Context<E> context,
                              @NotNull E entry,
                              @NotNull NewSectionInfo<E> newSectionsInfo,
                              @NotNull ArrangementEntryWrapper<E> arrangedWrapper,
                              @NotNull ArrangementEntryWrapper<E> initialWrapper,
                              @Nullable ArrangementEntryWrapper<E> parent) {
      final int afterOffset = arrangedWrapper.equals(initialWrapper) ? arrangedWrapper.getEndOffset() : initialWrapper.getStartOffset();
      final int length = arrangedWrapper.getEndOffset() - arrangedWrapper.getStartOffset();
      final int beforeOffset = arrangedWrapper.equals(initialWrapper) ? arrangedWrapper.getStartOffset() : afterOffset - length;
      insertSection(context, entry, newSectionsInfo, parent, beforeOffset, afterOffset);
    }

    @Override
    protected void insertSection(@NotNull Context<E> context,
                                 @NotNull E entry,
                                 @NotNull NewSectionInfo<E> newSectionsInfo,
                                 @Nullable ArrangementEntryWrapper<E> parent,
                                 int beforeOffset, int afterOffset) {
      int diff = 0;
      final String afterComment = newSectionsInfo.getEndComment(entry);
      if (afterComment != null) {
        insert(context, afterOffset, "\n" + afterComment);
        diff += afterComment.length() + 1;
      }
      final String beforeComment = newSectionsInfo.getStartComment(entry);
      if (beforeComment != null) {
        insert(context, beforeOffset, beforeComment + "\n");
        diff += beforeComment.length() + 1;
      }

      updateAllWrapperRanges(parent, diff);
    }

    /**
     * @return position <code>x</code> for which <code>myDocument.getText().substring(x, startOffset)</code> contains
     * <code>blankLinesNumber</code> line feeds and <code>myDocument.getText.charAt(x-1) == '\n'</code>
     */
    private int getBlankLineOffset(int blankLinesNumber, int startOffset) {
      int startLine = myDocument.getLineNumber(startOffset);
      if (startLine <= 0) {
        return 0;
      }
      CharSequence text = myDocument.getCharsSequence();
      for (int i = myDocument.getLineStartOffset(startLine - 1) - 1; i >= 0; i = CharArrayUtil.lastIndexOf(text, "\n", i - 1)) {
        if (--blankLinesNumber <= 0) {
          return i + 1;
        }
      }
      return 0;
    }

    private void shiftOffsets(int shift, int changeOffset) {
      for (int i = myWrappers.size() - 1; i >= 0; i--) {
        ArrangementEntryWrapper<E> wrapper = myWrappers.get(i);
        if (wrapper.getStartOffset() < changeOffset) {
          break;
        }
        wrapper.applyShift(shift);
      }
    }
  }
}
