/* ************************************************************************
#
#  DivConq
#
#  http://divconq.com/
#
#  Copyright:
#    Copyright 2012 eTimeline, LLC. All rights reserved.
#
#  License:
#    See the license.txt file in the project's top-level directory for details.
#
#  Authors:
#    * Andy White
#
************************************************************************ */
package divconq.xml;

import divconq.lang.Memory;

/**
 * An XML element that simply contains text. This is normally a child element of
 * {@link XElement}.
 */
public class XText extends XNode implements Cloneable {
	/**
	 * The value of the TextElement.
	 */
	protected String content = null;
	protected boolean cdata = false;

	/**
	 * @param string text content to associate with this node
	 */
	public XText(String string) {
		this.setValue(string);
	}
	
	/**
	 * @param cdata flag to indicate that this text was stored within a CDATA section
	 * @param string text content to associate with this node
	 */
	public XText(boolean cdata, String string) {
		this.setValue(string);
		this.cdata = true;
	}

	/*  TODO
	@Override
	public Object clone() throws CloneNotSupportedException {
		TextElement newText = (TextElement) super.clone();
		
		if (integer != null)
			newText.integer = new Integer(integer.intValue());
		
		return newText;
	}
	*/
	
	/**
	 * Sets the value of this node
	 * 
	 * @param value the value to store 
	 */
	public void setValue(String value) {
		this.content = value;
		this.cdata = false;
	}

	/**
	 * 
	 * @return the value of this node
	 */
	public String getValue() {
		return this.content;
	}
	
	/**
	 * Sets this element to print as a CDATA section
	 * 
	 * @param cdata true if it should be printed as a CDATA section
	 */
	public void setCData(boolean cdata) {
		this.cdata = cdata;
	}

	/**
	 * @return true if this text is part of a CDATA section
	 */
	public boolean getCData() {
		return this.cdata;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		if (this.cdata) {
			return "<![CDATA[" + this.content + "]]>";

			/*  TODO fix to support ]]> in content
			 * 
			 * You do not escape the ]]> but you escape the > after ]] by inserting ]]><![CDATA[ before the >, think 
			 * of this just like a \ in C/Java/PHP/Perl string but only needed before a > and after a ]].
			 */
			
			
			//return this.cdataToString(this.content).toString();
		}
		
		// TODO do we need to escape this?
		return this.content;
	}

	/* (non-Javadoc)
	 * @see divconq.xml.XNode#toString(java.lang.StringBuffer, boolean, int)
	 */
	@Override
	protected StringBuffer toString(StringBuffer sb, boolean formatted, int level) {
		if (formatted) {
			sb.append("\n");
			for (int i = level; i > 0; i--)
				sb.append("  ");
		}
		
		if (this.cdata) {
			sb.append("<![CDATA[");
			sb.append(this.content);
			sb.append("]]>");

			/*  TODO fix to support ]]> in content
			 * 
			 * You do not escape the ]]> but you escape the > after ]] by inserting ]]><![CDATA[ before the >, think 
			 * of this just like a \ in C/Java/PHP/Perl string but only needed before a > and after a ]].
			 */
		}
		else
			sb.append(this.content);
		
		return sb;
	}

	/* (non-Javadoc)
	 * @see divconq.xml.XNode#toMemory(divconq.lang.Memory, boolean, int)
	 */
	@Override
	protected void toMemory(Memory sb, boolean formatted, int level) {
		if (formatted) {
			sb.write("\n");
			for (int i = level; i > 0; i--)
				sb.write("  ");
		}
		
		if (this.cdata) {
			sb.write("<![CDATA[");
			sb.write(this.content);

			/*  TODO fix to support ]]> in content
			 * 
			 * You do not escape the ]]> but you escape the > after ]] by inserting ]]><![CDATA[ before the >, think 
			 * of this just like a \ in C/Java/PHP/Perl string but only needed before a > and after a ]].
			 * 
			 * 
			int index = 0;		
			
			while ((index >= 0) && (index <= sb.length())) {
				index = sb.indexOf("]]>", index);
				
				if (index < 0)
					break;
				
				index += 3;
				sb.insert(index, "]]&gt;<![CDATA[");
			}
			*/
			
			sb.write("]]>");
		}
		else
			sb.write(this.content);
	}
}
