// CategoryInfoList.cpp
//

#include "stdafx.h"
#include "XmlGuiCategoryInfoList.h"
#include "XmlGuiCategoryInfo.h"
#include "XmlClassInfo.h"

CXmlGuiCategoryInfoList::CXmlGuiCategoryInfoList():
	classInfo_(NULL),
	sorted_(true)
{

}

CXmlGuiCategoryInfoList::~CXmlGuiCategoryInfoList()
{
	Clear();
}

CXmlGuiCategoryInfo* CXmlGuiCategoryInfoList::InsertCategory(int index)
{
	if (index < 0)
		return NULL;

	CXmlGuiCategoryInfo* newCategory;

	newCategory = new CXmlGuiCategoryInfo;

	if (index >= categories_.size()) {
		categories_.push_back(newCategory);
	} else { 
		CategoryList::iterator it;
		int i = 0;

		for (it = categories_.begin(); it != categories_.end(); it++) {
			if (i == index) {
				categories_.insert(it, newCategory);	
				break;
			}
			i++;
		}
	}

	return newCategory;
}

void CXmlGuiCategoryInfoList::MoveUpCategory(int index)
{
	if (index == 0)
		return;

	MoveCategory(index, index - 1);
}

void CXmlGuiCategoryInfoList::MoveDownCategory(int index)
{
	if (index >= categories_.size() - 1)
		return;

	MoveCategory(index, index + 1);
}

void CXmlGuiCategoryInfoList::Clear()
{
	for (int i = 0; i < categories_.size(); i++)
		delete categories_[i];

	categories_.clear();
}

void CXmlGuiCategoryInfoList::MoveCategory(int oldIndex, int newIndex)
{
	CXmlGuiCategoryInfo* categoryInfo;
	CategoryList::iterator it;
	int i;

	// search and delete element at "oldIndex" position
	//
	i = 0;
	for (it = categories_.begin(); it != categories_.end(); it++) {
		if (i == oldIndex) {
			categoryInfo = *it;
			categories_.erase(it);
			break;
		}
		i++;
	}

	// insert element at "newIndex" position
	//
	i = 0;
	for (it = categories_.begin(); it != categories_.end(); it++) {
		if (i == newIndex) {
			categories_.insert(it, categoryInfo);
			return;
		}
		i++;
	}

	categories_.push_back(categoryInfo);

}

int CXmlGuiCategoryInfoList::GetSize()
{
	return categories_.size();
}

CXmlGuiCategoryInfo* CXmlGuiCategoryInfoList::GetCategory(int index)
{
	if (index < 0 || index >= categories_.size())
		return NULL;

	return categories_[index];
}

void CXmlGuiCategoryInfoList::RemoveCategory(int index)
{
	if (index < 0 || index >= categories_.size())
		return;

	delete categories_[index];
	categories_.erase(categories_.begin() + index);
}

void CXmlGuiCategoryInfoList::RemoveCategory(const cmString& caption)
{
	for (int i = 0; i < categories_.size(); i++) {
		if (categories_[i]->GetCaption() == caption) {
			RemoveCategory(i);
			break;
		}
	}
}

void CXmlGuiCategoryInfoList::RemoveCategory(CXmlGuiCategoryInfo* categoryInfo)
{
	for (int i = 0; i < categories_.size(); i++) {
		if (categories_[i] == categoryInfo) {
			RemoveCategory(i);
			break;
		}
	}
}

bool CXmlGuiCategoryInfoList::BuildFromXml(IXMLDOMNode* node)
{
	IXMLDOMNode* childNode;
	IXMLDOMNodeList* children;
	CXmlGuiCategoryInfo* newCat;
	HRESULT hRes;
	long i;
	long size;
	CComBSTR nodeName;
	CComVariant nodeValue;

	Clear();

	hRes = node->get_childNodes(&children);
	
	children->get_length(&size);
	for (i = 0; i < size; i++) {
		hRes = children->get_item(i, &childNode);
		hRes = childNode->get_nodeName(&nodeName);
		hRes = childNode->get_nodeTypedValue(&nodeValue);

		if (wcscmp(nodeName, _T("Sorted")) == 0) {
			
			sorted_ = (_wtoi(nodeValue.bstrVal) == 1);
		} else if (CXmlGuiCategoryInfo::GetXmlNodeName() == nodeName) {
			newCat = new CXmlGuiCategoryInfo;

			newCat->SetClassInfo(classInfo_);
			newCat->BuildFromXml(childNode);
			
			categories_.push_back(newCat);
		}
	}

	return true;
}

bool CXmlGuiCategoryInfoList::AppendToDOMDocument(IXMLDOMDocument2* xmlDoc, 
												  IXMLDOMElement* parentElement)
{
	IXMLDOMElement* newElement;
	bool ret;
	HRESULT hr;

	hr = xmlDoc->createElement(CComBSTR((const TCHAR*)GetXmlNodeName()), &newElement);

	AppendMemberNode(_T("Sorted"), sorted_, newElement, xmlDoc);

	ret = CXmlBaseElement::AppendToDOMDocument(xmlDoc, newElement);
	if (!ret)
		return false;

	// serialize members
	//
	CXmlGuiCategoryInfo* categoryInfo;
	
	for (int i = 0; i < categories_.size(); i++) {
		categoryInfo = categories_[i];
		categoryInfo->AppendToDOMDocument(xmlDoc, newElement);
	}
	
	// append node to parent element
	//
	IXMLDOMNode* newOutNode;

	if (parentElement)
		hr = parentElement->appendChild(newElement, &newOutNode);
	else
		hr = xmlDoc->appendChild(newElement, &newOutNode);
	newOutNode->Release();

	return ret;	
}

CXmlGuiCategoryField* CXmlGuiCategoryInfoList::GetFieldByMemberName(const cmString& memberName)
{
	CXmlGuiCategoryField* ret = NULL;

	for (int i = 0; i < categories_.size(); i++) {
		ret = categories_[i]->GetFieldByMemberName(memberName);
		if (ret)
			break;
	}

	return ret;
}

CXmlGuiCategoryField* CXmlGuiCategoryInfoList::GetFieldByCaption(const cmString& caption)
{
	CXmlGuiCategoryField* ret = NULL;

	for (int i = 0; i < categories_.size(); i++) {
		ret = categories_[i]->GetFieldByCaption(caption);
		if (ret)
			break;
	}

	return ret;
}

CXmlGuiCategoryInfo* CXmlGuiCategoryInfoList::GetCategoryByCaption(const cmString& caption)
{
	CXmlGuiCategoryInfo* ret = NULL;

	for (int i = 0; i < categories_.size(); i++) {
		if (categories_[i]->GetCaption() == caption) {
			ret = categories_[i];
			break;
		}
	}

	return ret;
}

CXmlGuiCategoryInfo* CXmlGuiCategoryInfoList::GetCategoryByName(const cmString& name)
{
	CXmlGuiCategoryInfo* ret = NULL;

	for (int i = 0; i < categories_.size(); i++) {
		if (categories_[i]->GetName() == name) {
			ret = categories_[i];
			break;
		}
	}

	return ret;
}

void CXmlGuiCategoryInfoList::SetClassInfo(CXmlClassInfo* classInfo)
{
	classInfo_ = classInfo;

	for (int i = 0; i < categories_.size(); i++)
		categories_[i]->SetClassInfo(classInfo);
}

void CXmlGuiCategoryInfoList::SetSorted(bool sorted)
{
	sorted_ = sorted;
}

bool CXmlGuiCategoryInfoList::GetSorted() const
{
	return sorted_;
}

