/** @file xmlencoder.cpp
 *  Encoder implementation for XML
 * 	@headerfile xmlencoder.h "EABaseTypesXml/xmlencoder.h"
 *	@author Chris Burns (cburns@ea.com)
 *
 *	CTUI
 *	(c) 2013 Electronic Arts Inc. 
 */

#include "EABaseTypesXml/xmlencoder.h"

#include "UTFXml/XmlWriter.h"

namespace EA
{
	namespace Types
	{
		XmlEncoder::XmlEncoder(EA::Allocator::ICoreAllocator* allocator, EA::XML::XmlWriter *writer):
            mAllocator(allocator),
			mWriter(writer)
		{
		}

		XmlEncoder::~XmlEncoder()
		{
		}

		void XmlEncoder::Reset()
		{
			EA_FAIL_MESSAGE("EA::XML::XmlWriter doesn't support reset - we'll have to work around this if we ever need to reset");
		}

		void XmlEncoder::BeginArray()
		{
			mWriter->BeginElement("Array");
		}

		void XmlEncoder::EndArray()
		{
			mWriter->EndElement("Array");
		}

		void XmlEncoder::BeginObject()
		{
			mWriter->BeginElement("Object");
		}

		void XmlEncoder::EndObject()
		{
			mWriter->EndElement("Object");
		}

		void XmlEncoder::BeginObjectValue(const char* key, size_t length)
		{
			mWriter->BeginElement("Value");
            EA::RawString k(mAllocator);
			k.assign(key, (EA::RawString::size_type)length); // key might not actually be null-terminated
            mWriter->AppendAttribute("key", k.c_str());
		}
        
        void XmlEncoder::EndObjectValue(const char* key, size_t length)
        {
            mWriter->EndElement("Value");
        }

		void XmlEncoder::Boolean(bool boolean)
		{
			mWriter->BeginElement("Boolean");
            mWriter->AppendAttribute("value", boolean ? "1" : "0");
            mWriter->EndElement("Boolean");
		}

		void XmlEncoder::Number(EA::BaseTypeFloat number)
		{
            mWriter->BeginElement("Number");
            
            EA::RawString v(mAllocator);
            
			int64_t truncated = static_cast<int64_t>(number);

			if(static_cast<EA::BaseTypeFloat>(truncated) == number)
			{
                v.sprintf("%ld", truncated); 
			}
			else
			{
				v.sprintf("%f", number);
			}
            
            mWriter->AppendAttribute("value", v.c_str());
            
            mWriter->EndElement("Number");
		}

		void XmlEncoder::String(const char* str, size_t length)
		{
			mWriter->BeginElement("String");
            EA::RawString v(mAllocator);
			v.assign(str, (EA::RawString::size_type)length);
            mWriter->AppendAttribute("value", v.c_str());
            mWriter->EndElement("String");
		}

		void XmlEncoder::Function(FunctionIn function)
		{
			mWriter->BeginElement("Function");
            mWriter->WriteComment("We can't really encode a Function as XML - you must use a proxy");
            mWriter->EndElement("Function");
		}

		void XmlEncoder::UserData(UserDataIn userData)
		{
			mWriter->BeginElement("UserData");
            mWriter->WriteComment("We can't really encode a UserData as XML - you must use a proxy");
            mWriter->EndElement("UserData");
		}

		void XmlEncoder::Null()
		{
			mWriter->BeginElement("Null");
            mWriter->EndElement("Null");
		}
	}
}
