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

import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.formatter.FormattingDocumentModelImpl;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;

/**
 * Object-level representation of continuous white space at document. Either line feed or tabulation or space is considered to be <code>'white-space'</code>.
 * I.e. document text fragment like {@code '\t   \t\t\n\t   \t'}  may be considered as a continuous white space and may be represented as a {@link WhiteSpace} object.
 * <p/>
 * Provides number of properties that describe encapsulated continuous white space:
 * <ul>
 *   <li>{@link #getLineFeeds() lineFeeds};</li>
 *   <li>{@link #getSpaces() spaces};</li>
 *   <li>{@link #getIndentSpaces()};</li>
 * </ul>
 * <p/>
 * Provides ability to build string representation of the managed settings taking into consideration user settings for tabulation vs white space usage, tabulation
 * size etc.
 * <p/>
 * Not thread-safe.
 */
class WhiteSpace {

  private static final char LINE_FEED = '\n';

  private final int myStart;
  private       int myEnd;

  private int mySpaces;
  private int myIndentSpaces;
  private int myInitialLastLinesSpaces;
  private int myInitialLastLinesTabs;

  private CharSequence myInitial;
  private int          myFlags;
  private boolean      myForceSkipTabulationsUsage;

  private static final byte FIRST = 1;
  private static final byte SAFE = 0x2;
  private static final byte KEEP_FIRST_COLUMN = 0x4;
  private static final byte LINE_FEEDS_ARE_READ_ONLY = 0x8;
  private static final byte READ_ONLY = 0x10;
  private static final byte CONTAINS_LF_INITIALLY = 0x20;
  private static final byte CONTAINS_SPACES_INITIALLY = 0x40;
  private static final int LF_COUNT_SHIFT = 7;
  private static final int MAX_LF_COUNT = 1 << 24;

  /**
   * Creates new <code>WhiteSpace</code> object with the given start offset and a flag that shows if current white space is
   * the first white space.
   * <p/>
   * <b>Note:</b> {@link #getEndOffset() end offset} value is the same as the {@link #getStartOffset() start offset} for
   * the newly constructed object. {@link #append(int, FormattingDocumentModel, CommonCodeStyleSettings.IndentOptions)} should be
   * called in order to apply desired end offset.
   *
   * @param startOffset       start offset to use
   * @param isFirst              flag that shows if current white space is the first
   */
  public WhiteSpace(int startOffset, boolean isFirst) {
    myStart = startOffset;
    myEnd = startOffset;
    setIsFirstWhiteSpace(isFirst);
  }

  /**
   * Applies new end offset to the current object.
   * <p/>
   * Namely, performs the following:
   * <ol>
   *   <li>Checks if new end offset can be applied, return in case of negative answer;</li>
   *   <li>
   *          Processes all new symbols introduced by the new end offset value, calculates number of line feeds,
   *          white spaces and tabulations between them and updates {@link #getLineFeeds() lineFeeds}, {@link #getSpaces() spaces},
   *          {@link #getIndentSpaces() indentSpaces} and {@link #getTotalSpaces() totalSpaces} properties accordingly;
   *    </li>
   * </ol>
   *
   * @param newEndOffset      new end offset value
   * @param model                 formatting model that is used to access to the underlying document text
   * @param options               indent formatting options
   */
  public void append(int newEndOffset, FormattingDocumentModel model, CommonCodeStyleSettings.IndentOptions options) {
    final int oldEndOffset = myEnd;
    if (newEndOffset == oldEndOffset) return;
    if (myStart >= newEndOffset) {
      InitialInfoBuilder.assertInvalidRanges(myStart,
        newEndOffset,
        model,
        "some block intersects with whitespace"
      );
    }

    myEnd = newEndOffset;
    TextRange range = new TextRange(myStart, myEnd);
    CharSequence oldText = myInitial;
    myInitial = model.getText(range);

    if (!coveredByBlock(model)) {
      InitialInfoBuilder.assertInvalidRanges(myStart,
        myEnd,
        model,
        "nonempty text is not covered by block"
      );
    }

    // There is a possible case that this method is called more than once on the same object. We want to
    if (newEndOffset > oldEndOffset) {
      refreshStateOnEndOffsetIncrease(newEndOffset, oldEndOffset, options.TAB_SIZE);
    } else {
      refreshStateOnEndOffsetDecrease(oldText, newEndOffset, oldEndOffset, options.TAB_SIZE);
    }
    IndentInside indent = IndentInside.getLastLineIndent(myInitial);
    myInitialLastLinesSpaces = indent.whiteSpaces;
    myInitialLastLinesTabs = indent.tabs;

    if (getLineFeeds() > 0) myFlags |= CONTAINS_LF_INITIALLY;
    else myFlags &= ~CONTAINS_LF_INITIALLY;

    final int totalSpaces = getTotalSpaces();
    if (totalSpaces > 0) myFlags |= CONTAINS_SPACES_INITIALLY;
    else myFlags &=~ CONTAINS_SPACES_INITIALLY;
  }

