package com.moandjiezana.toml;

import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;

class WriterContext {
  private String key = "";
  private String currentTableIndent = "";
  private String currentFieldIndent = "";
  private String arrayKey = null;
  private boolean isArrayOfTable = false;
  private boolean empty = true;
  private final TomlWriter tomlWriter;
  private final Writer output;

  WriterContext(TomlWriter tomlWriter, Writer output) {
    this.tomlWriter = tomlWriter;
    this.output = output;
  }

  WriterContext pushTable(String newKey) {
    String newIndent = "";
    if (!key.isEmpty()) {
      newIndent = growIndent(tomlWriter.getIndentationPolicy());
    }

    String fullKey = key + (key.isEmpty() ? newKey : "." + newKey);

    WriterContext subContext = new WriterContext(fullKey, newIndent, output, tomlWriter);
    if (!empty) {
      subContext.empty = false;
    }
    
    return subContext;
  }

  WriterContext pushTableFromArray() {
    WriterContext subContext = new WriterContext(key, currentTableIndent, output, tomlWriter);
    if (!empty) {
      subContext.empty = false;
    }
    subContext.setIsArrayOfTable(true);

    return subContext;
  }
  
  WriterContext write(String s) {
    try {
      output.write(s);
      if (s != null && !s.isEmpty()) {
        empty = false;
      }
      
      return this;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  void write(char[] chars) {
    for (char c : chars) {
      write(c);
    }
  }
  
  WriterContext write(char c) {
    try {
      output.write(c);
      empty = false;
      
      return this;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  void writeKey() {
    if (key.isEmpty()) {
      return;
    }

    if (!empty) {
      write('\n');
    }

    write(currentTableIndent);

    if (isArrayOfTable) {
      write("[[").write(key).write("]]\n");
    } else {
      write('[').write(key).write("]\n");
    }
  }

  void writeArrayDelimiterPadding() {
    for (int i = 0; i < tomlWriter.getIndentationPolicy().getArrayDelimiterPadding(); i++) {
      write(' ');
    }
  }

  void indent() {
    if (!key.isEmpty()) {
      write(currentFieldIndent);
    }
  }

  WriterContext setIsArrayOfTable(boolean isArrayOfTable) {
    this.isArrayOfTable = isArrayOfTable;
    return this;
  }

  private String growIndent(WriterIndentationPolicy indentationPolicy) {
    return currentTableIndent + fillStringWithSpaces(indentationPolicy.getTableIndent());
  }

  private String fillStringWithSpaces(int count) {
    char[] chars = new char[count];
    Arrays.fill(chars, ' ');

    return new String(chars);
  }

  private WriterContext(String key, String tableIndent, Writer output, TomlWriter tomlWriter) {
    this.key = key;
    this.currentTableIndent = tableIndent;
    this.currentFieldIndent = tableIndent + fillStringWithSpaces(tomlWriter.getIndentationPolicy().getKeyValueIndent());
    this.output = output;
    this.tomlWriter = tomlWriter;
  }

  public TomlWriter getTomlWriter() {
    return tomlWriter;
  }

  public WriterContext setArrayKey(String arrayKey) {
    this.arrayKey = arrayKey;
    return this;
  }

  public String getContextPath() {
    return key.isEmpty() ? arrayKey : key + "." + arrayKey;
  }
}

@@ -145,16 +145,23 @@
 ing 
-k
+arrayK
 ey = 
-%22%22
+null
 ;%0A  
@@ -172,80 +172,70 @@
 ate 
-String currentTableIndent = %22%22;%0A  private String currentFieldIndent = %22%22
+boolean isArrayOfTable = false;%0A  private boolean empty = true
 ;%0A  
@@ -246,104 +246,110 @@
 ate 
+final 
 String 
-arrayKey = null;%0A  private boolean isArrayOfTable = false;%0A  private boolean empty = true
+key;%0A  private final String currentTableIndent;%0A  private final String currentFieldIndent
 ;%0A  
@@ -415,16 +415,75 @@
  output;
+%0A  private final WriterIndentationPolicy indentationPolicy;
 %0A%0A  Writ
@@ -544,58 +544,36 @@
 this
-.tomlWriter = tomlWriter;%0A    this.output = output
+(%22%22, %22%22, output, tomlWriter)
 ;%0A  
@@ -700,31 +700,17 @@
 wIndent(
-tomlWriter.getI
+i
 ndentati
@@ -717,18 +717,16 @@
 onPolicy
-()
 );%0A    %7D
@@ -755,15 +755,8 @@
  key
- + (key
 .isE
@@ -772,16 +772,22 @@
 newKey :
+ key +
  %22.%22 + n
@@ -791,17 +791,16 @@
 + newKey
-)
 ;%0A%0A    W
@@ -2090,31 +2090,17 @@
  0; i %3C 
-tomlWriter.getI
+i
 ndentati
@@ -2103,26 +2103,24 @@
 tationPolicy
-()
 .getArrayDel
@@ -2816,24 +2816,114 @@
 .key = key;%0A
+    this.output = output;%0A    this.indentationPolicy = tomlWriter.getIndentationPolicy();%0A
     this.cur
@@ -3019,30 +3019,21 @@
 Spaces(t
-omlWriter.getI
+his.i
 ndentati
@@ -3040,18 +3040,16 @@
 onPolicy
-()
 .getKeyV
@@ -3067,34 +3067,8 @@
 ));%0A
-    this.output = output;%0A
     

Streamline WriterContext constructors. Make instance variables final where possible.