package stexfires.io.properties;

import stexfires.core.consumer.ConsumerException;
import stexfires.core.record.KeyValueRecord;
import stexfires.io.internal.AbstractWritableConsumer;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Date;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static stexfires.io.properties.PropertiesFileSpec.*;

/**
 * @author Mathias Kalb
 * @since 0.1
 */
public class PropertiesConsumer extends AbstractWritableConsumer<KeyValueRecord> {

    private final PropertiesFileSpec fileSpec;

    public PropertiesConsumer(BufferedWriter writer, PropertiesFileSpec fileSpec) {
        super(writer);
        Objects.requireNonNull(fileSpec);
        this.fileSpec = fileSpec;
    }

    protected static String mapCharacter(char character, boolean escapeSpace, boolean escapeUnicode) {
        switch (character) {
            case ' ':
                return escapeSpace ? "\\ " : " ";
            case '\t':
                return "\\t";
            case '\n':
                return "\\n";
            case '\r':
                return "\\r";
            case '\f':
                return "\\f";
            case '\\':
                return "\\\\";
            case '=':
                return "\\=";
            case ':':
                return "\\:";
            case '#':
                return "\\#";
            case '!':
                return "\\!";
            default:
                if (((character < 0x0020) || (character > 0x007e)) & escapeUnicode) {
                    return "\\u" + String.format("%04X", (int) character);
                }
                return Character.toString(character);
        }
    }

    @Override
    public void writeBefore() throws IOException {
        super.writeBefore();
        if (fileSpec.isDateComment()) {
            write(COMMENT_PREFIX);
            write(new Date().toString());
            write(fileSpec.getLineSeparator().getSeparator());
        }
    }

    @Override
    public void writeRecord(KeyValueRecord record) throws IOException, ConsumerException {
        super.writeRecord(record);
        write(convertKey(record.getValueOfKeyField()));
        write(DELIMITER);
        write(convertValue(record.getValueField().getValueOrElse(NULL_VALUE)));
        write(fileSpec.getLineSeparator().getSeparator());
    }

    private String convertKey(String key) {
        return IntStream.range(0, key.length())
                        .mapToObj(i -> mapCharacter(key.charAt(i), true, fileSpec.isEscapeUnicode()))
                        .collect(Collectors.joining());
    }

    private String convertValue(String value) {
        return IntStream.range(0, value.length())
                        .mapToObj(i -> mapCharacter(value.charAt(i), i == 0, fileSpec.isEscapeUnicode()))
                        .collect(Collectors.joining());
    }

}


@@ -555,21 +555,23 @@
 %0A%0A    pr
-ivate
+otected
  final P
@@ -1730,32 +1730,594 @@
        %7D%0A    %7D%0A%0A
+    protected static String convertKey(String key, boolean escapeUnicode) %7B%0A        return IntStream.range(0, key.length())%0A                        .mapToObj(i -%3E mapCharacter(key.charAt(i), true, escapeUnicode))%0A                        .collect(Collectors.joining());%0A    %7D%0A%0A    protected static String convertValue(String value, boolean escapeUnicode) %7B%0A        return IntStream.range(0, value.length())%0A                        .mapToObj(i -%3E mapCharacter(value.charAt(i), i == 0, escapeUnicode))%0A                        .collect(Collectors.joining());%0A    %7D%0A%0A
     @Override%0A  
@@ -2783,16 +2783,44 @@
 yField()
+, fileSpec.isEscapeUnicode()
 ));%0A    
@@ -2921,332 +2921,44 @@
 LUE)
-));%0A        write(fileSpec.getLineSeparator().getSeparator());%0A    %7D%0A%0A    private String convertKey(String key) %7B%0A        return IntStream.range(0, key.length())%0A                        .mapToObj(i -%3E mapCharacter(key.charAt(i), true, fileSpec.isEscapeUnicode()))%0A                        .collect(Collectors.joining(
+, fileSpec.isEscapeUnicode()
 ));%0A    
 %7D%0A%0A 
@@ -2957,266 +2957,58 @@
     
-%7D%0A%0A
     
-private String convertValue(String value) %7B%0A        return IntStream.range(0, value.length())%0A                        .mapToObj(i -%3E mapCharacter(value.charAt(i), i == 0, fileSpec.isEscapeUnicode()))%0A                        .collect(Collectors.joining
+write(fileSpec.getLineSeparator().getSeparator
 ());

Change visibility of fileSpec from private to protected Change convert methods from private to protected static