package org.infinispan.protostream.annotations.impl;

import java.io.Writer;

/**
 * A Writer capable of appending Strings in a similar manner to StringWriter but with indentation capabilities to
 * support more readable code generation. No IOExceptions are ever thrown. Closing has no effect.
 *
 * @author anistor@redhat.com
 * @since 3.0
 */
public final class IndentWriter extends Writer {

   private final StringBuilder sb = new StringBuilder(256);

   /**
    * The 'equivalent' of one TAB character, because we do not use TABs.
    */
   private static final String TAB = "   ";
   private int indent = 0;
   private boolean indentNeeded = false;

   public IndentWriter() {
   }

   /**
    * Increase indentation.
    */
   public void inc() {
      indent++;
   }

   /**
    * Decrease indentation.
    */
   public void dec() {
      if (indent > 0) {
         indent--;
      }
   }

   @Override
   public void write(int c) {
      if (indentNeeded) {
         indentNeeded = false;
         for (int i = 0; i < indent; i++) {
            sb.append(TAB);
         }
      }
      sb.append((char) c);
      if (c == '\n') {
         indentNeeded = true;
      }
   }

   @Override
   public void write(char[] buf, int off, int len) {
      for (int i = off; i < off + len; i++) {
         write(buf[i]);
      }
   }

   @Override
   public void write(String s) {
      if (s == null) {
         s = "null";
      }
      write(s, 0, s.length());
   }

   @Override
   public void write(String s, int off, int len) {
      for (int i = off; i < off + len; i++) {
         write(s.charAt(i));
      }
   }

   @Override
   public IndentWriter append(CharSequence cs) {
      write(cs == null ? "null" : cs.toString());
      return this;
   }

   @Override
   public IndentWriter append(CharSequence cs, int start, int end) {
      if (cs == null) {
         cs = "null";
      }
      write(cs.subSequence(start, end).toString());
      return this;
   }

   @Override
   public IndentWriter append(char c) {
      write(c);
      return this;
   }

   @Override
   public String toString() {
      return sb.toString();
   }

   @Override
   public void flush() {
   }

   @Override
   public void close() {
   }
}

@@ -564,27 +564,26 @@
 nal 
-Str
 in
-g
+t
  TAB
- = %22   %22;
+_SIZE = 3;%0A
 %0A   
@@ -606,16 +606,17 @@
 nt = 0;%0A
+%0A
    priva
@@ -734,20 +734,28 @@
  public 
-void
+IndentWriter
  inc() %7B
@@ -771,16 +771,35 @@
 dent++;%0A
+      return this;%0A
    %7D%0A%0A  
@@ -848,20 +848,28 @@
  public 
-void
+IndentWriter
  dec() %7B
@@ -890,9 +890,10 @@
 ent 
-%3E
+==
  0) 
@@ -893,24 +893,73 @@
  == 0) %7B%0A   
+      throw new IllegalStateException();%0A      %7D%0A
       indent
@@ -960,33 +960,44 @@
 indent--;%0A      
-%7D
+return this;
 %0A   %7D%0A%0A   @Overr
@@ -1069,70 +1069,50 @@
     
-indentNeeded = false;%0A         for (int i = 0; i %3C indent; i++
+for (int i = indent * TAB_SIZE; i %3E 0; i--
 ) %7B%0A
@@ -1133,19 +1133,19 @@
 .append(
-TAB
+' '
 );%0A     
@@ -1189,34 +1189,8 @@
 c);%0A
-      if (c == '%5Cn') %7B%0A   
     
@@ -1210,21 +1210,18 @@
 d = 
-true;%0A      %7D
+c == '%5Cn';
 %0A   

Return this in IndentWriter.inc()/dec() to be able to chain calls