// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.xml;

import java.io.*;
import java.net.*;

import org.apache.juneau.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.xml.annotation.*;

/**
 * Specialized writer for serializing XML.
 *
 * <ul class='notes'>
 * 	<li>
 * 		This class is not intended for external use.
 * </ul>
 */
public class XmlWriter extends SerializerWriter {

	private String defaultNsPrefix;
	private boolean enableNs;

	/**
	 * Constructor.
	 *
	 * @param out The wrapped writer.
	 * @param useWhitespace If <jk>true</jk> XML elements will be indented.
	 * @param maxIndent The maximum indentation level.
	 * @param trimStrings If <jk>true</jk>, strings should be trimmed before they're serialized.
	 * @param quoteChar The quote character to use for attributes.  Should be <js>'\''</js> or <js>'"'</js>.
	 * @param uriResolver The URI resolver for resolving URIs to absolute or root-relative form.
	 * @param enableNs Flag to indicate if XML namespaces are enabled.
	 * @param defaultNamespace The default namespace if XML namespaces are enabled.
	 */
	public XmlWriter(Writer out, boolean useWhitespace, int maxIndent, boolean trimStrings, char quoteChar,
			UriResolver uriResolver, boolean enableNs, Namespace defaultNamespace) {
		super(out, useWhitespace, maxIndent, trimStrings, quoteChar, uriResolver);
		this.enableNs = enableNs;
		this.defaultNsPrefix = defaultNamespace == null ? null : defaultNamespace.name;
	}

	/**
	 * Writes an opening tag to the output:  <code><xt>&lt;ns:name</xt></code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @param needsEncoding If <jk>true</jk>, element name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter oTag(String ns, String name, boolean needsEncoding) throws IOException {
		append('<');
		if (enableNs && ns != null && ! (ns.isEmpty() || ns.equals(defaultNsPrefix)))
			append(ns).append(':');
		if (needsEncoding)
			XmlUtils.encodeElementName(out, name);
		else
			append(name);
		return this;
	}

	/**
	 * Shortcut for <code>oTag(ns, name, <jk>false</jk>);</code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter oTag(String ns, String name) throws IOException {
		return oTag(ns, name, false);
	}

	/**
	 * Shortcut for <code>oTag(<jk>null</jk>, name, <jk>false</jk>);</code>
	 *
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter oTag(String name) throws IOException {
		return oTag(null, name, false);
	}

	/**
	 * Shortcut for <c>i(indent).oTag(ns, name, needsEncoding);</c>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @param needsEncoding If <jk>true</jk>, element name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter oTag(int indent, String ns, String name, boolean needsEncoding) throws IOException {
		return i(indent).oTag(ns, name, needsEncoding);
	}

	/**
	 * Shortcut for <code>i(indent).oTag(ns, name, <jk>false</jk>);</code>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter oTag(int indent, String ns, String name) throws IOException {
		return i(indent).oTag(ns, name, false);
	}

	/**
	 * Shortcut for <code>i(indent).oTag(<jk>null</jk>, name, <jk>false</jk>);</code>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter oTag(int indent, String name) throws IOException {
		return i(indent).oTag(null, name, false);
	}

	/**
	 * Closes a tag.
	 *
	 * <p>
	 * Shortcut for <code>append(<js>'>'</js>);</code>
	 *
	 * @return This object (for method chaining).
	 * @throws IOException Thrown by underlying stream.
	 */
	public XmlWriter cTag() throws IOException {
		append('>');
		return this;
	}

	/**
	 * Closes an empty tag.
	 *
	 * <p>
	 * Shortcut for <code>append(<js>'/'</js>).append(<js>'>'</js>);</code>
	 *
	 * @return This object (for method chaining).
	 * @throws IOException Thrown by underlying stream.
	 */
	public XmlWriter ceTag() throws IOException {
		append('/').append('>');
		return this;
	}