  /**
   * Allows to check if <code>'myInitial'</code> property value stands for continuous white space text.
   * <p/>
   * The text is considered to be continuous <code>'white space'</code> at following cases:
   * <ul>
   *   <li><code>'myInitial'</code> is empty string or string that contains white spaces only;</li>
   *   <li><code>'myInitial'</code> is a <code>CDATA</code> string which content is empty or consists from white spaces only;</li>
   *   <li><code>'myInitial'</code> string belongs to the same {@link PsiWhiteSpace} element;</li>
   * </ul>
   *
   * @param model     formatting model that is used to provide access to the <code>PSI API</code> if necessary
   * @return          <code>true</code> if <code>'myInitial'</code> property value stands for white space;
   *                  <code>false</code> otherwise
   */
  private boolean coveredByBlock(final FormattingDocumentModel model) {
    if (myInitial == null) return true;
    if (model.containsWhiteSpaceSymbolsOnly(myStart, myEnd)) return true;

    if (!(model instanceof FormattingDocumentModelImpl)) return false;
    PsiFile psiFile = ((FormattingDocumentModelImpl)model).getFile();
    if (psiFile == null) return false;
    PsiElement start = psiFile.findElementAt(myStart);
    PsiElement end = psiFile.findElementAt(myEnd-1);
    return start == end && start instanceof PsiWhiteSpace; // there maybe non-white text inside CDATA-encoded injected elements
  }

  private void refreshStateOnEndOffsetIncrease(int newEndOffset, int oldEndOffset, int tabSize) {
    assert newEndOffset > oldEndOffset;
    WhiteSpaceInfo info = parse(myInitial, oldEndOffset - myStart, newEndOffset - myStart, mySpaces + myIndentSpaces, tabSize);
    if (info.lineFeeds > 0) {
      setLineFeeds(getLineFeeds() + info.lineFeeds);
      mySpaces = 0;
      myIndentSpaces = 0;
    }
    mySpaces += info.spaces;
    myIndentSpaces += info.indentSpaces;
  }

  private void refreshStateOnEndOffsetDecrease(CharSequence oldText, int newEndOffset, int oldEndOffset, int tabSize) {
    assert newEndOffset < oldEndOffset;
    int lineFeedsNumberAtRemovedText = 0;
    int spacesNumberAtRemovedText = 0;
    int indentSpacesNumberAtRemovedText = 0;
    int column = mySpaces + myIndentSpaces;
    for (int i = oldEndOffset - 1; i >= newEndOffset; i--) {
      switch (oldText.charAt(i)) {
        case LINE_FEED: ++lineFeedsNumberAtRemovedText; column = 0; break;
        case ' ': ++spacesNumberAtRemovedText; column--; break;
        case '\t':
          int change = column % tabSize;
          if (change == 0) {
            change = tabSize;
          }
          indentSpacesNumberAtRemovedText += change; column -= change; break;
      }
    }

    // There are no line feeds at remained text, hence, we can just subtract number of spaces and indent spaces
    // from removed text and finish.
    if (getLineFeeds() - lineFeedsNumberAtRemovedText <= 0) {
      setLineFeeds(0);
      mySpaces -= spacesNumberAtRemovedText;
      myIndentSpaces -= indentSpacesNumberAtRemovedText;
      return;
    }

    // There are white spaces at remained text, hence, we need to calculate number of spaces and indent spaces between
    // last line feed and new end offset.
    int newLineFeedsNumber = getLineFeeds() - lineFeedsNumberAtRemovedText;
    assert newLineFeedsNumber >= 0;
    newLineFeedsNumber = newLineFeedsNumber < 0 ? 0 : newLineFeedsNumber; // Never expect the defense to be triggered.
    setLineFeeds(newLineFeedsNumber);
    int startOffset = CharArrayUtil.shiftForwardUntil(oldText, newEndOffset - 1, "\n") + 1;
    WhiteSpaceInfo info = parse(oldText, startOffset, newEndOffset, 0, tabSize);
    mySpaces = info.spaces;
    myIndentSpaces = info.indentSpaces;
  }

