/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.io;

import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
import java.io.Writer;
import net.ranides.assira.text.StringUtils;

/**
 * Writer, który dodaje do Writera dodatkową funkcjonalność ułatwiającą generowanie
 * tekstu z wcięciami. Wcięcia mogą być zagnieżdżane. Uwaga: writer współpracuje z 
 * unixowymi znakami nowej linii, nie zachowuje się w sposób zależny od platformy.
 * @author ranides
 */
public class IndentWriter extends Writer {
    
    private final Appendable delegator;
    private int prefix = 0;
    private int indentation = 4;
    private boolean indented;

    /**
     * Tworzy nowy writer generujący wynik do podanego delegatora.
     * @param delegator
     */
    public IndentWriter(Appendable delegator) {
        this.delegator = delegator;
    }
    
    /**
     * Zwiększa wcięcie tekstu o jeden poziom.
     */
    public void indent() {
        prefix += indentation;
    }
    
    /**
     * Zmniejsza wcięcie tekstu o jeden poziom.
     */
    public void outdent() {
        assert prefix >= 1;
        prefix -= indentation;
    }
    
    /**
     * Zwraca głębokość wcięcia.
     * @return
     */
    public int getIndentation() {
        return indentation;
    }

    /**
     * Ustawia poziom wcięcia tekstu na konkretną wartość.
     * @param indentation
     */
    public void setIndentation(int indentation) {
        this.indentation = indentation;
    }
    
    @Override
    public void close() throws IOException {
        if(delegator instanceof Closeable) {
            ((Closeable)delegator).close();
        }
    }

    @Override
    public void flush() throws IOException {
        if(delegator instanceof Flushable) {
            ((Flushable)delegator).flush();
        }
    }
    
    @Override
    public void write(char[] cbuf) throws IOException {
        write(cbuf, 0, cbuf.length);
    }

    @Override
    public void write(char[] cbuf, int off, int len) throws IOException {
        for(int i=off; i<len; i++) { write(cbuf[i]); }
    }
    
    @Override
    public void write(String str) throws IOException {
        write(str, 0, str.length());
    }
    
    @Override
    public void write(String str, int off, int len) throws IOException {
        for(int i=off; i<len; i++) { write(str.charAt(i)); }
    }

    @Override
    public void write(int chr) throws IOException {
        if('\n' == chr) {
            delegator.append((char)chr);
            indented = false;
        } else {
            if(!indented) {
                delegator.append( StringUtils.nCopies(prefix, ' ') );
                indented = true;
            }
            delegator.append((char)chr);
        }
    }
    
}