	/**
	 * Writes a closed tag to the output:  <code><xt>&lt;ns:name/&gt;</xt></code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @param needsEncoding If <jk>true</jk>, element name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter tag(String ns, String name, boolean needsEncoding) throws IOException {
		append('<');
		if (enableNs && ns != null && ! (ns.isEmpty() || ns.equals(defaultNsPrefix)))
			append(ns).append(':');
		if (needsEncoding)
			XmlUtils.encodeElementName(out, name);
		else
			append(name);
		return append('/').append('>');
	}

	/**
	 * Shortcut for <code>tag(ns, name, <jk>false</jk>);</code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter tag(String ns, String name) throws IOException {
		return tag(ns, name, false);
	}

	/**
	 * Shortcut for <code>tag(<jk>null</jk>, name, <jk>false</jk>);</code>
	 *
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter tag(String name) throws IOException {
		return tag(null, name, false);
	}

	/**
	 * Shortcut for <code>i(indent).tag(<jk>null</jk>, name, <jk>false</jk>);</code>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter tag(int indent, String name) throws IOException {
		return i(indent).tag(name);
	}

	/**
	 * Shortcut for <c>i(indent).tag(ns, name, needsEncoding);</c>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @param needsEncoding If <jk>true</jk>, element name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter tag(int indent, String ns, String name, boolean needsEncoding) throws IOException {
		return i(indent).tag(ns, name, needsEncoding);
	}

	/**
	 * Shortcut for <code>i(indent).tag(ns, name, <jk>false</jk>);</code>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter tag(int indent, String ns, String name) throws IOException {
		return i(indent).tag(ns, name);
	}


	/**
	 * Writes a start tag to the output:  <code><xt>&lt;ns:name&gt;</xt></code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @param needsEncoding If <jk>true</jk>, element name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter sTag(String ns, String name, boolean needsEncoding) throws IOException {
		return oTag(ns, name, needsEncoding).append('>');
	}

	/**
	 * Shortcut for <code>sTag(ns, name, <jk>false</jk>);</code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter sTag(String ns, String name) throws IOException {
		return sTag(ns, name, false);
	}

	/**
	 * Shortcut for <code>sTag(<jk>null</jk>, name, <jk>false</jk>);</code>
	 *
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter sTag(String name) throws IOException {
		return sTag(null, name);
	}

	/**
	 * Shortcut for <c>i(indent).sTag(ns, name, needsEncoding);</c>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @param needsEncoding If <jk>true</jk>, element name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter sTag(int indent, String ns, String name, boolean needsEncoding) throws IOException {
		return i(indent).sTag(ns, name, needsEncoding);
	}

	/**
	 * Shortcut for <code>i(indent).sTag(ns, name, <jk>false</jk>);</code>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter sTag(int indent, String ns, String name) throws IOException {
		return i(indent).sTag(ns, name, false);
	}

	/**
	 * Shortcut for <code>i(indent).sTag(<jk>null</jk>, name, <jk>false</jk>);</code>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter sTag(int indent, String name) throws IOException {
		return i(indent).sTag(null, name, false);
	}


	/**
	 * Writes an end tag to the output:  <code><xt>&lt;/ns:name&gt;</xt></code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @param needsEncoding If <jk>true</jk>, element name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter eTag(String ns, String name, boolean needsEncoding) throws IOException {
		append('<').append('/');
		if (enableNs && ns != null && ! (ns.isEmpty() || ns.equals(defaultNsPrefix)))
			append(ns).append(':');
		if (needsEncoding)
			XmlUtils.encodeElementName(out, name);
		else
			append(name);
		return append('>');
	}

	/**
	 * Shortcut for <code>eTag(ns, name, <jk>false</jk>);</code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter eTag(String ns, String name) throws IOException {
		return eTag(ns, name, false);
	}

	/**
	 * Shortcut for <code>eTag(<jk>null</jk>, name, <jk>false</jk>);</code>
	 *
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter eTag(String name) throws IOException {
		return eTag(null, name);
	}

	/**
	 * Shortcut for <c>i(indent).eTag(ns, name, needsEncoding);</c>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @param needsEncoding If <jk>true</jk>, element name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter eTag(int indent, String ns, String name, boolean needsEncoding) throws IOException {
		return i(indent).eTag(ns, name, needsEncoding);
	}

	/**
	 * Shortcut for <code>i(indent).eTag(ns, name, <jk>false</jk>);</code>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter eTag(int indent, String ns, String name) throws IOException {
		return i(indent).eTag(ns, name, false);
	}

	/**
	 * Shortcut for <code>i(indent).eTag(<jk>null</jk>, name, <jk>false</jk>);</code>
	 *
	 * @param indent The number of prefix tabs to add.
	 * @param name The element name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter eTag(int indent, String name) throws IOException {
		return i(indent).eTag(name);
	}

	/**
	 * Writes an attribute to the output:  <code><xa>ns:name</xa>=<xs>'value'</xs></code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The attribute name.
	 * @param value The attribute value.
	 * @param valNeedsEncoding If <jk>true</jk>, attribute name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter attr(String ns, String name, Object value, boolean valNeedsEncoding) throws IOException {
		return oAttr(ns, name).q().attrValue(value, valNeedsEncoding).q();
	}

	/**
	 * Shortcut for <code>attr(<jk>null</jk>, name, value, <jk>false</jk>);</code>
	 *
	 * @param name The attribute name.
	 * @param value The attribute value.
	 * @param valNeedsEncoding If <jk>true</jk>, attribute name will be encoded.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter attr(String name, Object value, boolean valNeedsEncoding) throws IOException {
		return attr(null, name, value, valNeedsEncoding);
	}

	/**
	 * Shortcut for <code>attr(ns, name, value, <jk>false</jk>);</code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The attribute name.
	 * @param value The attribute value.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter attr(String ns, String name, Object value) throws IOException {
		return oAttr(ns, name).q().attrValue(value, false).q();
	}

	/**
	 * Same as {@link #attr(String, String, Object)}, except pass in a {@link Namespace} object for the namespace.
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The attribute name.
	 * @param value The attribute value.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter attr(Namespace ns, String name, Object value) throws IOException {
		return oAttr(ns == null ? null : ns.name, name).q().attrValue(value, false).q();
	}

	/**
	 * Shortcut for <code>attr(<jk>null</jk>, name, value, <jk>false</jk>);</code>
	 *
	 * @param name The attribute name.
	 * @param value The attribute value.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter attr(String name, Object value) throws IOException {
		return attr((String)null, name, value);
	}


	/**
	 * Writes an open-ended attribute to the output:  <code><xa>ns:name</xa>=</code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The attribute name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter oAttr(String ns, String name) throws IOException {
		append(' ');
		if (enableNs && ns != null && ! (ns.isEmpty() || ns.equals(defaultNsPrefix)))
			append(ns).append(':');
		append(name).append('=');
		return this;
	}

	/**
	 * Writes an open-ended attribute to the output:  <code><xa>ns:name</xa>=</code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The attribute name.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter oAttr(Namespace ns, String name) throws IOException {
		return oAttr(ns == null ? null : ns.name, name);
	}

	/**
	 * Writes an attribute with a URI value to the output:  <code><xa>ns:name</xa>=<xs>'uri-value'</xs></code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The attribute name.
	 * @param value The attribute value, convertible to a URI via <c>toString()</c>
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter attrUri(Namespace ns, String name, Object value) throws IOException {
		return attr(ns, name, uriResolver.resolve(value));
	}

	/**
	 * Writes an attribute with a URI value to the output:  <code><xa>ns:name</xa>=<xs>'uri-value'</xs></code>
	 *
	 * @param ns The namespace.  Can be <jk>null</jk>.
	 * @param name The attribute name.
	 * @param value The attribute value, convertible to a URI via <c>toString()</c>
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter attrUri(String ns, String name, Object value) throws IOException {
		return attr(ns, name, uriResolver.resolve(value), true);
	}

	/**
	 * Append an attribute with a URI value.
	 *
	 * @param name The attribute name.
	 * @param value The attribute value.  Can be any object whose <c>toString()</c> method returns a URI.
	 * @return This object (for method chaining);
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter attrUri(String name, Object value) throws IOException {
		return attrUri((String)null, name, value);
	}

	/**
	 * Shortcut for calling <code>text(o, <jk>false</jk>);</code>
	 *
	 * @param o The object being serialized.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred.
	 */
	public XmlWriter text(Object o) throws IOException {
		text(o, false);
		return this;
	}

