/* OdLib_Css- Copyright (c) 2008-2010 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.opendocument.css.output;

import net.mapeadores.opendocument.css.output.ns.NameSpace;
import java.io.IOException;


/**
 *
 * @author Vincent Calame
 */
public class XMLWriter {

    private Appendable appendable;
    private int indentLength;
    private boolean aposEscaped = true;

    public XMLWriter(Appendable appendable, int indentLength) {
        this.indentLength = indentLength;
        this.appendable = appendable;
    }

    public void setAposEscaped(boolean aposEscaped) {
        this.aposEscaped = aposEscaped;
    }

    public boolean isAposEscaped() {
        return aposEscaped;
    }

    public void appendXMLDeclaration() throws IOException {
        append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    }

    public void appendStylesheet(String href, String type) throws IOException {
        appendIndent();
        append("<?xml-stylesheet href=\"");
        append(href);
        append("\" type=\"");
        append(type);
        append("\"?>");
    }

    public void appendCssStyleSheet(String href) throws IOException {
        appendStylesheet(href, "text/css");
    }

    public void appendDocType(String doctype) throws IOException {
        appendIndent();
        append("<!DOCTYPE ");
        append(doctype);
        append(">");
    }

    public void append(char c) throws IOException {
        appendable.append(c);
    }

    public void append(String s) throws IOException {
        appendable.append(s);
    }

    public void addEmptyElement(String tagname) throws IOException {
        startOpenTag(tagname);
        closeEmptyTag();
    }

    public void addSimpleElement(String tagname, String value) throws IOException {
        if ((value == null) || (value.length() == 0)) {
            return;
        }
        startOpenTag(tagname);
        endOpenTag(false);
        escape(value);
        closeTag(tagname, false, false);
    }

    public void addSimpleElement(String tagname, String attribute, String attributeValue, String value) throws IOException {
        startOpenTag(tagname);
        addAttribute(attribute, attributeValue);
        endOpenTag(false);
        escape(value);
        closeTag(tagname, false, false);
    }

    public void appendIndent() throws IOException {
        if (indentLength > - 1) {
            append('\n');
            for (int i = 0; i < indentLength; i++) {
                append('\t');
            }
        }
    }

    public int getCurrentIndentValue() {
        return indentLength;
    }

    public void increaseIndentValue() {
        indentLength++;
    }

    public void decreaseIndentValue() {
        indentLength--;
    }

    public void startOpenTag(String name) throws IOException {
        startOpenTag(name, true);
    }

    public void startOpenTag(String name, boolean indentBefore) throws IOException {
        if (indentBefore) {
            appendIndent();
        }
        append('<');
        append(name);
    }

    public void endOpenTag() throws IOException {
        endOpenTag(true);
    }

    public void endOpenTag(boolean increaseIndent) throws IOException {
        append('>');
        if (increaseIndent) {
            increaseIndentValue();
        }
    }

    public void closeEmptyTag() throws IOException {
        append('/');
        append('>');
    }

    public void openTag(String name) throws IOException {
        openTag(name, true, true);
    }

    public void openTag(String name, boolean indentBefore, boolean indentIncrease) throws IOException {
        if (indentBefore) {
            appendIndent();
        }
        append('<');
        append(name);
        append('>');
        if (indentIncrease) {
            increaseIndentValue();
        }
    }

    public void closeTag(String name) throws IOException {
        closeTag(name, true, true);
    }

    public void closeTag(String name, boolean indentBefore, boolean indentDecrease) throws IOException {
        if (indentDecrease) {
            decreaseIndentValue();
        }
        if (indentBefore) {
            appendIndent();
        }
        append('<');
        append('/');
        append(name);
        append('>');
    }

    public void escape(CharSequence charSequence) throws IOException {
        if (charSequence == null) {
            return;
        }
        int length = charSequence.length();
        for (int i = 0; i < length; i++) {
            char carac = charSequence.charAt(i);
            escape(carac);
        }
    }

    public void escape(char carac) throws IOException {
        if (carac < 32) {
            append(' ');
        } else {
            switch (carac) {
                case '&':
                    append("&amp;");
                    break;
                case '"':
                    append("&quot;");
                    break;
                case '\'':
                    if (aposEscaped) {
                        append("&apos;");
                    } else {
                        append(carac);
                    }
                    break;
                case '<':
                    append("&lt;");
                    break;
                case '>':
                    append("&gt;");
                    break;
                case '\u00A0':
                    append("&#x00A0;");
                    break;
                default:
                    append(carac);
            }
        }
    }

    public void addNameSpaceAttribute(NameSpace nameSpace) throws IOException {
        addNameSpaceAttribute(nameSpace.getPrefix(), nameSpace.getName());
    }

    public void addNameSpaceAttribute(String prefix, String nameSpace) throws IOException {
        if ((nameSpace == null) || (nameSpace.length() == 0)) {
            return;
        }
        append(' ');
        append("xmlns");
        if ((prefix != null) && (prefix.length() > 0)) {
            append(':');
            append(prefix);
        }
        append('=');
        append('\"');
        escape(nameSpace);
        append('\"');
    }

    public void addAttribute(String attributeName, String value) throws IOException {
        if ((value == null) || (value.length() == 0)) {
            return;
        }
        append(' ');
        append(attributeName);
        append('=');
        append('\"');
        escape(value);
        append('\"');
    }

    public void addAttribute(String attributeName, char c) throws IOException {
        append(' ');
        append(attributeName);
        append('=');
        append('\"');
        escape(c);
        append('\"');
    }

    public void addAttribute(String attributeName, int i) throws IOException {
        append(' ');
        append(attributeName);
        append('=');
        append('\"');
        append(String.valueOf(i));
        append('\"');
    }

}
