/*
 * 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.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static java.util.Arrays.asList;

/**
 * @author lesya
 */
public abstract class AbstractBlockWrapper {

  private static final Set<IndentImpl.Type> RELATIVE_INDENT_TYPES = new HashSet<IndentImpl.Type>(asList(
    Indent.Type.NORMAL, Indent.Type.CONTINUATION, Indent.Type.CONTINUATION_WITHOUT_FIRST
  ));

  protected WhiteSpace myWhiteSpaceBefore;
  protected CompositeBlockWrapper myParent;
  protected int                   myStart;
  protected int                   myEnd;
  protected int                   myFlags;

  static int CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT = 1;
  static int INCOMPLETE                                 = 2;

  private final Language myLanguage;

  protected IndentInfo myIndentFromParent = null;
  private   IndentImpl myIndent           = null;
  private AlignmentImpl myAlignment;
  private WrapImpl      myWrap;
  private final ASTNode myNode;

  public AbstractBlockWrapper(final Block block,
                              final WhiteSpace whiteSpaceBefore,
                              final CompositeBlockWrapper parent,
                              final TextRange textRange) {
    myWhiteSpaceBefore = whiteSpaceBefore;
    myParent = parent;
    myStart = textRange.getStartOffset();
    myEnd = textRange.getEndOffset();

    myFlags = CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT | (block.isIncomplete() ? INCOMPLETE : 0);
    myAlignment = (AlignmentImpl)block.getAlignment();
    myWrap = (WrapImpl)block.getWrap();
    myLanguage = deriveLanguage(block);
    myNode = block instanceof ASTBlock ? ((ASTBlock) block).getNode() : null;
  }

  @Nullable
  private static Language deriveLanguage(@NotNull Block block) {
    if (block instanceof BlockEx) {
      return ((BlockEx)block).getLanguage();
    }
    return null;
  }

  /**
   * Returns the whitespace preceding the block.
   *
   * @return the whitespace preceding the block
   */
  public WhiteSpace getWhiteSpace() {
    return myWhiteSpaceBefore;
  }

  /**
   * Returns the AST node corresponding to the block, if known.
   *
   * @return the AST node or null
   */
  @Nullable
  public ASTNode getNode() {
    return myNode;
  }

  /**
   * Returns the list of wraps for this block and its parent blocks that start at the same offset. The returned list is ordered from top
   * to bottom (higher-level wraps go first). Stops if the wrap for a block is marked as "ignore parent wraps".
   *
   * @return the list of wraps.
   */
  public ArrayList<WrapImpl> getWraps() {
    final ArrayList<WrapImpl> result = new ArrayList<WrapImpl>(3);
    AbstractBlockWrapper current = this;
    while(current != null && current.getStartOffset() == getStartOffset()) {
      final WrapImpl wrap = current.getOwnWrap();
      if (wrap != null && !result.contains(wrap)) result.add(0, wrap);
      if (wrap != null && wrap.getIgnoreParentWraps()) break;
      current = current.myParent;
    }
    return result;
  }

  public int getStartOffset() {
    return myStart;
  }

  public int getEndOffset() {
    return myEnd;
  }

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

  /**
   * There is a possible case that particular block's language differs from the language implied by the file type. We need to
   * distinguish such a situation because, for example in case of indent calculation (code style settings for different languages
   * may have different indent values).
   * <p/>
   * This method allows to retrieve the language associated with the current block (if provided).
   * 
   * @return current block's language (if provided)
   */
  @Nullable
  public Language getLanguage() {
    return myLanguage;
  }

  /**
   * Applies given start offset to the current block wrapper and recursively calls this method on parent block wrapper
   * if it starts at the same place as the current one.
   *
   * @param startOffset     new start offset value to apply
   */
  protected void arrangeStartOffset(final int startOffset) {
    if (getStartOffset() == startOffset) return;
    boolean isFirst = getParent() != null && getStartOffset() == getParent().getStartOffset();
    myStart = startOffset;
    if (isFirst) {
      getParent().arrangeStartOffset(startOffset);
    }
  }

  public IndentImpl getIndent(){
    return myIndent;
  }

  public CompositeBlockWrapper getParent() {
    return myParent;
  }

  @Nullable
  public WrapImpl getWrap() {
    final ArrayList<WrapImpl> wraps = getWraps();
    if (wraps.size() == 0) return null;
    return wraps.get(0);
  }

  /**
   * @return    wrap object configured for the current block wrapper if any; <code>null</code> otherwise
   */
  public WrapImpl getOwnWrap() {
    return myWrap;
  }

