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

package net.ranides.assira.xml;

import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import net.ranides.assira.text.Charsets;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class XMLWriter implements AutoCloseable, Closeable {
    
    

    
    private final Writer writer;
    
    private final Transformer transformer;
    
    public XMLWriter() {
        this((Writer)null);
    }
    
    public XMLWriter(File file) throws FileNotFoundException {
        this(new FileOutputStream(file));
    }

    public XMLWriter(OutputStream ostream) {
        this(new OutputStreamWriter(ostream, Charsets.UTF8));
    }
    
    public XMLWriter(Writer writer) {
        try {
            this.writer = writer;
            this.transformer = TransformerFactory.newInstance().newTransformer();
        } catch(TransformerFactoryConfigurationError | TransformerConfigurationException cause) {
            throw new XMLException(cause);
        }
    }
    
    public XMLWriter write(XMLElement document) throws IOException {
        document.apply(transformer, new StreamResult(writer));
        return this;
    }
    
    public String toString(XMLElement document) {
        StringWriter out = new StringWriter();
        document.apply(transformer, new StreamResult(out));
        return out.toString();
    }


    @Override
    public void close() throws IOException {
        if(null != writer) {
            writer.close();
        }
    }
    
    public XMLWriter param(XMLOptions param, String value) {
        return param(param.key(), value);
    }
    
    public XMLWriter param(String param, String value) {
        transformer.setOutputProperty(param, value);
        return this;
    }
    
    public XMLWriter indent(int size) {
        if(size == 0) {
            param(XMLOptions.INDENT, "no");
        } else {
            // we want to put "root tag" in new line after <?xml declaration?>
            // DOCTYPE is workaround for strage bug in JDK formatter
            param(XMLOptions.DOCTYPE_PUBLIC, ""); 
            param(XMLOptions.INDENT, "yes");
            param(XMLOptions.INDENT_AMOUNT, String.valueOf(size));
        }
        return this;
    }

}
