// CCppClassArrayGenerator.cpp
//
#include "stdafx.h"
#include "CSharpClassArrayGenerator.h"
#include "XmlProjectSettings.h"
#include "XmlClassInfo.h"
#include "XmlMemberInfo.h"

CCSharpClassArrayGenerator::CCSharpClassArrayGenerator()
{}

CCSharpClassArrayGenerator::~CCSharpClassArrayGenerator()
{}

void CCSharpClassArrayGenerator::Generate()
{
	// generate header file
	//
	///GenerateHeader();
	
	// generate implementation file
	//
	//GenerateImplementation();
}

/***	
void CCppClassArrayGenerator::GenerateHeader()
{
	cmString fileName;
	cmString pathName;

	Head_generateHeader();
	Head_generateIfDefBegin();
	Head_generateIncludeSection();
	Head_generateForwardDecl();
	Head_generateClassBegin();
	Head_generateConstructor();
	Head_generateDestructor();
	Head_generateMethods();
	Head_generateSerialization();
	Head_generateMembers();
	Head_generateClassEnd();
	Head_generateIfDefEnd();

	pathName = BuildGeneratedSourcePath() + _T("include\\");
	fileName = GetClassName() + GetCardinalityPostfix(classInfo_) + _T(".h");
	SaveFile(pathName + fileName, headCode_);

	hGeneratedFiles_[fileName] = pathName + fileName; 
}

void CCppClassArrayGenerator::Head_generateHeader()
{
	headCode_ += _T("// ") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T(".h") + xCrLf;
	headCode_ += _T("// ") + xCrLf; 
	headCode_ += GetGenerationTimeStamp();
}

void CCppClassArrayGenerator::Head_generateIfDefBegin()
{
	headCode_ += _T("#if !defined(") + DefineOf(GetClassName()) + GetCardinalityPostfix(classInfo_) + _T(")") + xCrLf;
	headCode_ += _T("#define ") + DefineOf(GetClassName()) + GetCardinalityPostfix(classInfo_) + xCrLf;
	headCode_ += xCrLf;
}

void CCppClassArrayGenerator::Head_generateIncludeSection()
{
	headCode_ += _T("#include <vector>") + xCrLf;
	headCode_ += _T("#include \"XmlSerializable.h\"") + xCrLf;
	headCode_ += _T("#include \"cmString.h\"") + xCrLf;

	// include contained class header
	//
	headCode_ += _T("#include \"") + GetClassName(classInfo_->GetName()) + _T(".h\"") + xCrLf;
	headCode_ += xCrLf;

	headCode_ += xCrLf;
	headCode_ += _T("using namespace std;") + xCrLf;
	headCode_ += xCrLf;
}

void CCppClassArrayGenerator::Head_generateForwardDecl()
{
}

void CCppClassArrayGenerator::Head_generateClassBegin()
{
	headCode_ += _T("class AFX_EXT_CLASS ") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T(": public CXmlSerializable") + xCrLf;
	headCode_ += _T("{") + xCrLf;
}

void CCppClassArrayGenerator::Head_generateConstructor()
{
	headCode_ += _T("public:") + xCrLf;
	headCode_ += xTab + GetClassName() + GetCardinalityPostfix(classInfo_) + _T("();") + xCrLf;
	headCode_ += xTab + GetClassName() + GetCardinalityPostfix(classInfo_) + _T("(const ") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T("& copy);") + xCrLf;
}

void CCppClassArrayGenerator::Head_generateDestructor()
{
	headCode_ += xTab + _T("virtual ~") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T("();") + xCrLf + xCrLf;
}

void CCppClassArrayGenerator::Head_generateMethods()
{
	headCode_ += xTab + _T("// utils") + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += _T("public:") + xCrLf;
	headCode_ += xTab + _T("void operator=(const ") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T("& copy);") + xCrLf + xCrLf;
	headCode_ += xTab + _T("void SetDefaults();")  + xCrLf;
	headCode_ += xTab + _T("void Clear();")  + xCrLf;
	headCode_ += xTab + _T("virtual cmString GetXmlNodeName(){return _T(\"") + classInfo_->GetName() + GetCardinalityPostfix(classInfo_) + _T("\");}") + xCrLf;
	headCode_ += xCrLf;
	headCode_ += xTab + _T("// access methods") + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += xTab + _T("int GetSize() const;") + xCrLf;
	headCode_ += xTab + _T("const ") + GetClassName() + _T("& operator[] (int index) const;") + xCrLf;
	headCode_ += xTab + GetClassName() + _T("& operator[] (int index);") + xCrLf;
	headCode_ += xTab + _T("void Insert(int index, const ") + GetClassName() + _T("& ") + GetCamelCase(classInfo_->GetName()) + _T(");") + xCrLf;
	headCode_ += xTab + _T("void Delete(int index);") + xCrLf;
	headCode_ += xCrLf;

	headCode_ += _T("protected:") + xCrLf;
	headCode_ += xTab + _T("void Copy(const ") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T("& copy);") + xCrLf;
	headCode_ += xCrLf;
}

void CCppClassArrayGenerator::Head_generateSerialization()
{
	headCode_ += xTab + _T("// serialization")+ xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += xTab + _T("public:") + xCrLf;
	headCode_ += xTab + _T("virtual bool BuildFromXml(IXMLDOMNode* node);") + xCrLf;
	headCode_ += xTab + _T("virtual bool AppendToDOMDocument(IXMLDOMDocument2* xmlDoc, IXMLDOMElement* parentElement);") + xCrLf;
	headCode_ += xCrLf;
}

void CCppClassArrayGenerator::Head_generateMembers()
{
	headCode_ += xTab + _T("// inner members") + xCrLf;
	headCode_ += xTab + _T("//") + xCrLf;
	headCode_ += _T("protected:") + xCrLf;

	headCode_ += xTab + _T("vector<") + GetClassName() + _T("> ") + GetCamelCase(classInfo_->GetName()+ GetCardinalityPostfix(classInfo_))  + _T("_;");
}

void CCppClassArrayGenerator::Head_generateClassEnd()
{
	headCode_ += xCrLf;
	headCode_ += _T("};") + xCrLf;
	headCode_ += xCrLf;
}

void CCppClassArrayGenerator::Head_generateIfDefEnd()
{
	headCode_ += _T("#endif //!defined(") + DefineOf(GetClassName() + GetCardinalityPostfix(classInfo_)) + _T(")") + xCrLf + xCrLf;
}

void CCppClassArrayGenerator::GenerateImplementation()
{
	cmString fileName;
	cmString pathName;

	Impl_generateHeader();
	Impl_generateIncludeSection();
	
	Impl_generateConstructor();
	Impl_generateDestructor();
	Impl_generateMethods();
	Impl_generateSerialization();

	pathName = BuildGeneratedSourcePath() + _T("src\\");
	fileName =  GetClassName() + GetCardinalityPostfix(classInfo_) +  _T(".cpp");
	SaveFile(pathName + fileName, implCode_);

	cppGeneratedFiles_[fileName] = pathName + fileName; 
}

void CCppClassArrayGenerator::Impl_generateHeader()
{
	implCode_ += _T("// ") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T(".cpp") + xCrLf;
	implCode_ += _T("// ") + xCrLf; 
	implCode_ += GetGenerationTimeStamp();
}

void CCppClassArrayGenerator::Impl_generateIncludeSection()
{
	implCode_ += _T("#include \"stdafx.h\"") + xCrLf;
	implCode_ += _T("#include \"") + GetClassName() + GetCardinalityPostfix(classInfo_) + _T(".h\"") + xCrLf;

	ClassMemberMap::iterator it;
	ClassMemberMap* members;
	CXmlBaseElement* member;
	cmString name;

	members = classInfo_->GetMembers();
	for(it = members->begin(); it != members->end(); it++) {
		member = it->second;
		if (member->GetDataType() == enDataType_Class) {
			CXmlClassInfo* classInfo;

			classInfo = dynamic_cast<CXmlClassInfo*>(member);
			if (classInfo->GetDefinitionInheritance())
				classInfo = dynamic_cast<CXmlClassInfo*>(rootClassInfo_->GetMemberById(classInfo->GetInherithClassId()));

			name = classInfo->GetName();
			implCode_ += _T("#include \"") + GetClassName(name) + _T(".h\"") + xCrLf;
		}
	}

	implCode_ +=  xCrLf;
}

void CCppClassArrayGenerator::Impl_generateConstructor()
{
	cmString p;

	p = GetCardinalityPostfix(classInfo_);

	// default constructor
	//
	implCode_ += GetClassName() + p + _T("::") + GetClassName() + p + _T("()") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("SetDefaults();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// copy constructor
	//
	implCode_ += GetClassName() + p + _T("::");
	implCode_ += GetClassName() + p;
	implCode_ += _T("(const ") + GetClassName()  + p + _T("& ");
	implCode_ += GetCamelCase(classInfo_->GetName())  + p + _T(")") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Copy(") + GetCamelCase(classInfo_->GetName()) + p + _T(");") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;
}

void CCppClassArrayGenerator::Impl_generateDestructor()
{
	cmString p;

	p = GetCardinalityPostfix(classInfo_);

	implCode_ += GetClassName() + p + _T("::~") + GetClassName() + p + _T("()") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Clear();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;
}

void CCppClassArrayGenerator::Impl_generateMethods()
{
	cmString p;

	p = GetCardinalityPostfix(classInfo_);
	// operator =
	//
	implCode_ += _T("void ") +  GetClassName() + p + _T("::operator=(const ") + GetClassName() + p + _T("& ") + GetCamelCase(classInfo_->GetName()) + p + _T(")") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Copy(") + GetCamelCase(classInfo_->GetName()) + p + _T(");") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// copy
	//
	cmString vectName;

	vectName = GetCamelCase(classInfo_->GetName()) + p;
	implCode_ += _T("void ") + GetClassName() + p + _T("::Copy(const ") + GetClassName() + p + _T("& ") + GetCamelCase(classInfo_->GetName()) + p + _T(")")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Clear();") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("for (int i = 0; i < ") + vectName + _T(".GetSize(); i++)") + xCrLf;
	implCode_ += xTab + xTab + vectName + _T("_.push_back(") + vectName + _T("[i]);") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// SetDefaults
	//
	implCode_ += _T("void ") + GetClassName() + p + _T("::SetDefaults()")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("Clear();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// SetDefaults
	//
	implCode_ += _T("void ") + GetClassName() + p + _T("::Clear()")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + vectName + _T("_.clear();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// GetSize
	//
	implCode_ += _T("int ") + GetClassName() + p + _T("::GetSize() const")  + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("return ") + vectName + _T("_.size();") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// operator []
	//
	implCode_ += _T("const ") + GetClassName() + _T("& ") + GetClassName() + p + _T("::operator[] (int index) const") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("return ") + vectName + _T("_[index];") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// operator []
	//
	implCode_ += GetClassName() + _T("& ") + GetClassName() + p + _T("::operator[] (int index)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("return ") + vectName + _T("_[index];") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// Insert
	//
	implCode_ += _T("void ") + GetClassName() + p + _T("::Insert(int index, const ") + GetClassName() + _T("& ") + GetCamelCase(classInfo_->GetName()) + _T(")") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + vectName + _T("_.insert(") + vectName + _T("_.begin() + index, ") + GetCamelCase(classInfo_->GetName()) + _T(");") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	// Delete
	//
	implCode_ += _T("void ") + GetClassName() + p + _T(":: Delete(int index)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + vectName + _T("_.erase(") + vectName + _T("_.begin() + index);") + xCrLf;
	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;
}

void CCppClassArrayGenerator::Impl_generateSerialization()
{
	ClassMemberMap::iterator it;
	cmString p;
	cmString arrayName;
	
	p = GetCardinalityPostfix(classInfo_);
	arrayName = GetCamelCase(classInfo_->GetName()) + p;

	//////////////////////////////////////////////////////////////////////
	// BuildFromXml
	//
	implCode_ += _T("bool ") + GetClassName() + p + _T("::BuildFromXml(IXMLDOMNode* node)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("USES_CONVERSION;") + xCrLf + xCrLf;

	implCode_ += xTab + _T("IXMLDOMNode* childNode;") + xCrLf;
    implCode_ += xTab + _T("IXMLDOMNodeList* children;") + xCrLf;
	implCode_ += xTab + _T("CComBSTR nodeName;") + xCrLf;
	implCode_ += xTab + _T("HRESULT hr;") + xCrLf;
	implCode_ += xTab + _T("long size;") + xCrLf;

	implCode_ += xTab + GetClassName() + _T(" newElement;") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("SetDefaults();") + xCrLf;
	implCode_ += xCrLf;

	implCode_ += xTab + _T("hr = node->get_childNodes(&children);") + xCrLf;
	implCode_ += xTab + _T("hr = children->get_length(&size);") + xCrLf;

	implCode_ += xTab + _T("for (long i = 0; i < size; i++) {") + xCrLf;
	implCode_ += xTab + xTab + _T("hr = children->get_item(i, &childNode);") + xCrLf;
	implCode_ += xTab + xTab + _T("hr = childNode->get_nodeName(&nodeName);") + xCrLf;
	//implCode_ += xTab + xTab + _T("if (nodeName == newElement.GetXmlNodeName()) {") + xCrLf;
	implCode_ += xTab + xTab + _T("if (newElement.GetXmlNodeName().CompareNoCase(W2T((BSTR)nodeName)) == 0) {") + xCrLf;
	implCode_ += xTab + xTab + xTab + _T("newElement.BuildFromXml(childNode);") + xCrLf;
	implCode_ += xTab + xTab + xTab + arrayName + _T("_.push_back(newElement);") + xCrLf;
	implCode_ += xTab + xTab + _T("}") + xCrLf;
	implCode_ += xCrLf;
	implCode_ += xTab + _T("}") + xCrLf + xCrLf;

	implCode_ += xTab + _T("return true;") + xCrLf;

	implCode_ += _T("}") + xCrLf;
	implCode_ += xCrLf;

	//////////////////////////////////////////////////////////////////////
	// AppendToDOMDocument
	//
	implCode_ += _T("bool ") + GetClassName() + p + _T("::AppendToDOMDocument(IXMLDOMDocument2* xmlDoc, IXMLDOMElement* parentElement)") + xCrLf;
	implCode_ += _T("{") + xCrLf;
	implCode_ += xTab + _T("HRESULT hr;") + xCrLf;
	if (classInfo_->GetCardinalityInfo()->GetUseContainerNode()) {
		implCode_ += xTab + _T("IXMLDOMElement* newElement;") + xCrLf;
		implCode_ += xCrLf;

		implCode_ += xTab + _T("hr = xmlDoc->createElement(CComBSTR((const TCHAR*)GetXmlNodeName()), &newElement);") + xCrLf;
		implCode_ += xTab + _T("if (FAILED(hr))")+ xCrLf;
		implCode_ += xTab + xTab + _T("return false;") + xCrLf;
		implCode_ += xCrLf;
		implCode_ += xTab + _T("for (int i = 0; i < ") + arrayName + _T("_.size(); i++) {") + xCrLf;
		implCode_ += xTab + xTab + arrayName + _T("_[i].AppendToDOMDocument(xmlDoc, newElement);") + xCrLf;
		implCode_ += xTab + _T("}") + xCrLf;
		implCode_ += xCrLf;
		implCode_ += xTab + _T("if (parentElement)") + xCrLf;
		implCode_ += xTab + xTab + _T("hr = parentElement->appendChild(newElement, NULL);") + xCrLf;
		implCode_ += xTab + _T("else") + xCrLf;
		implCode_ += xTab + xTab + _T("hr = xmlDoc->appendChild(newElement, NULL);") + xCrLf;
		implCode_ += xCrLf;
	} else {
		// if no container node is needed append nodes directly under parentElement
		//
		implCode_ += xCrLf;
		implCode_ += xTab + _T("for (int i = 0; i < ") + arrayName + _T("_.size(); i++)") + xCrLf;
		implCode_ += xTab + xTab + _T("hr = ") + arrayName + _T("_[i].AppendToDOMDocument(xmlDoc, parentElement);") + xCrLf;
		implCode_ += xCrLf;
	}

	implCode_ += xTab + _T("return true;") + xCrLf;
	implCode_ += _T("}") + xCrLf + xCrLf;

}

  ***/