/*
 * Copyright 2000-2014 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.formatting;

import com.intellij.lang.ASTNode;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.TextRange;
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.CommonCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.formatter.FormattingDocumentModelImpl;
import com.intellij.psi.formatter.PsiBasedFormattingModel;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SequentialTask;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

public class FormatterImpl extends FormatterEx
  implements IndentFactory,
             WrapFactory,
             AlignmentFactory,
             SpacingFactory,
             FormattingModelFactory {
  private static final Logger LOG = Logger.getInstance("#com.intellij.formatting.FormatterImpl");

  private final AtomicReference<FormattingProgressTask> myProgressTask = new AtomicReference<FormattingProgressTask>();

  private final AtomicInteger myIsDisabledCount = new AtomicInteger();
  private final IndentImpl NONE_INDENT = new IndentImpl(Indent.Type.NONE, false, false);
  private final IndentImpl myAbsoluteNoneIndent = new IndentImpl(Indent.Type.NONE, true, false);
  private final IndentImpl myLabelIndent = new IndentImpl(Indent.Type.LABEL, false, false);
  private final IndentImpl myContinuationIndentRelativeToDirectParent = new IndentImpl(Indent.Type.CONTINUATION, false, true);
  private final IndentImpl myContinuationIndentNotRelativeToDirectParent = new IndentImpl(Indent.Type.CONTINUATION, false, false);
  private final IndentImpl myContinuationWithoutFirstIndentRelativeToDirectParent
    = new IndentImpl(Indent.Type.CONTINUATION_WITHOUT_FIRST, false, true);
  private final IndentImpl myContinuationWithoutFirstIndentNotRelativeToDirectParent
    = new IndentImpl(Indent.Type.CONTINUATION_WITHOUT_FIRST, false, false);
  private final IndentImpl myAbsoluteLabelIndent = new IndentImpl(Indent.Type.LABEL, true, false);
  private final IndentImpl myNormalIndentRelativeToDirectParent = new IndentImpl(Indent.Type.NORMAL, false, true);
  private final IndentImpl myNormalIndentNotRelativeToDirectParent = new IndentImpl(Indent.Type.NORMAL, false, false);
  private final SpacingImpl myReadOnlySpacing = new SpacingImpl(0, 0, 0, true, false, true, 0, false, 0);

  public FormatterImpl() {
    Indent.setFactory(this);
    Wrap.setFactory(this);
    Alignment.setFactory(this);
    Spacing.setFactory(this);
    FormattingModelProvider.setFactory(this);
  }

  @Override
  public Alignment createAlignment(boolean applyToNonFirstBlocksOnLine, @NotNull Alignment.Anchor anchor) {
    return new AlignmentImpl(applyToNonFirstBlocksOnLine, anchor);
  }

  @Override
  public Alignment createChildAlignment(final Alignment base) {
    AlignmentImpl result = new AlignmentImpl();
    result.setParent(base);
    return result;
  }

  @Override
  public Indent getNormalIndent(boolean relative) {
    return relative ? myNormalIndentRelativeToDirectParent : myNormalIndentNotRelativeToDirectParent;
  }

  @Override
  public Indent getNoneIndent() {
    return NONE_INDENT;
  }

  @Override
  public void setProgressTask(@NotNull FormattingProgressTask progressIndicator) {
    if (!FormatterUtil.isFormatterCalledExplicitly()) {
      return;
    }
    myProgressTask.set(progressIndicator);
  }

  @Override
  public int getSpacingForBlockAtOffset(FormattingModel model, int offset) {
    Couple<Block> blockWithParent = getBlockAtOffset(null, model.getRootBlock(), offset);
    if (blockWithParent != null) {
      Block parentBlock = blockWithParent.first;
      Block targetBlock = blockWithParent.second;
      if (parentBlock != null && targetBlock != null) {
        Block prevBlock = findPreviousSibling(parentBlock, targetBlock);
        if (prevBlock != null) {
          SpacingImpl spacing = (SpacingImpl)parentBlock.getSpacing(prevBlock, targetBlock);
          if (spacing != null) {
            int minSpaces = spacing.getMinSpaces();
            if (minSpaces > 0) {
              return minSpaces;
            }
          }
        }
      }
    }
    return 0;
  }

  @Nullable
  private static Couple<Block> getBlockAtOffset(@Nullable Block parent, @NotNull Block block, int offset) {
    TextRange textRange = block.getTextRange();
    int startOffset = textRange.getStartOffset();
    int endOffset = textRange.getEndOffset();
    if (startOffset == offset) {
      return Couple.of(parent, block);
    }
    if (startOffset > offset || endOffset < offset || block.isLeaf()) {
      return null;
    }
    for (Block subBlock : block.getSubBlocks()) {
      Couple<Block> result = getBlockAtOffset(block, subBlock, offset);
      if (result != null) {
        return result;
      }
    }
    return null;
  }

  @Nullable
  private static Block findPreviousSibling(@NotNull Block parent, Block block) {
    Block result = null;
    for (Block subBlock : parent.getSubBlocks()) {
      if (subBlock == block) {
        return result;
      }
      result = subBlock;
    }
    return null;
  }

  @Override
  public void format(final FormattingModel model, final CodeStyleSettings settings,
                     final CommonCodeStyleSettings.IndentOptions indentOptions,
                     final CommonCodeStyleSettings.IndentOptions javaIndentOptions,
                     final FormatTextRanges affectedRanges) throws IncorrectOperationException
  {
    try {
      validateModel(model);
      SequentialTask task = new MyFormattingTask() {
        @NotNull
        @Override
        protected FormatProcessor buildProcessor() {
          FormatProcessor processor = new FormatProcessor(
            model.getDocumentModel(), model.getRootBlock(), settings, indentOptions, affectedRanges, FormattingProgressCallback.EMPTY
          );
          processor.setJavaIndentOptions(javaIndentOptions);

          processor.format(model);
          return processor;
        }
      };
      execute(task);
    }
    catch (FormattingModelInconsistencyException e) {
      LOG.error(e);
    }
  }

  @Override
  public Wrap createWrap(WrapType type, boolean wrapFirstElement) {
    return new WrapImpl(type, wrapFirstElement);
  }

  @Override
  public Wrap createChildWrap(final Wrap parentWrap, final WrapType wrapType, final boolean wrapFirstElement) {
    final WrapImpl result = new WrapImpl(wrapType, wrapFirstElement);
    result.registerParent((WrapImpl)parentWrap);
    return result;
  }

  @Override
  @NotNull
  public Spacing createSpacing(int minOffset,
                               int maxOffset,
                               int minLineFeeds,
                               final boolean keepLineBreaks,
                               final int keepBlankLines) {
    return getSpacingImpl(minOffset, maxOffset, minLineFeeds, false, false, keepLineBreaks, keepBlankLines,false, 0);
  }

  @Override
  @NotNull
  public Spacing getReadOnlySpacing() {
    return myReadOnlySpacing;
  }

  @NotNull
  @Override
  public Spacing createDependentLFSpacing(int minSpaces,
                                          int maxSpaces,
                                          @NotNull TextRange dependencyRange,
                                          boolean keepLineBreaks,
                                          int keepBlankLines,
                                          @NotNull DependentSpacingRule rule)
  {
    return new DependantSpacingImpl(minSpaces, maxSpaces, dependencyRange, keepLineBreaks, keepBlankLines, rule);
  }

  @NotNull
  private FormattingProgressCallback getProgressCallback() {
    FormattingProgressCallback result = myProgressTask.get();
    return result == null ? FormattingProgressCallback.EMPTY : result;
  }

  @Override
  public void format(final FormattingModel model,
                     final CodeStyleSettings settings,
                     final CommonCodeStyleSettings.IndentOptions indentOptions,
                     final FormatTextRanges affectedRanges) throws IncorrectOperationException {
    try {
      validateModel(model);
      SequentialTask task = new MyFormattingTask() {
        @NotNull
        @Override
        protected FormatProcessor buildProcessor() {
          FormatProcessor processor = new FormatProcessor(
            model.getDocumentModel(), model.getRootBlock(), settings, indentOptions, affectedRanges, getProgressCallback()
          );
          processor.format(model, true);
          return processor;
        }
      };
      execute(task);
    }
    catch (FormattingModelInconsistencyException e) {
      LOG.error(e);
    }
  }

  public void formatWithoutModifications(final FormattingDocumentModel model,
                                         final Block rootBlock,
                                         final CodeStyleSettings settings,
                                         final CommonCodeStyleSettings.IndentOptions indentOptions,
                                         final TextRange affectedRange) throws IncorrectOperationException
  {
    SequentialTask task = new MyFormattingTask() {
      @NotNull
      @Override
      protected FormatProcessor buildProcessor() {
        FormatProcessor result = new FormatProcessor(
          model, rootBlock, settings, indentOptions, new FormatTextRanges(affectedRange, true), FormattingProgressCallback.EMPTY
        );
        result.formatWithoutRealModifications();
        return result;
      }
    };
    execute(task);
  }

  /**
   * Execute given sequential formatting task. Two approaches are possible:
   * <pre>
   * <ul>
   *   <li>
   *      <b>synchronous</b> - the task is completely executed during the current method processing;
   *   </li>
   *   <li>
   *       <b>asynchronous</b> - the task is executed at background thread under the progress dialog;
   *   </li>
   * </ul>
   * </pre>
   *
   * @param task    task to execute
   */
  private void execute(@NotNull SequentialTask task) {
    disableFormatting();
    Application application = ApplicationManager.getApplication();
    FormattingProgressTask progressTask = myProgressTask.getAndSet(null);
    if (progressTask == null || !application.isDispatchThread() || application.isUnitTestMode()) {
      try {
        task.prepare();
        while (!task.isDone()) {
          task.iteration();
        }
      }
      finally {
        enableFormatting();
      }
    }
    else {
      progressTask.setTask(task);
      Runnable callback = new Runnable() {
        @Override
        public void run() {
          enableFormatting();
        }
      };
      for (FormattingProgressCallback.EventType eventType : FormattingProgressCallback.EventType.values()) {
        progressTask.addCallback(eventType, callback);
      }
      ProgressManager.getInstance().run(progressTask);
    }
  }

  @Override
  public IndentInfo getWhiteSpaceBefore(final FormattingDocumentModel model,
                                        final Block block,
                                        final CodeStyleSettings settings,
                                        final CommonCodeStyleSettings.IndentOptions indentOptions,
                                        final TextRange affectedRange, final boolean mayChangeLineFeeds)
  {
    disableFormatting();
    try {
      final FormatProcessor processor = buildProcessorAndWrapBlocks(
        model, block, settings, indentOptions, new FormatTextRanges(affectedRange, true)
      );
      final LeafBlockWrapper blockBefore = processor.getBlockAfter(affectedRange.getStartOffset());
      LOG.assertTrue(blockBefore != null);
      WhiteSpace whiteSpace = blockBefore.getWhiteSpace();
      LOG.assertTrue(whiteSpace != null);
      if (!mayChangeLineFeeds) {
        whiteSpace.setLineFeedsAreReadOnly();
      }
      processor.setAllWhiteSpacesAreReadOnly();
      whiteSpace.setReadOnly(false);
      processor.formatWithoutRealModifications();
      return new IndentInfo(whiteSpace.getLineFeeds(), whiteSpace.getIndentOffset(), whiteSpace.getSpaces());
    }
    finally {
      enableFormatting();
    }
  }

  @Override
  public void adjustLineIndentsForRange(final FormattingModel model,
                                        final CodeStyleSettings settings,
                                        final CommonCodeStyleSettings.IndentOptions indentOptions,
                                        final TextRange rangeToAdjust) {
    disableFormatting();
    try {
      validateModel(model);
      final FormattingDocumentModel documentModel = model.getDocumentModel();
      final Block block = model.getRootBlock();
      final FormatProcessor processor = buildProcessorAndWrapBlocks(
        documentModel, block, settings, indentOptions, new FormatTextRanges(rangeToAdjust, true)
      );
      LeafBlockWrapper tokenBlock = processor.getFirstTokenBlock();
      while (tokenBlock != null) {
        final WhiteSpace whiteSpace = tokenBlock.getWhiteSpace();
        whiteSpace.setLineFeedsAreReadOnly(true);
        if (!whiteSpace.containsLineFeeds()) {
          whiteSpace.setIsReadOnly(true);
        }
        tokenBlock = tokenBlock.getNextBlock();
      }
      processor.formatWithoutRealModifications();
      processor.performModifications(model);
    }
    catch (FormattingModelInconsistencyException e) {
      LOG.error(e);
    }
    finally {
      enableFormatting();
    }
  }

  @Override
  public void formatAroundRange(final FormattingModel model,
                                final CodeStyleSettings settings,
                                final TextRange textRange,
                                final FileType fileType) {
    disableFormatting();
    try {
      validateModel(model);
      final FormattingDocumentModel documentModel = model.getDocumentModel();
      final Block block = model.getRootBlock();
      final FormatProcessor processor = buildProcessorAndWrapBlocks(
        documentModel, block, settings, settings.getIndentOptions(fileType), null
      );
      LeafBlockWrapper tokenBlock = processor.getFirstTokenBlock();
      while (tokenBlock != null) {
        final WhiteSpace whiteSpace = tokenBlock.getWhiteSpace();

        if (whiteSpace.getEndOffset() < textRange.getStartOffset() || whiteSpace.getEndOffset() > textRange.getEndOffset() + 1) {
          whiteSpace.setIsReadOnly(true);
        } else if (whiteSpace.getStartOffset() > textRange.getStartOffset() &&
                   whiteSpace.getEndOffset() < textRange.getEndOffset())
        {
          if (whiteSpace.containsLineFeeds()) {
            whiteSpace.setLineFeedsAreReadOnly(true);
          } else {
            whiteSpace.setIsReadOnly(true);
          }
        }

        tokenBlock = tokenBlock.getNextBlock();
      }
      processor.formatWithoutRealModifications();
      processor.performModifications(model);
    }
    catch (FormattingModelInconsistencyException e) {
      LOG.error(e);
    }
    finally{
      enableFormatting();
    }
  }

  @Override
  public int adjustLineIndent(final FormattingModel model,
                              final CodeStyleSettings settings,
                              final CommonCodeStyleSettings.IndentOptions indentOptions,
                              final int offset,
                              final TextRange affectedRange) throws IncorrectOperationException {
    disableFormatting();
    try {
      validateModel(model);
      if (model instanceof PsiBasedFormattingModel) {
        ((PsiBasedFormattingModel)model).canModifyAllWhiteSpaces();
      }
      final FormattingDocumentModel documentModel = model.getDocumentModel();
      final Block block = model.getRootBlock();
      final FormatProcessor processor = buildProcessorAndWrapBlocks(
        documentModel, block, settings, indentOptions, new FormatTextRanges(affectedRange, true), offset
      );

      final LeafBlockWrapper blockAfterOffset = processor.getBlockAfter(offset);

      if (blockAfterOffset != null && blockAfterOffset.contains(offset)) {
        return offset;
      }

      WhiteSpace whiteSpace = blockAfterOffset != null ? blockAfterOffset.getWhiteSpace() : processor.getLastWhiteSpace();
      return adjustLineIndent(offset, documentModel, processor, indentOptions, model, whiteSpace,
                              blockAfterOffset != null ? blockAfterOffset.getNode() : null);
    }
    catch (FormattingModelInconsistencyException e) {
      LOG.error(e);
    }
    finally {
      enableFormatting();
    }
    return offset;
  }

  /**
   * Delegates to
   * {@link #buildProcessorAndWrapBlocks(FormattingDocumentModel, Block, CodeStyleSettings, CommonCodeStyleSettings.IndentOptions, FormatTextRanges, int)}
   * with '-1' as an interested offset.
   *
   * @param docModel
   * @param rootBlock
   * @param settings
   * @param indentOptions
   * @param affectedRanges
   * @return
   */
  private static FormatProcessor buildProcessorAndWrapBlocks(final FormattingDocumentModel docModel,
                                                             Block rootBlock,
                                                             CodeStyleSettings settings,
                                                             CommonCodeStyleSettings.IndentOptions indentOptions,
                                                             @Nullable FormatTextRanges affectedRanges)
  {
    return buildProcessorAndWrapBlocks(docModel, rootBlock, settings, indentOptions, affectedRanges, -1);
  }

  /**
   * Builds {@link FormatProcessor} instance and asks it to wrap all {@link Block code blocks}
   * {@link FormattingModel#getRootBlock() derived from the given model}.
   *
   * @param docModel            target model
   * @param rootBlock           root block to process
   * @param settings            code style settings to use
   * @param indentOptions       indent options to use
   * @param affectedRanges      ranges to reformat
   * @param interestingOffset   interesting offset; <code>'-1'</code> if no particular offset has a special interest
   * @return                    format processor instance with wrapped {@link Block code blocks}
   */
  @SuppressWarnings({"StatementWithEmptyBody"})
  private static FormatProcessor buildProcessorAndWrapBlocks(final FormattingDocumentModel docModel,
                                                             Block rootBlock,
                                                             CodeStyleSettings settings,
                                                             CommonCodeStyleSettings.IndentOptions indentOptions,
                                                             @Nullable FormatTextRanges affectedRanges,
                                                             int interestingOffset)
  {
    FormatProcessor processor = new FormatProcessor(
      docModel, rootBlock, settings, indentOptions, affectedRanges, interestingOffset, FormattingProgressCallback.EMPTY
    );
    while (!processor.iteration()) ;
    return processor;
  }

  private static int adjustLineIndent(
    final int offset,
    final FormattingDocumentModel documentModel,
    final FormatProcessor processor,
    final CommonCodeStyleSettings.IndentOptions indentOptions,
    final FormattingModel model,
    final WhiteSpace whiteSpace,
    ASTNode nodeAfter)
  {
    boolean wsContainsCaret = whiteSpace.getStartOffset() <= offset && offset < whiteSpace.getEndOffset();

    int lineStartOffset = getLineStartOffset(offset, whiteSpace, documentModel);

    final IndentInfo indent = calcIndent(offset, documentModel, processor, whiteSpace);

    final String newWS = whiteSpace.generateWhiteSpace(indentOptions, lineStartOffset, indent).toString();
    if (!whiteSpace.equalsToString(newWS)) {
      try {
        if (model instanceof FormattingModelEx) {
          ((FormattingModelEx) model).replaceWhiteSpace(whiteSpace.getTextRange(), nodeAfter, newWS);
        }
        else {
          model.replaceWhiteSpace(whiteSpace.getTextRange(), newWS);
        }
      }
      finally {
        model.commitChanges();
      }
    }

    final int defaultOffset = offset - whiteSpace.getLength() + newWS.length();

    if (wsContainsCaret) {
      final int ws = whiteSpace.getStartOffset()
                     + CharArrayUtil.shiftForward(newWS, Math.max(0, lineStartOffset - whiteSpace.getStartOffset()), " \t");
      return Math.max(defaultOffset, ws);
    } else {
      return defaultOffset;
    }
  }

  private static boolean hasContentAfterLineBreak(final FormattingDocumentModel documentModel, final int offset, final WhiteSpace whiteSpace) {
    return documentModel.getLineNumber(offset) == documentModel.getLineNumber(whiteSpace.getEndOffset()) &&
           documentModel.getTextLength() != offset;
  }

  @Override
  public String getLineIndent(final FormattingModel model,
                              final CodeStyleSettings settings,
                              final CommonCodeStyleSettings.IndentOptions indentOptions,
                              final int offset,
                              final TextRange affectedRange) {
    final FormattingDocumentModel documentModel = model.getDocumentModel();
    final Block block = model.getRootBlock();
    if (block.getTextRange().isEmpty()) return null; // handing empty document case
    final FormatProcessor processor = buildProcessorAndWrapBlocks(
      documentModel, block, settings, indentOptions, new FormatTextRanges(affectedRange, true), offset
    );
    final LeafBlockWrapper blockAfterOffset = processor.getBlockAfter(offset);

    if (blockAfterOffset != null) {
      final WhiteSpace whiteSpace = blockAfterOffset.getWhiteSpace();
      final IndentInfo indent = calcIndent(offset, documentModel, processor, whiteSpace);

      return indent.generateNewWhiteSpace(indentOptions);
    }
    return null;
  }

  private static IndentInfo calcIndent(int offset, FormattingDocumentModel documentModel, FormatProcessor processor, WhiteSpace whiteSpace) {
    processor.setAllWhiteSpacesAreReadOnly();
    whiteSpace.setLineFeedsAreReadOnly(true);
    final IndentInfo indent;
    if (hasContentAfterLineBreak(documentModel, offset, whiteSpace)) {
      whiteSpace.setReadOnly(false);
      processor.formatWithoutRealModifications();
      indent = new IndentInfo(0, whiteSpace.getIndentOffset(), whiteSpace.getSpaces());
    }
    else {
      indent = processor.getIndentAt(offset);
    }
    return indent;
  }

  public static String getText(final FormattingDocumentModel documentModel) {
    return getCharSequence(documentModel).toString();
  }

  private static CharSequence getCharSequence(final FormattingDocumentModel documentModel) {
    return documentModel.getText(new TextRange(0, documentModel.getTextLength()));
  }

  private static int getLineStartOffset(final int offset,
                                        final WhiteSpace whiteSpace,
                                        final FormattingDocumentModel documentModel) {
    int lineStartOffset = offset;

    CharSequence text = getCharSequence(documentModel);
    lineStartOffset = CharArrayUtil.shiftBackwardUntil(text, lineStartOffset, " \t\n");
    if (lineStartOffset > whiteSpace.getStartOffset()) {
      if (lineStartOffset >= text.length()) lineStartOffset = text.length() - 1;
      final int wsStart = whiteSpace.getStartOffset();
      int prevEnd;

      if (text.charAt(lineStartOffset) == '\n'
          && wsStart <= (prevEnd = documentModel.getLineStartOffset(documentModel.getLineNumber(lineStartOffset - 1))) &&
          documentModel.getText(new TextRange(prevEnd, lineStartOffset)).toString().trim().length() == 0 // ws consists of space only, it is not true for <![CDATA[
         ) {
        lineStartOffset--;
      }
      lineStartOffset = CharArrayUtil.shiftBackward(text, lineStartOffset, "\t ");
      if (lineStartOffset < 0) lineStartOffset = 0;
      if (lineStartOffset != offset && text.charAt(lineStartOffset) == '\n') {
        lineStartOffset++;
      }
    }
    return lineStartOffset;
  }

  @Override
  public void adjustTextRange(final FormattingModel model,
                              final CodeStyleSettings settings,
                              final CommonCodeStyleSettings.IndentOptions indentOptions,
                              final TextRange affectedRange,
                              final boolean keepBlankLines,
                              final boolean keepLineBreaks,
                              final boolean changeWSBeforeFirstElement,
                              final boolean changeLineFeedsBeforeFirstElement,
                              @Nullable final IndentInfoStorage indentInfoStorage) {
    disableFormatting();
    try {
      validateModel(model);
      final FormatProcessor processor = buildProcessorAndWrapBlocks(
        model.getDocumentModel(), model.getRootBlock(), settings, indentOptions, new FormatTextRanges(affectedRange, true)
      );
      LeafBlockWrapper current = processor.getFirstTokenBlock();
      while (current != null) {
        WhiteSpace whiteSpace = current.getWhiteSpace();

        if (!whiteSpace.isReadOnly()) {
          if (whiteSpace.getStartOffset() > affectedRange.getStartOffset()) {
            if (whiteSpace.containsLineFeeds() && indentInfoStorage != null) {
              whiteSpace.setLineFeedsAreReadOnly(true);
              current.setIndentFromParent(indentInfoStorage.getIndentInfo(current.getStartOffset()));
            }
            else {
              whiteSpace.setReadOnly(true);
            }
          }
          else {
            if (!changeWSBeforeFirstElement) {
              whiteSpace.setReadOnly(true);
            }
            else {
              if (!changeLineFeedsBeforeFirstElement) {
                whiteSpace.setLineFeedsAreReadOnly(true);
              }
              final SpacingImpl spaceProperty = current.getSpaceProperty();
              if (spaceProperty != null) {
                boolean needChange = false;
                int newKeepLineBreaks = spaceProperty.getKeepBlankLines();
                boolean newKeepLineBreaksFlag = spaceProperty.shouldKeepLineFeeds();

                if (!keepLineBreaks) {
                  needChange = true;
                  newKeepLineBreaksFlag = false;
                }
                if (!keepBlankLines) {
                  needChange = true;
                  newKeepLineBreaks = 0;
                }

                if (needChange) {
                  assert !(spaceProperty instanceof DependantSpacingImpl);
                  current.setSpaceProperty(
                    getSpacingImpl(
                      spaceProperty.getMinSpaces(), spaceProperty.getMaxSpaces(), spaceProperty.getMinLineFeeds(),
                      spaceProperty.isReadOnly(),
                      spaceProperty.isSafe(), newKeepLineBreaksFlag, newKeepLineBreaks, false, spaceProperty.getPrefLineFeeds()
                    )
                  );
                }
              }
            }
          }
        }
        current = current.getNextBlock();
      }
      processor.format(model);
    }
    catch (FormattingModelInconsistencyException e) {
      LOG.error(e);
    }
    finally {
      enableFormatting();
    }
  }

  @Override
  public void adjustTextRange(final FormattingModel model,
                              final CodeStyleSettings settings,
                              final CommonCodeStyleSettings.IndentOptions indentOptions,
                              final TextRange affectedRange) {
    disableFormatting();
    try {
      validateModel(model);
      final FormatProcessor processor = buildProcessorAndWrapBlocks(
        model.getDocumentModel(), model.getRootBlock(), settings, indentOptions, new FormatTextRanges(affectedRange, true)
      );
      LeafBlockWrapper current = processor.getFirstTokenBlock();
      while (current != null) {
        WhiteSpace whiteSpace = current.getWhiteSpace();

        if (!whiteSpace.isReadOnly()) {
          if (whiteSpace.getStartOffset() > affectedRange.getStartOffset()) {
            whiteSpace.setReadOnly(true);
          }
          else {
            whiteSpace.setReadOnly(false);
          }
        }
        current = current.getNextBlock();
      }
      processor.format(model);
    }
    catch (FormattingModelInconsistencyException e) {
      LOG.error(e);
    }
    finally {
      enableFormatting();
    }
  }

  @Override
  public void saveIndents(final FormattingModel model, final TextRange affectedRange,
                          IndentInfoStorage storage,
                          final CodeStyleSettings settings,
                          final CommonCodeStyleSettings.IndentOptions indentOptions) {
    try {
      validateModel(model);
      final Block block = model.getRootBlock();

      final FormatProcessor processor = buildProcessorAndWrapBlocks(
        model.getDocumentModel(), block, settings, indentOptions, new FormatTextRanges(affectedRange, true)
      );
      LeafBlockWrapper current = processor.getFirstTokenBlock();
      while (current != null) {
        WhiteSpace whiteSpace = current.getWhiteSpace();

        if (!whiteSpace.isReadOnly() && whiteSpace.containsLineFeeds()) {
          storage.saveIndentInfo(current.calcIndentFromParent(), current.getStartOffset());
        }
        current = current.getNextBlock();
      }
    }
    catch (FormattingModelInconsistencyException e) {
      LOG.error(e);
    }
  }

  @Override
  public FormattingModel createFormattingModelForPsiFile(final PsiFile file,
                                                         @NotNull final Block rootBlock,
                                                         final CodeStyleSettings settings) {
    return new PsiBasedFormattingModel(file, rootBlock, FormattingDocumentModelImpl.createOn(file));
  }

  @Override
  public Indent getSpaceIndent(final int spaces, final boolean relative) {
    return getIndent(Indent.Type.SPACES, spaces, relative, false);
  }

  @Override
  public Indent getIndent(@NotNull Indent.Type type, boolean relativeToDirectParent, boolean enforceIndentToChildren) {
    return getIndent(type, 0, relativeToDirectParent, enforceIndentToChildren);
  }

  @Override
  public Indent getIndent(@NotNull Indent.Type type, int spaces, boolean relativeToDirectParent, boolean enforceIndentToChildren) {
    return new IndentImpl(type, false, spaces, relativeToDirectParent, enforceIndentToChildren);
  }

  @Override
  public Indent getAbsoluteLabelIndent() {
    return myAbsoluteLabelIndent;
  }

  @Override
  @NotNull
  public Spacing createSafeSpacing(final boolean shouldKeepLineBreaks, final int keepBlankLines) {
    return getSpacingImpl(0, 0, 0, false, true, shouldKeepLineBreaks, keepBlankLines, false, 0);
  }

  @Override
  @NotNull
  public Spacing createKeepingFirstColumnSpacing(final int minSpace,
                                                 final int maxSpace,
                                                 final boolean keepLineBreaks,
                                                 final int keepBlankLines) {
    return getSpacingImpl(minSpace, maxSpace, -1, false, false, keepLineBreaks, keepBlankLines, true, 0);
  }

  @Override
  @NotNull
  public Spacing createSpacing(final int minSpaces, final int maxSpaces, final int minLineFeeds, final boolean keepLineBreaks, final int keepBlankLines,
                               final int prefLineFeeds) {
    return getSpacingImpl(minSpaces, maxSpaces, minLineFeeds, false, false, keepLineBreaks, keepBlankLines, false, prefLineFeeds);
  }

  private final Map<SpacingImpl,SpacingImpl> ourSharedProperties = new HashMap<SpacingImpl,SpacingImpl>();
  private final SpacingImpl ourSharedSpacing = new SpacingImpl(-1,-1,-1,false,false,false,-1,false,0);

  private SpacingImpl getSpacingImpl(final int minSpaces,
                                     final int maxSpaces,
                                     final int minLineFeeds,
                                     final boolean readOnly,
                                     final boolean safe,
                                     final boolean keepLineBreaksFlag,
                                     final int keepLineBreaks,
                                     final boolean keepFirstColumn,
                                     int prefLineFeeds)
  {
    synchronized(ourSharedSpacing) {
      ourSharedSpacing.init(minSpaces, maxSpaces, minLineFeeds, readOnly, safe, keepLineBreaksFlag, keepLineBreaks, keepFirstColumn, prefLineFeeds);
      SpacingImpl spacing = ourSharedProperties.get(ourSharedSpacing);

      if (spacing == null) {
        spacing = new SpacingImpl(minSpaces, maxSpaces, minLineFeeds, readOnly, safe, keepLineBreaksFlag, keepLineBreaks, keepFirstColumn, prefLineFeeds);
        ourSharedProperties.put(spacing, spacing);
      }
      return spacing;
    }
  }

  @Override
  public Indent getAbsoluteNoneIndent() {
    return myAbsoluteNoneIndent;
  }

  @Override
  public Indent getLabelIndent() {
    return myLabelIndent;
  }

  @Override
  public Indent getContinuationIndent(boolean relative) {
    return relative ? myContinuationIndentRelativeToDirectParent : myContinuationIndentNotRelativeToDirectParent;
  }

  //is default
  @Override
  public Indent getContinuationWithoutFirstIndent(boolean relative) {
    return relative ? myContinuationWithoutFirstIndentRelativeToDirectParent : myContinuationWithoutFirstIndentNotRelativeToDirectParent;
  }

  @Override
  public boolean isDisabled() {
    return myIsDisabledCount.get() > 0;
  }

  private void disableFormatting() {
    myIsDisabledCount.incrementAndGet();
  }

  private void enableFormatting() {
    int old = myIsDisabledCount.getAndDecrement();
    if (old <= 0) {
      LOG.error("enableFormatting()/disableFormatting() not paired. DisabledLevel = " + old);
    }
  }

  @Nullable
  public <T> T runWithFormattingDisabled(@NotNull Computable<T> runnable) {
    disableFormatting();
    try {
      return runnable.compute();
    }
    finally {
      enableFormatting();
    }
  }

  private abstract static class MyFormattingTask implements SequentialTask {
    private FormatProcessor myProcessor;
    private boolean         myDone;

    @Override
    public void prepare() {
      myProcessor = buildProcessor();
    }

    @Override
    public boolean isDone() {
      return myDone;
    }

    @Override
    public boolean iteration() {
      return myDone = myProcessor.iteration();
    }

    @Override
    public void stop() {
      myProcessor.stopSequentialProcessing();
      myDone = true;
    }

    @NotNull
    protected abstract FormatProcessor buildProcessor();
  }

  private static void validateModel(FormattingModel model) throws FormattingModelInconsistencyException {
    FormattingDocumentModel documentModel = model.getDocumentModel();
    Document document = documentModel.getDocument();
    Block rootBlock = model.getRootBlock();
    if (rootBlock instanceof ASTBlock) {
      PsiElement rootElement = ((ASTBlock)rootBlock).getNode().getPsi();
      if (!rootElement.isValid()) {
        throw new FormattingModelInconsistencyException("Invalid root block PSI element");
      }
      PsiFile file = rootElement.getContainingFile();
      Project project = file.getProject();
      PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
      if (documentManager.isUncommited(document)) {
        throw new FormattingModelInconsistencyException("Uncommitted document");
      }
      if (document.getTextLength() != file.getTextLength()) {
        throw new FormattingModelInconsistencyException(
          "Document length " + document.getTextLength() +
          " doesn't match PSI file length " + file.getTextLength() + ", language: " + file.getLanguage()
        );
      }
    }
  }

  private static class FormattingModelInconsistencyException extends Exception {
    public FormattingModelInconsistencyException(String message) {
      super(message);
    }
  }
}
