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

package net.ranides.assira.xml.impl;

import net.ranides.assira.xml.*;
import java.io.File;
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 W3Writer implements XMLWriter {
    
    private final XMLElement element;
    
    private final Transformer transformer;
    
    W3Writer(XMLElement element) {
        try {
            this.element = element;
            this.transformer = TransformerFactory.newInstance().newTransformer();
        } catch(TransformerFactoryConfigurationError | TransformerConfigurationException cause) {
            throw new XMLException(cause);
        }
    }
    
    @Override
    public W3Writer save(File file) throws IOException {
        try(FileOutputStream ostream = new FileOutputStream(file)) {
            return save(ostream);
        }
    }

    @Override
    public W3Writer save(OutputStream ostream) throws IOException {
        return save(new OutputStreamWriter(ostream, Charsets.UTF8));
    }

    @Override
    public W3Writer save(Writer writer) throws IOException {
        element.apply(transformer, new StreamResult(writer));
        return this;
    }
    
    @Override
    public String toString() {
        StringWriter out = new StringWriter();
        element.apply(transformer, new StreamResult(out));
        return out.toString();
    }
    
    @Override
    public W3Writer param(XMLOptions param, String value) {
        return param(param.key(), value);
    }
    
    @Override
    public W3Writer param(String param, String value) {
        transformer.setOutputProperty(param, value);
        return this;
    }
    
    @Override
    public W3Writer 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;
    }

}
