#include "xmllayout.h"
#include "xmlui.h"

const char* key_parent = "$parent";

// ----------------------------------------------------------------------------
CXmlAnchor::CXmlAnchor()
{
	m_relativeTo.clear();
	m_point				= eAnchor_Null;
	m_relativePoint		= eAnchor_Null;
}

// ----------------------------------------------------------------------------
int	CXmlAnchor::XmlValueToAnchorPoint( const char* valueStr )
{
	if ( valueStr )
	{
		if ( XMLString::compareString(valueStr, "TOPLEFT") == 0 )
			return eAnchor_TopLeft;
		else if ( XMLString::compareString(valueStr, "TOP") == 0 )
			return eAnchor_Top;
		else if ( XMLString::compareString(valueStr, "TOPRIGHT") == 0 )
			return eAnchor_TopRight;
		else if ( XMLString::compareString(valueStr, "LEFT") == 0 )
			return eAnchor_Left;
		else if ( XMLString::compareString(valueStr, "CENTER") == 0 )
			return eAnchor_Center;
		else if ( XMLString::compareString(valueStr, "RIGHT") == 0 )
			return eAnchor_Right;
		else if ( XMLString::compareString(valueStr, "BOTTOMLEFT") == 0 )
			return eAnchor_BottomLeft;
		else if ( XMLString::compareString(valueStr, "BOTTOM") == 0 )
			return eAnchor_Bottom;
		else if ( XMLString::compareString(valueStr, "BOTTOMRIGHT") == 0 )
			return eAnchor_BottomRight;
	}
	return eAnchor_Null;
}

// ----------------------------------------------------------------------------
bool CXmlAnchor::LoadFromDOMNode( const DOMNode* node )
{
	if ( node == NULL || node->getNodeType() != DOMNode::ELEMENT_NODE )
		return false;		
			
	// Attribute
	DOMNamedNodeMap* nodeMap = node->getAttributes();
	if ( nodeMap )
	{
		const XMLCh* nodeValue;
		if ( (nodeValue = GetNodeAttribute(nodeMap, "point")) != NULL )
		{
			char* tmp = XMLString::transcode(nodeValue);
			m_point = XmlValueToAnchorPoint(tmp);
			XMLString::release(&tmp);
		}
		if ( (nodeValue = GetNodeAttribute(nodeMap, "relativeTo")) != NULL )
		{
			char* tmp = XMLString::transcode(nodeValue);
			m_relativeTo = tmp;
			XMLString::release(&tmp);
		}
		if ( (nodeValue = GetNodeAttribute(nodeMap, "relativePoint")) != NULL )
		{
			char* tmp = XMLString::transcode(nodeValue);
			m_relativePoint = XmlValueToAnchorPoint(tmp);
			XMLString::release(&tmp);
		}
	}

	// Element
	node = node->getFirstChild();
	while ( node )
	{
		if ( node->getNodeType() == DOMNode::ELEMENT_NODE )
		{
			char* nodeName = XMLString::transcode(node->getNodeName());

			// Offset
			if ( XMLString::compareString(nodeName, "Offset") == 0 )
			{
				m_offset.LoadFromDOMNode(node);
			}
			XMLString::release(&nodeName);
		}
		node = node->getNextSibling();
	}

	return true;
}

// ----------------------------------------------------------------------------
CXmlAnchors::CXmlAnchors()
{
	m_vector.clear();
}

// ----------------------------------------------------------------------------
bool CXmlAnchors::LoadFromDOMNode(const DOMNode* node)
{
	if ( node == NULL || node->getNodeType() != DOMNode::ELEMENT_NODE )
		return false;

	// Element
	node = node->getFirstChild();
	while ( node )
	{
		if ( node->getNodeType() == DOMNode::ELEMENT_NODE )
		{
			char* nodeName = XMLString::transcode(node->getNodeName());
			if ( XMLString::compareString(nodeName, "Anchor") == 0 )
			{
				CXmlAnchor anchor;
				anchor.LoadFromDOMNode(node);				
				m_vector.push_back(anchor);
			}
			XMLString::release(&nodeName);
		}
		node = node->getNextSibling();
	}

	return true;
}

// ----------------------------------------------------------------------------
CXmlLayout::CXmlLayout(CXmlUi* pUi, CXmlLayout* pParent)
{
	m_type				= eXmlUiType_Layout;

	m_name.clear();	

	m_parent			= pParent;
	m_isVisible			= true;
	m_isVirtual			= false;
	m_pXmlUi			= pUi;
}