  /**
   * Parses information about white space symbols at the target region of the given text.
   *
   * @param text         target text
   * @param startOffset  target text range's start offset (inclusive)
   * @param endOffset    target text range's end offset (exclusive)
   * @param startColumn  given start offset's column. It affects how tab width is calculated, say, a tab symbol which
   *                     occupies four columns, will occupy only three if located at the first column
   * @param tabSize      tab width in columns
   * @return             information about white space symbols at the target region of the given text
   */
  @NotNull
  private static WhiteSpaceInfo parse(@NotNull CharSequence text, int startOffset, int endOffset, int startColumn, int tabSize) {
    assert startOffset <= endOffset;

    int spaces = 0;
    int indentSpaces = 0;
    int lineFeeds = 0;
    int column = startColumn;

    for (int i = startOffset; i < endOffset; i++) {
      switch (text.charAt(i)) {
        case LINE_FEED:
          lineFeeds++;
          spaces = 0;
          indentSpaces = 0;
          column = 0;
          break;
        case '\t':
          int change = tabSize - (column % tabSize);
          indentSpaces += change;
          column += change;
          break;
        default: spaces++; column++;
      }
    }

    return new WhiteSpaceInfo(lineFeeds, indentSpaces, spaces);
  }

  /**
   * Builds string that contains line feeds, white spaces and tabulation symbols known to the current {@link WhiteSpace} object.
   *
   * @param options     indentation formatting options
   * @return            string that contains line feeds, white spaces and tabulation symbols known to the current
   *                    {@link WhiteSpace} object
   */
  public String generateWhiteSpace(CommonCodeStyleSettings.IndentOptions options) {
    return new IndentInfo(getLineFeeds(), myIndentSpaces, mySpaces, myForceSkipTabulationsUsage).generateNewWhiteSpace(options);
  }

  /**
   * Tries to apply given values to {@link #getSpaces() spaces} and {@link #getIndentSpaces() indentSpaces} properties accordingly.
   * <p/>
   * The action is not guaranteed to be executed (i.e. the it's not guaranteed that target properties return given values after
   * this method call - see {@link #performModification(Runnable)} for more details).
   * <p/>
   * Moreover, the action is guaranteed to be <b>not</b> executed  if {@link #isKeepFirstColumn() keepFirstColumn} property
   * is unset and target document string doesn't contain spaces.
   *
   * @param spaces      new value for the {@link #getSpaces() spaces} property
   * @param indent      new value for the {@link #getIndentSpaces()}  indentSpaces} property
   */
  public void setSpaces(final int spaces, final int indent) {
    performModification(new Runnable() {
      @Override
      public void run() {
        if (!isKeepFirstColumn() || (myFlags & CONTAINS_SPACES_INITIALLY) != 0) {
          mySpaces = spaces;
          myIndentSpaces = indent;
        }
      }
    });
  }

  private boolean doesNotContainAnySpaces() {
    return getTotalSpaces() == 0 && getLineFeeds() == 0;
  }

  public int getStartOffset() {
    return myStart;
  }

  public int getEndOffset() {
    return myEnd;
  }