  public void reset() {
    myFlags |= CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
    final AlignmentImpl alignment = myAlignment;
    if (alignment != null) alignment.reset();
    final WrapImpl wrap = myWrap;
    if (wrap != null) wrap.reset();
  }

  public IndentData getChildOffset(AbstractBlockWrapper child, CommonCodeStyleSettings.IndentOptions options, int targetBlockStartOffset) {
    final boolean childStartsNewLine = child.getWhiteSpace().containsLineFeeds();
    IndentImpl.Type childIndentType = child.getIndent().getType();
    IndentData childIndent;

    // Calculate child indent.
    if (childStartsNewLine
        || (!getWhiteSpace().containsLineFeeds() && RELATIVE_INDENT_TYPES.contains(childIndentType) && indentAlreadyUsedBefore(child)))
    {
      childIndent = CoreFormatterUtil.getIndent(options, child, targetBlockStartOffset);
    }
    else if (child.getIndent().isEnforceIndentToChildren() && !child.getWhiteSpace().containsLineFeeds()) {
      // Enforce indent if child doesn't start new line, e.g. prefer the code below:
      //    void test() {
      //        foo("test", new Runnable() {
      //                public void run() {
      //                }
      //            },
      //            new Runnable() {
      //                public void run() {
      //                }
      //            }
      //        );
      //    }
      // to this one:
      //    void test() {
      //        foo("test", new Runnable() {
      //            public void run() {
      //            }
      //        },
      //            new Runnable() {
      //                public void run() {
      //                }
      //            }
      //        );
      //    }
      AlignmentImpl alignment = child.getAlignment();
      if (alignment != null) {
        // Generally, we want to handle situation like the one below:
        //   test("text", new Runnable() { 
        //            @Override
        //            public void run() {
        //            }
        //        },
        //        new Runnable() {
        //            @Override
        //            public void run() {
        //            }
        //        }
        //   );
        // I.e. we want 'run()' method from the first anonymous class to be aligned with the 'run()' method of the second anonymous class.

        AbstractBlockWrapper anchorBlock = alignment.getOffsetRespBlockBefore(child);
        if (anchorBlock == null) {
          anchorBlock = this;
          if (anchorBlock instanceof CompositeBlockWrapper) {
            List<AbstractBlockWrapper> children = ((CompositeBlockWrapper)anchorBlock).getChildren();
            for (AbstractBlockWrapper c : children) {
              if (c.getStartOffset() != getStartOffset()) {
                anchorBlock = c;
                break;
              }
            }
          }
        }
        return anchorBlock.getNumberOfSymbolsBeforeBlock();
      }
      childIndent = CoreFormatterUtil.getIndent(options, child, getStartOffset());
    }
    else {
      childIndent = new IndentData(0);
    }

    // Use child indent if it's absolute and the child is contained on new line.
    if (childStartsNewLine) {
      if (child.getIndent().isAbsolute()) {
        myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
        AbstractBlockWrapper current = this;
        while (current != null && current.getStartOffset() == getStartOffset()) {
          current.myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
          current = current.myParent;
        }
        return childIndent;
      }      
      else if (child.getIndent().isRelativeToDirectParent() && child.getStartOffset() > getStartOffset()) {
        return childIndent.add(getNumberOfSymbolsBeforeBlock());
      }
    }

    if (child.getStartOffset() == getStartOffset()) {
      final boolean newValue = (myFlags & CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT) != 0 &&
                               (child.myFlags & CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT) != 0 && childIndent.isEmpty();
      setCanUseFirstChildIndentAsBlockIndent(newValue);
    }

    if (getStartOffset() == targetBlockStartOffset) {
      if (myParent == null) {
        return childIndent;
      }
      else {
        return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset));
      }
    }
    else if (!getWhiteSpace().containsLineFeeds()) {
      final IndentData indent = createAlignmentIndent(childIndent, child);
      if (indent != null) {
        return indent;
      }
      return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset));
    }
    else {
      if (myParent == null) return  childIndent.add(getWhiteSpace());
      if (getIndent().isAbsolute()) {
        if (myParent.myParent != null) {
          return childIndent.add(myParent.myParent.getChildOffset(myParent, options, targetBlockStartOffset));
        }
        else {
          return  childIndent.add(getWhiteSpace());
        }
      }
      if ((myFlags & CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT) != 0) {
        final IndentData indent = createAlignmentIndent(childIndent, child);
        if (indent != null) {
          return indent;
        }
        return childIndent.add(getWhiteSpace());
      }
      else {
        return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset));
      }
    }
  }

  /**
   * Allows to answer if current wrapped block has a child block that is located before given block and has line feed.
   *
   * @param child   target child block to process
   * @return        <code>true</code> if current block has a child that is located before the given block and contains line feed;
   *                <code>false</code> otherwise
   */
  protected abstract boolean indentAlreadyUsedBefore(final AbstractBlockWrapper child);

  /**
   * Allows to retrieve object that encapsulates information about number of symbols before the current block starting
   * from the line start. I.e. all symbols (either white space or not) between start of the line where current block begins
   * and the block itself are count and returned.
   *
   * @return    object that encapsulates information about number of symbols before the current block
   */
  protected abstract IndentData getNumberOfSymbolsBeforeBlock();

  /**
   * @return    previous block for the current block if any; <code>null</code> otherwise
   */
  @Nullable
  protected abstract LeafBlockWrapper getPreviousBlock();

  protected final void setCanUseFirstChildIndentAsBlockIndent(final boolean newValue) {
    if (newValue) myFlags |= CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
    else myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT;
  }

  /**
   * Applies start offset of the current block wrapper to the parent block wrapper if the one is defined.
   */
  public void arrangeParentTextRange() {
    if (myParent != null) {
      myParent.arrangeStartOffset(getStartOffset());
    }
  }
  public IndentData calculateChildOffset(final CommonCodeStyleSettings.IndentOptions indentOption, final ChildAttributes childAttributes,
                                         int index) {
    IndentImpl childIndent = (IndentImpl)childAttributes.getChildIndent();

    if (childIndent == null) childIndent = (IndentImpl)Indent.getContinuationWithoutFirstIndent(indentOption.USE_RELATIVE_INDENTS);

    IndentData indent = getIndent(indentOption, index, childIndent);
    if (childIndent.isRelativeToDirectParent()) {
      return new IndentData(indent.getIndentSpaces() + CoreFormatterUtil.getStartColumn(CoreFormatterUtil.getFirstLeaf(this)),
                            indent.getSpaces());
    }
    if (myParent == null || (myFlags & CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT) != 0 && getWhiteSpace().containsLineFeeds()) {
      return indent.add(getWhiteSpace());
    }
    else {
      IndentData offsetFromParent = myParent.getChildOffset(this, indentOption, -1);
      return indent.add(offsetFromParent);
    }

  }

  /**
   * Allows to retrieve alignment applied to any block that conforms to the following conditions:
   * <p/>
   * <ul>
   *   <li>that block is current block or its ancestor (direct or indirect parent);</li>
   *   <li>that block starts at the same offset as the current one;</li>
   * </ul>
   *
   * @return    alignment of the current block or it's ancestor that starts at the same offset as the current if any;
   *            <code>null</code> otherwise
   */
  @Nullable
  public AlignmentImpl getAlignmentAtStartOffset() {
    for (AbstractBlockWrapper block = this; block != null && block.getStartOffset() == getStartOffset(); block = block.getParent()) {
      if (block.getAlignment() != null) {
        return block.getAlignment();
      }
    }
    return null;
  }

  /**
   * Check if it's possible to construct indent for the block that is affected by aligning rules. E.g. there is a possible case
   * that the user configures method call arguments to be aligned and single parameter expression spans more than one line:
   * <p/>
   * <pre>
   *     public void test(String s1, String s2) {}
   *
   *     public void foo() {
   *         test("11"
   *                  + "12"
   *                  + "13",
   *              "21"
   *                  + "22");
   *     }
   * </pre>
   * <p/>
   * Here both composite blocks (<b>"11" + "12" + "13"</b> and <b>"21" + "22"</b>) are aligned as method call argument but their
   * sub-blocks that are located on new lines should also be indented to the point of composite block start.
   * <p/>
   * This method takes care about constructing target absolute indent of the given child block assuming that it's parent
   * (referenced by <code>'this'</code>) or it's ancestor that starts at the same offset is aligned.
   *
   * @param indentFromParent    basic indent of given child from the current parent block
   * @param child               child block of the current aligned composite block
   * @return                    absolute indent to use for the given child block of the current composite block if alignment-affected
   *                            indent should be used for it;
   *                            <code>null</code> otherwise
   */
  @Nullable
  private IndentData createAlignmentIndent(IndentData indentFromParent, AbstractBlockWrapper child) {
    if (!child.getWhiteSpace().containsLineFeeds()) {
      return null;
    }

    AlignmentImpl alignment = getAlignmentAtStartOffset();
    if (alignment == null || alignment == child.getAlignment()) {
      return null;
    }
    
    AbstractBlockWrapper previous = child.getPreviousBlock();
    LeafBlockWrapper anchorOffsetBlock = alignment.getOffsetRespBlockBefore(child);
    if (anchorOffsetBlock != null && anchorOffsetBlock.getStartOffset() != getStartOffset()) {
      // Located on different lines.
      boolean onDifferentLines = false;
      for (LeafBlockWrapper b = anchorOffsetBlock.getNextBlock(); b != null && b.getStartOffset() < getStartOffset(); b = b.getNextBlock()) {
        if (b.getWhiteSpace().containsLineFeeds()) {
          onDifferentLines = true;
          break;
        }
      }

      if (!onDifferentLines) {
        return null;
      }
    }

    // There is no point in continuing processing if given child is the first block, i.e. there is no alignment-implied
    // offset to add to the given 'indent from parent'.
    if (previous == null) {
      return indentFromParent;
    }

    IndentData symbolsBeforeCurrent;
    if (anchorOffsetBlock == null) {
      symbolsBeforeCurrent = getNumberOfSymbolsBeforeBlock();
    }
    else {
      symbolsBeforeCurrent = anchorOffsetBlock.getNumberOfSymbolsBeforeBlock();
    }

    // Result is calculated as a number of symbols between the current composite parent block plus given 'indent from parent'.
    int indentSpaces = symbolsBeforeCurrent.getIndentSpaces() + indentFromParent.getSpaces() + indentFromParent.getIndentSpaces();
    return new IndentData(indentSpaces, symbolsBeforeCurrent.getSpaces());
  }

  private static IndentData getIndent(final CommonCodeStyleSettings.IndentOptions options, final int index, IndentImpl indent) {
    if (indent.getType() == Indent.Type.CONTINUATION) {
      return new IndentData(options.CONTINUATION_INDENT_SIZE);
    }
    if (indent.getType() == Indent.Type.CONTINUATION_WITHOUT_FIRST) {
      if (index != 0) {
        return new IndentData(options.CONTINUATION_INDENT_SIZE);
      }
      else {
        return new IndentData(0);
      }
    }
    if (indent.getType() == Indent.Type.LABEL) return new IndentData(options.LABEL_INDENT_SIZE);
    if (indent.getType() == Indent.Type.NONE) return new IndentData(0);
    if (indent.getType() == Indent.Type.SPACES) return new IndentData(indent.getSpaces(), 0);
    return new IndentData(options.INDENT_SIZE);

  }

  /**
   * Applies given indent value to '<code>indentFromParent'</code> property of the current wrapped block.
   * <p/>
   * Given value is also applied to '<code>indentFromParent'</code> properties of all parents of the current wrapped block if the
   * value is defined (not <code>null</code>).
   * <p/>
   * This property is used later during
   * {@link LeafBlockWrapper#calculateOffset(CommonCodeStyleSettings.IndentOptions)} leaf block offset calculation}.
   *
   * @param indentFromParent    indent value to apply
   */
  public void setIndentFromParent(final IndentInfo indentFromParent) {
    myIndentFromParent = indentFromParent;
    if (myIndentFromParent != null) {
      AbstractBlockWrapper parent = myParent;
      if (myParent != null && myParent.getStartOffset() == myStart) {
        parent.setIndentFromParent(myIndentFromParent);
      }
    }    
  }

  /**
   * Tries to find first parent block of the current block that starts before the current block and which
   * {@link WhiteSpace white space} contains line feeds.
   *
   * @return    first parent block that starts before the current block and which white space contains line feeds if any;
   *            <code>null</code> otherwise
   */
  @Nullable
  protected AbstractBlockWrapper findFirstIndentedParent() {
    if (myParent == null) return null;
    if (myStart != myParent.getStartOffset() && myParent.getWhiteSpace().containsLineFeeds()) return myParent;
    return myParent.findFirstIndentedParent();
  }

  public void setIndent(@Nullable final IndentImpl indent) {
    myIndent = indent;
  }

  public AlignmentImpl getAlignment() {
    return myAlignment;
  }

  public boolean isIncomplete() {
    return (myFlags & INCOMPLETE) != 0;
  }

  public void dispose() {
    myAlignment = null;
    myWrap = null;
    myIndent = null;
    myIndentFromParent = null;
    myParent = null;
    myWhiteSpaceBefore = null;
  }

  @Override
  public String toString() {
    return getClass().getName() + "(" + myStart + "-" + myEnd + ")";
  }
}