// ----------------------------------------------------------------------------
CXmlLayout::~CXmlLayout()
{
}

// ----------------------------------------------------------------------------
bool CXmlLayout::LoadFromDOMNode(const DOMNode* node)
{
	bool isResult = CXmlNode::LoadFromDOMNode(node);
	if ( isResult )
	{
		if (m_pXmlUi && !m_name.empty())
			m_pXmlUi->AddName(m_name.c_str(), this);		// 加入索引表
	}
	return isResult;
}

// ----------------------------------------------------------------------------
void CXmlLayout::LoadNodeAttribute(const DOMNamedNodeMap* nodeMap)
{
	const XMLCh* nodeValue;
	if ( (nodeValue = GetNodeAttribute(nodeMap, "virtual")) != NULL )
	{
		char* tmp = XMLString::transcode(nodeValue);
		m_isVirtual = XmlValueToBoolean(tmp);
		XMLString::release(&tmp);
	}
	if ( (nodeValue = GetNodeAttribute(nodeMap, "name")) != NULL )
	{
		char* tmp = XMLString::transcode(nodeValue);
		m_name = tmp;
		XMLString::release(&tmp);
	}	
	if ( (nodeValue = GetNodeAttribute(nodeMap, "inherits")) != NULL )
	{
		if (m_pXmlUi)
		{
			char* tmp = XMLString::transcode(nodeValue);
			CXmlLayout* pXmlLayout = m_pXmlUi->FindByName(tmp);
			if (pXmlLayout)
			{
				if (!pXmlLayout->m_isVirtual)
				{
					// 不能繼承非虛擬物件
					assert(false);
				}
				else
					Inherit(pXmlLayout);		// 繼承
			}
			else
				// 繼承物件不存在
				assert(false);

			XMLString::release(&tmp);
		}
	}	
	if ( (nodeValue = GetNodeAttribute(nodeMap, "hidden")) != NULL )
	{
		char* tmp = XMLString::transcode(nodeValue);
		m_isVisible = !XmlValueToBoolean(tmp);
		XMLString::release(&tmp);
	}

	if (m_parent)
	{
		m_isVirtual = m_parent->m_isVirtual;
	}

	if (!m_isVirtual)
	{
		ChangeName(m_name);
	}
}

// ----------------------------------------------------------------------------
void CXmlLayout::LoadNodeElement(const DOMNode* node, const char* nodeName)
{
	// Size
	if ( XMLString::compareString(nodeName, "Size") == 0 )
	{
		m_size.LoadFromDOMNode(node);
	}
	// Anchor
	else if ( XMLString::compareString(nodeName, "Anchors") == 0 )
	{
		m_anchors.LoadFromDOMNode(node);
	}

	// 若產生實體則需將名稱做置換
	if (!m_isVirtual)
	{
		vector<CXmlAnchor>& anchors = m_anchors.m_vector;
		for (vector<CXmlAnchor>::iterator iter = anchors.begin(); iter != anchors.end(); iter++)
			ChangeName((*iter).m_relativeTo);
	}
}

// ----------------------------------------------------------------------------
void CXmlLayout::Inherit(CXmlLayout* pXmlLayout)
{
	if (pXmlLayout)
	{		
		m_anchors	= pXmlLayout->m_anchors;
		m_size		= pXmlLayout->m_size;
		m_isVisible = pXmlLayout->m_isVisible;

		if (m_parent)
			m_isVirtual = m_parent->m_isVirtual;

		// 若是虛擬名稱則將名稱繼承
		if ( strncmp(pXmlLayout->m_name.c_str(), key_parent, strlen(key_parent)) == 0 )
			m_name = pXmlLayout->m_name;

		if (!m_isVirtual)
		{
			ChangeName(m_name);

			vector<CXmlAnchor>& anchors = m_anchors.m_vector;
			for (vector<CXmlAnchor>::iterator iter = anchors.begin(); iter != anchors.end(); iter++)
				ChangeName((*iter).m_relativeTo);
		}
	}
}

// ----------------------------------------------------------------------------
void CXmlLayout::ChangeName(string &str)
{	
	if ( strncmp(str.c_str(), key_parent, strlen(key_parent)) == 0 )
	{
		const char* tmp = str.c_str() + strlen(key_parent);
		if (m_parent)
			str = m_parent->m_name + tmp;
		else
			str = tmp;
	}
}