  /**
   * Execute given action in a safe manner.
   * <p/>
   * <code>'Safe manner'</code> here means the following:
   * <ul>
   *   <li>don't execute the action if {@link #isIsReadOnly() isReadOnly} property value is set to <code>true</code>;</li>
   *   <li>
   *        ensure that number of line feeds after action execution is preserved if line feeds are
   *        {@link #isLineFeedsAreReadOnly() read only};
   *   </li>
   *   <li>
   *        ensure the following if {@link #isIsSafe() isSafe} property is set to <code>true</code>:
   *        <ul>
   *          <li>
   *            cut all white spaces and line feeds appeared after given action execution to single white space if there
   *            were no line feeds and white spaces before;
   *          </li>
   *        </ul>
   *    </li>
   * </ul>
   *
   * @param action      action that should be performed in a safe manner
   */
  private void performModification(Runnable action) {
    if (isIsReadOnly()) return;
    final boolean before = doesNotContainAnySpaces();
    final int lineFeedsBefore = getLineFeeds();
    action.run();
    if (isLineFeedsAreReadOnly()) {
      setLineFeeds(lineFeedsBefore);
    }
    if (isIsSafe()) {
      final boolean after = doesNotContainAnySpaces();
      if (before && !after) {
        // Actions below seem to be useless if 'after' value is 'false'. Are kept as historical heritage.
        mySpaces = 0;
        myIndentSpaces = 0;
        setLineFeeds(0);
      }
      else if (!before && after) {
        mySpaces = 1;
        myIndentSpaces = 0;
      }
    }
  }

  /**
   * Tries to arrange {@link #getSpaces() spaces} property value to belong to
   * [{@link SpacingImpl#getMinSpaces() min}; {@link SpacingImpl#getMaxSpaces()}] bounds defined by the given spacing object
   * if {@link #getTotalSpaces() totalSpaces} property value lays out of the same bounds.
   * <p/>
   * The action is <b>not</b> performed if there are line feeds configured for the
   * current {@link WhiteSpace} object ({@link #getSpaces()} != 0).
   *
   * @param spaceProperty     spacing settings holder
   */
  public void arrangeSpaces(final SpacingImpl spaceProperty) {
    performModification(new Runnable() {
      @Override
      public void run() {
        if (spaceProperty != null) {
          if (getLineFeeds() == 0) {
            if (spaceProperty.getMinSpaces() >= 0 && getTotalSpaces() < spaceProperty.getMinSpaces()) {
              setSpaces(spaceProperty.getMinSpaces(), 0);
            }
            if (spaceProperty.getMaxSpaces() >= 0 && getTotalSpaces() > spaceProperty.getMaxSpaces()) {
              setSpaces(spaceProperty.getMaxSpaces(), 0);
            }
          }
        }
      }
    });
  }

  /**
   * Tries to ensure that number of line feeds managed by the current {@link WhiteSpace} is consistent to the settings
   * defined at the given spacing property.
   *
   * @param spaceProperty       space settings holder
   * @param formatProcessor    format processor to use for space settings state refreshing
   */
  public void arrangeLineFeeds(final SpacingImpl spaceProperty, final FormatProcessor formatProcessor) {
    performModification(new Runnable() {
      @Override
      public void run() {
        if (spaceProperty != null) {
          spaceProperty.refresh(formatProcessor);

          if (spaceProperty.getMinLineFeeds() >= 0 && getLineFeeds() < spaceProperty.getMinLineFeeds()) {
            setLineFeeds(spaceProperty.getMinLineFeeds());
          }
          if (getLineFeeds() > 0) {
            if (spaceProperty.getKeepBlankLines() > 0) {
              if (getLineFeeds() >= spaceProperty.getKeepBlankLines() + 1) {
                setLineFeeds(spaceProperty.getKeepBlankLines() + 1);
              }
            }
            else {
              if (getLineFeeds() > spaceProperty.getMinLineFeeds()) {
                if (spaceProperty.shouldKeepLineFeeds()) {
                  setLineFeeds(Math.max(spaceProperty.getMinLineFeeds(), 1));
                }
                else {
                  setLineFeeds(spaceProperty.getMinLineFeeds());
                  if (getLineFeeds() == 0) mySpaces = 0;
                }
              }
            }
            if (getLineFeeds() == 1 && !spaceProperty.shouldKeepLineFeeds() && spaceProperty.getMinLineFeeds() == 0) {
              setLineFeeds(0);
              mySpaces = 0;
            }

            if (getLineFeeds() > 0 && getLineFeeds() < spaceProperty.getPrefLineFeeds()) {
              setLineFeeds(spaceProperty.getPrefLineFeeds());
            }
          }
        } else if (isFirst()) {
          setLineFeeds(0);
          mySpaces = 0;
        }
      }
    });

  }