	/**
	 * Serializes and encodes the specified object as valid XML text.
	 *
	 * @param o The object being serialized.
	 * @param preserveWhitespace
	 * 	If <jk>true</jk>, then we're serializing {@link XmlFormat#MIXED_PWS} or {@link XmlFormat#TEXT_PWS} content.
	 * @return This object (for method chaining).
	 * @throws IOException Thrown by underlying stream.
	 */
	public XmlWriter text(Object o, boolean preserveWhitespace) throws IOException {
		XmlUtils.encodeText(this, o, trimStrings, preserveWhitespace);
		return this;
	}

	/**
	 * Same as {@link #text(Object)} but treats the value as a URL to resolved then serialized.
	 *
	 * @param o The object being serialized.
	 * @return This object (for method chaining).
	 * @throws IOException Thrown by underlying stream.
	 */
	public XmlWriter textUri(Object o) throws IOException {
		text(uriResolver.resolve(o), false);
		return this;
	}

	private XmlWriter attrValue(Object o, boolean needsEncoding) throws IOException {
		if (needsEncoding)
			XmlUtils.encodeAttrValue(out, o, this.trimStrings);
		else if (o instanceof URI || o instanceof URL)
			append(uriResolver.resolve(o));
		else
			append(o);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter cr(int depth) throws IOException {
		super.cr(depth);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter cre(int depth) throws IOException {
		super.cre(depth);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter appendln(int indent, String text) throws IOException {
		super.appendln(indent, text);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter appendln(String text) throws IOException {
		super.appendln(text);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter append(int indent, String text) throws IOException {
		super.append(indent, text);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter append(int indent, char c) throws IOException {
		super.append(indent, c);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter s() throws IOException {
		super.s();
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter q() throws IOException {
		super.q();
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter i(int indent) throws IOException {
		super.i(indent);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter ie(int indent) throws IOException {
		super.ie(indent);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter nl(int indent) throws IOException {
		super.nl(indent);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter append(Object text) throws IOException {
		super.append(text);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter append(String text) throws IOException {
		super.append(text);
		return this;
	}

	@Override /* SerializerWriter */
	public XmlWriter append(char c) throws IOException {
		out.write(c);
		return this;
	}

	@Override /* Object */
	public String toString() {
		return out.toString();
	}
}
