package com.intellij.formatting;

import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;

import java.io.PrintStream;
import java.util.List;

/**
 * @author yole
 */
@SuppressWarnings({"HardCodedStringLiteral"})
public class FormattingModelDumper {
  private FormattingModelDumper() {
  }

  public static void dumpFormattingModel(final Block block, int indent, final PrintStream output) {
    if (indent == 0) {
      output.println("--- FORMATTING MODEL ---");
    }
    output.print(StringUtil.repeatSymbol(' ', indent));
    List<Block> subBlocks = block.getSubBlocks();
    if (subBlocks.isEmpty()) {
      dumpTextBlock(block, output);
    }
    else {
      dumpBlock(block, output);
      Block prevBlock = null;
      for(Block subBlock: subBlocks) {
        if (prevBlock != null) {
          Spacing spacing = block.getSpacing(prevBlock, subBlock);
          if (spacing != null) {
            dumpSpacing(spacing, indent+2, output);
          }
        }
        prevBlock = subBlock;
        dumpFormattingModel(subBlock, indent+2, output);
      }
    }
  }

  private static void dumpTextBlock(final Block block, final PrintStream output) {
    StringBuilder blockData = new StringBuilder("\"" + getBlockText(block) + "\"");
    dumpBlockProperties(block, blockData);
    output.println(blockData.toString());
  }

  private static String getBlockText(final Block block) {
    if (block instanceof ASTBlock) {
      return ((ASTBlock)block).getNode().getText();
    }
    else {
      return "unknown block " + block.getClass();
    }
  }

  private static void dumpBlock(final Block block, final PrintStream output) {
    StringBuilder blockData = new StringBuilder("<block ");
    if (block instanceof ASTBlock) {
      blockData.append(((ASTBlock)block).getNode().getElementType());
    }
    dumpBlockProperties(block, blockData);
    blockData.append(">");
    output.println(blockData.toString());
  }

  private static void dumpBlockProperties(final Block block, final StringBuilder blockData) {
    TextRange textRange = block.getTextRange();
    blockData.append(" ").append(textRange.getStartOffset()).append(":").append(textRange.getEndOffset());
    Wrap wrap = block.getWrap();
    if (wrap != null) {
      blockData.append(" ").append(wrap);
    }
    Indent indent = block.getIndent();
    if (indent != null) {
      blockData.append(" ").append(indent);
    }
  }

  private static void dumpSpacing(final Spacing spacing, final int indent, final PrintStream out) {
    out.print(StringUtil.repeatSymbol(' ', indent));
    out.println("spacing: " + spacing);
  }
}

@@ -398,32 +398,270 @@
 nt, 
-final PrintStream output
+PrintStream stream) %7B%0A    StringBuilder builder = new StringBuilder();%0A    dumpFormattingModel(block, indent, builder);%0A    stream.print(builder.toString());%0A  %7D%0A%0A  public static void dumpFormattingModel(final Block block, int indent, final StringBuilder builder
 ) %7B%0A
@@ -689,30 +689,30 @@
 %7B%0A      
-output.println
+builder.append
 (%22--- FO
@@ -729,16 +729,18 @@
 ODEL ---
+%5Cn
 %22);%0A    
@@ -745,28 +745,30 @@
   %7D%0A    
-output.print
+builder.append
 (StringU
@@ -903,30 +903,31 @@
 lock(block, 
-output
+builder
 );%0A    %7D%0A   
@@ -957,22 +957,23 @@
 (block, 
-output
+builder
 );%0A     
@@ -1204,38 +1204,39 @@
 cing, indent+2, 
-output
+builder
 );%0A          %7D%0A 
@@ -1322,22 +1322,23 @@
 dent+2, 
-output
+builder
 );%0A     
@@ -1416,85 +1416,65 @@
 nal 
-PrintStream output) %7B%0A    StringBuilder blockData = new StringBuilder(%22%5C%22%22 + 
+StringBuilder builder) %7B%0A    builder.append(%22%5C%22%22).append(
 getB
@@ -1488,19 +1488,25 @@
 t(block)
- + 
+).append(
 %22%5C%22%22);%0A 
@@ -1540,58 +1540,40 @@
 k, b
-lockData);%0A    output.println(blockData.toString()
+uilder);%0A    builder.append(%22%5Cn%22
 );%0A 
@@ -1862,77 +1862,51 @@
 nal 
-PrintStream output) %7B%0A    StringBuilder blockData = new StringBuilder
+StringBuilder builder) %7B%0A    builder.append
 (%22%3Cb
@@ -1954,32 +1954,30 @@
 k) %7B%0A      b
-lockData
+uilder
 .append(((AS
@@ -2061,85 +2061,41 @@
 k, b
-lockData);%0A    blockData.append(%22%3E%22);%0A    output.println(blockData.toString()
+uilder);%0A    builder.append(%22%3E%5Cn%22
 );%0A 
@@ -2653,27 +2653,29 @@
 , final 
-PrintStream
+StringBuilder
  out) %7B%0A
@@ -2682,21 +2682,22 @@
     out.
-print
+append
 (StringU
@@ -2740,15 +2740,14 @@
 out.
-println
+append
 (%22sp
@@ -2758,18 +2758,37 @@
 g: %22
- + spacing
+).append(spacing).append(%22%5Cn%22
 );%0A 

use StringBuilder instead of PrintStream for dumping formatting model