  /**
   * There is a possible case that particular indent info is applied to the code block that is not the first block on a line.
   * E.g. we may want to align field name during <code>'align fields in columns'</code> processing:
   *     <pre>
   *         public class Test {
   *             private Object o;
   *             private int {@code <white space to align>}i;
   *         }
   *     </pre>
   * We may not want to use tabulation characters then even if user configured
   * {@link CommonCodeStyleSettings.IndentOptions#USE_TAB_CHARACTER their usage} because we can't be sure how many visual columns
   * will be used for tab representation if there are non-white space symbols before it (IJ editor may use different number of columns
   * for single tabulation symbol representation).
   * <p/>
   * Hence, we can ask current white space object to avoid using tabulation symbols.
   *
   * @param skip   indicates if tabulations symbols usage should be suppressed
   */
  public void setForceSkipTabulationsUsage(boolean skip) {
    myForceSkipTabulationsUsage = skip;
  }

  /**
   * Allows to get information if target text document continuous 'white space' represented by the current object contained line feed
   * symbol(s) initially or contains line feed(s) now.
   *
   * @return    <code>true</code> if this object contained line feeds initially or contains them now; <code>false</code> otherwise
   * @see #containsLineFeedsInitially()
   */
  public boolean containsLineFeeds() {
    return isIsFirstWhiteSpace() || getLineFeeds() > 0;
  }

  public int getTotalSpaces() {
    return mySpaces + myIndentSpaces;
  }

  /**
   * Tries to ensure that current {@link WhiteSpace} object contains at least one line feed.
   */
  public void ensureLineFeed() {
    performModification(new Runnable() {
      @Override
      public void run() {
        if (!containsLineFeeds()) {
          setLineFeeds(1);
          mySpaces = 0;
        }
      }
    });
  }

  public boolean isReadOnly() {
    return isIsReadOnly() || (isIsSafe() && doesNotContainAnySpaces());
  }

  /**
   * @param ws      char sequence to check
   * @return        <code>true</code> if given char sequence is equal to the target document text identified by
   *                start/end offsets managed by the current {@link WhiteSpace} object; <code>false</code> otherwise
   */
  public boolean equalsToString(CharSequence ws) {
    if (myInitial == null) return ws.length() == 0;
    return Comparing.equal(ws,myInitial,true);
  }

  public void setIsSafe(final boolean value) {
    setFlag(SAFE, value);
  }

  private void setFlag(final int mask, final boolean value) {
    if (value) {
      myFlags |= mask;
    }
    else {
      myFlags &= ~mask;
    }
  }

  private boolean getFlag(final int mask) {
    return (myFlags & mask) != 0;
  }

  private boolean isFirst() {
    return isIsFirstWhiteSpace();
  }

  /**
   * Allows to get information if current object contained line feed(s) initially. It's considered to contain them if
   * line feeds were found at the target text document fragment after
   * new {@link #append(int, FormattingDocumentModel, CommonCodeStyleSettings.IndentOptions) end offset appliance}.
   *
   * @return    <code>true</code> if current object contained line feeds initially; <code>false</code> otherwise
   */
  public boolean containsLineFeedsInitially() {
    if (myInitial == null) return false;
    return (myFlags & CONTAINS_LF_INITIALLY) != 0;
  }

  /**
   * Tries to ensure that number of line feeds and white spaces managed by the given {@link WhiteSpace} object is the
   * same as the one defined by the given <code>'spacing'</code> object.
   * <p/>
   * This method may be considered a shortcut for calling {@link #arrangeLineFeeds(SpacingImpl, FormatProcessor)} and
   * {@link #arrangeSpaces(SpacingImpl)}.
   *
   * @param spacing             spacing settings holder
   * @param formatProcessor     format processor to use to refresh state of the given <code>'spacing'</code> object
   */
  public void removeLineFeeds(final SpacingImpl spacing, final FormatProcessor formatProcessor) {
    performModification(new Runnable() {
      @Override
      public void run() {
        setLineFeeds(0);
        mySpaces = 0;
        myIndentSpaces = 0;
      }
    });
    arrangeLineFeeds(spacing, formatProcessor);
    arrangeSpaces(spacing);
  }

  public int getIndentOffset() {
    return myIndentSpaces;
  }

  /**
   * Allows to get information about number of 'pure' white space symbols at the last line of continuous white space document
   * text fragment represented by the current {@link WhiteSpace} object.
   * <p/>
   * <b>Note:</b> pay special attention to <code>'last line'</code> qualification here. Consider the following target continuous
   * white space document fragment:
   * <pre>
   *        ' ws<sub>11</sub>ws<sub>12</sub>
   *        'ws<sub>21</sub>'
   * </pre>
   * <p/>
   * Here <code>'ws<sub>nm</sub>'</code> is a m-th white space symbol at the n-th line. <code>'Spaces'</code> property of
   * {@link WhiteSpace} object for such white-space text has a value not <b>2</b> or <b>3</b> but <b>1</b>.
   *
   * @return      number of white spaces at the last line of target continuous white space text document fragment
   */
  public int getSpaces() {
    return mySpaces;
  }

  public void setKeepFirstColumn(final boolean b) {
    setFlag(KEEP_FIRST_COLUMN, b);
  }

  public void setLineFeedsAreReadOnly() {
    setLineFeedsAreReadOnly(true);
  }

  public void setReadOnly(final boolean isReadOnly) {
    setIsReadOnly(isReadOnly);
  }

  public boolean isIsFirstWhiteSpace() {
    return getFlag(FIRST);
  }

  public boolean isIsSafe() {
    return getFlag(SAFE);
  }

  public boolean isKeepFirstColumn() {
    return getFlag(KEEP_FIRST_COLUMN);
  }

  public boolean isLineFeedsAreReadOnly() {
    return getFlag(LINE_FEEDS_ARE_READ_ONLY);
  }

  public void setLineFeedsAreReadOnly(final boolean lineFeedsAreReadOnly) {
    setFlag(LINE_FEEDS_ARE_READ_ONLY, lineFeedsAreReadOnly);
  }

  public boolean isIsReadOnly() {
    return getFlag(READ_ONLY);
  }

  public void setIsReadOnly(final boolean isReadOnly) {
    setFlag(READ_ONLY, isReadOnly);
  }

  public void setIsFirstWhiteSpace(final boolean isFirstWhiteSpace) {
    setFlag(FIRST, isFirstWhiteSpace);
  }

  public StringBuilder generateWhiteSpace(final CommonCodeStyleSettings.IndentOptions indentOptions,
                                                  final int offset,
                                                  final IndentInfo indent) {
    final StringBuilder result = new StringBuilder();
    int currentOffset = getStartOffset();
    CharSequence[] lines = getInitialLines();
    int currentLine = 0;
    for (int i = 0; i < lines.length - 1 && currentOffset + lines[i].length() <= offset; i++) {
      result.append(lines[i]);
      currentOffset += lines[i].length();
      result.append(LINE_FEED);
      currentOffset++;
      currentLine++;
      if (currentOffset == offset) {
        break;
      }

    }
    final String newIndentSpaces = indent.generateNewWhiteSpace(indentOptions);
    result.append(newIndentSpaces);
    appendNonWhitespaces(result, lines, currentLine);
    if (currentLine + 1 < lines.length) {
      result.append(LINE_FEED);
      for (int i = currentLine + 1; i < lines.length - 1; i++) {
        result.append(lines[i]);
        result.append(LINE_FEED);
      }
      appendNonWhitespaces(result, lines, lines.length-1);
      result.append(lines[lines.length - 1]);

    }
    return result;
  }

  @NotNull
  public IndentInside getInitialLastLineIndent() {
    return new IndentInside(myInitialLastLinesSpaces, myInitialLastLinesTabs);
  }

  private static void appendNonWhitespaces(StringBuilder result, CharSequence[] lines, int currentLine) {
    // It looks like regexp usage is too heavy here.
    if (currentLine != lines.length && !lines[currentLine].toString().matches("\\s*")) {
      result.append(lines[currentLine]);
    }
  }

  /**
   * Shows target document text fragment identified by start/end offsets as a sequence of strings.
   * <p/>
   * <b>Note:</b> arrays usage here is considered to be a historical heritage.
   *
   * @return      target document text fragment as a sequence of strings
   */
  private CharSequence[] getInitialLines() {
    if (myInitial == null) return new CharSequence[]{""};
    final ArrayList<CharSequence> result = new ArrayList<CharSequence>();
    StringBuilder currentLine = new StringBuilder();
    for (int i = 0; i < myInitial.length(); i++) {
      final char c = myInitial.charAt(i);
      if (c == LINE_FEED) {
        result.add(currentLine);
        currentLine = new StringBuilder();
      }
      else {
        currentLine.append(c);
      }
    }
    result.add(currentLine);
    return result.toArray(new CharSequence[result.size()]);
  }

  /**
   * Provides access to the information about indent white spaces at last line of continuous white space text document
   * fragment represented by the current {@link WhiteSpace} object.
   * <p/>
   * <code>'Indent white space'</code> here is a white space representation of tabulation symbol. User may define that
   * he or she wants to use particular number of white spaces instead of tabulation
   * ({@link CommonCodeStyleSettings.IndentOptions#TAB_SIZE}). So, {@link WhiteSpace} object uses corresponding
   * number of 'indent white spaces' for each tabulation symbol encountered at target continuous white space text document fragment.
   * <p/>
   * <b>Note:</b> pay special attention to <code>'last line'</code> qualification here. Consider the following target
   * continuous white space document fragment:
   * <pre>
   *        ' \t\t
   *        '\t'
   * </pre>
   * <p/>
   * Let's consider that <code>'tab size'</code> is defined as four white spaces (default setting).
   * <code>'IndentSpaces'</code> property of {@link WhiteSpace} object for such white-space text has a value not
   * <b>8</b> or <b>12</b> but <b>4</b>, i.e. tabulation symbols from last line
   * only are counted.
   *
   * @return        number of indent spaces at the last line of target continuous white space text document fragment
   */
  public int getIndentSpaces() {
    return myIndentSpaces;
  }

  public int getLength() {
    return myEnd - myStart;
  }

  /**
   * Provides access to the line feed symbols number at continuous white space text document fragment represented
   * by the current {@link WhiteSpace} object.
   *
   * @return      line feed symbols number
   */
  public final int getLineFeeds() {
    return myFlags >>> LF_COUNT_SHIFT;
  }

  public void setLineFeeds(final int lineFeeds) {
    assert lineFeeds < MAX_LF_COUNT;
    final int flags = myFlags;
    myFlags &= ~0xFFFFFF80; // keep only seven lower bits, i.e. drop all line feeds registered before if any
    myFlags |= (lineFeeds << LF_COUNT_SHIFT);

    assert getLineFeeds() == lineFeeds;
    assert (flags & 0x7F) == (myFlags & 0x7F);
  }

  public TextRange getTextRange() {
    return new TextRange(myStart, myEnd);
  }

  @Override
  public String toString() {
    return "WhiteSpace(" + myStart + "-" + myEnd + " spaces=" + mySpaces + " LFs=" + getLineFeeds() + ")";
  }

  private static class WhiteSpaceInfo {

    public final int spaces;
    public final int indentSpaces;
    public final int lineFeeds;

    WhiteSpaceInfo(int lineFeeds, int indentSpaces, int spaces) {
      this.lineFeeds = lineFeeds;
      this.indentSpaces = indentSpaces;
      this.spaces = spaces;
    }
  }
}

