// CCppResourceGenerator.cpp
//
#include "stdafx.h"
#include "CppResourceGenerator.h"
#include "XmlClassInfo.h"
#include "XmlFormInfo.h"
#include "XmlBaseFormItem.h"
#include "XmlProjectSettings.h"
#include "XmlProjectIcons.h"
#include "XmlProject.h"
#include <map>
#include "CPathSplit.h"

using namespace std;

CCppResourceGenerator::CCppResourceGenerator()
{}

CCppResourceGenerator::~CCppResourceGenerator()
{}

void CCppResourceGenerator::Generate()
{
	cmString fileName;
	cmString pathName;

	int dlgCount = 0;

	resCounter_ = 1000;
	headCode_ = _T("");

	Head_generateHeader();
	Head_generateIfDefBegin();
	Head_generateGlobalResource();
	Head_generateClassResource(classInfo_, _T(""), dlgCount);
	Head_generateIfDefEnd();

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

	hGeneratedFiles_[fileName] = pathName + fileName;

	GenerateTreeIconsHeaderFile();
	GenerateTreeResourceFile();
}

void CCppResourceGenerator::Head_generateHeader()
{
	headCode_ += _T("// ") + GetResourceFileName() + _T(".h") + xCrLf;
	headCode_ += _T("// ") + xCrLf;
	headCode_ += GetGenerationTimeStamp();
}

void CCppResourceGenerator::Head_generateIfDefBegin()
{
	headCode_ += _T("#if !defined(") + DefineOf(GetResourceFileName()) + _T(")") + xCrLf;
	headCode_ += _T("#define ") + DefineOf(GetResourceFileName()) + xCrLf;
	headCode_ += xCrLf;
}

cmString CCppResourceGenerator::ComposeLine(const cmString& define, const cmString& number, const cmString& comment)
{
	cmString line;
	cmString pad = _T("                                                  ");

	line = define;
	line += pad.Mid(0, 50 - define.GetLength());
	line += number;
	line += pad.Mid(0, 15 - number.GetLength());
	line += comment;
	line += xCrLf;

	return line;
}

void CCppResourceGenerator::Head_generateClassResource(CXmlClassInfo* classInfo, cmString parentPath, int& count)
{
	count++;

	headCode_ += xCrLf;
	headCode_ += _T("// control ID for class ") + GetClassName(classInfo->GetName()) + xCrLf;
	headCode_ += _T("// ") + xCrLf;

	// generate class dialog ID
	//
	cmString buf;
	cmString define;
	cmString number;
	cmString comment;
	CXmlClassInfo* tmpClassInfo;

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

	if (tmpClassInfo->GetCardinalityInfo()->GetCardinality() == enCardinality_Array) {
		
		buf.Format(_T("%d"), resCounter_);
		
		//define = "#define " + GetDialogId(classInfo, count) + "_ARRAY";
		define = _T("#define ") + GetDialogId(tmpClassInfo, count) + _T("_ARRAY");
		number = buf;
		comment = _T("// ") + parentPath + _T("::") + tmpClassInfo->GetName() + _T("Array");
		headCode_ += ComposeLine(define, number, comment);
		
		resCounter_++;
	} else if (tmpClassInfo->GetCardinalityInfo()->GetCardinality() == enCardinality_Map) {
		
		buf.Format(_T("%d"), resCounter_);
		
		define = _T("#define ") + GetDialogId(tmpClassInfo, count) + _T("_MAP");
		number = buf;
		comment = _T("// ") + parentPath + _T("::") + classInfo->GetName() + _T("Map");
		headCode_ += ComposeLine(define, number, comment);

		resCounter_++;
	}
	
	buf.Format(_T("%d"), resCounter_);
	define = _T("#define ") + GetDialogId(tmpClassInfo, count);
	number = buf;
	if (parentPath.GetLength())
		comment = _T("// ") + parentPath + _T("::") + tmpClassInfo->GetName();
	else
		comment = _T("// ") + tmpClassInfo->GetName();
	headCode_ += ComposeLine(define, number, comment);
	
	resCounter_++;

	// generate form IDs
	//
	CXmlFormInfo* form;
	FormItemList* formItems;
	FormItemList::iterator formItemIt;
	CXmlBaseFormItem* formItem;
	
	form = classInfo->GetForm();
	
	formItems = form->GetItemList();
	for (formItemIt = formItems->begin(); formItemIt != formItems->end(); formItemIt++) {
		formItem = formItemIt->second;
		buf.Format(_T(" %d"), resCounter_);
		headCode_ += _T("#define ") + GetControlId(formItem, classInfo) + buf + xCrLf;

		resCounter_++;
	}
	headCode_ += xCrLf;

	// generate children IDs
	//
	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	CXmlBaseElement* member;
	cmString tmp;

	members = tmpClassInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;

		if (member->GetDataType() == enDataType_Class) {
			if (parentPath == _T(""))
				tmp = classInfo->GetName();
			else
				tmp = parentPath + _T("::") + classInfo->GetName();
			
			Head_generateClassResource(dynamic_cast<CXmlClassInfo*>(member), tmp,  count);		
		}
	}
}

void CCppResourceGenerator::Head_generateIfDefEnd()
{
	headCode_ += _T("#endif //!defined(") + DefineOf(GetResourceFileName()) + _T(")") + xCrLf + xCrLf;
}

void CCppResourceGenerator::Head_generateGlobalResource()
{
	TCHAR buf[20];

	headCode_ += _T("// global controls") + xCrLf;
	headCode_ += _T("//") + xCrLf;
	
	wsprintf(buf, _T(" %d"), resCounter_++);
	headCode_ += _T("#define ") + GetTreeControlID() + buf + xCrLf;
	
	wsprintf(buf, _T(" %d"), resCounter_++);
	headCode_ += cmString(_T("#define IDC_OPTIONSTREE_OPTIONS ")) + buf + xCrLf;
}

void CCppResourceGenerator::GenerateTreeIconsHeaderFile()
{
	CXmlProjectIcons* projectIcons;
	map<cmString, cmString> icons;
	map<cmString, cmString>::iterator it;
	cmString code;
	int i;
	TCHAR buf[100];
	
	i = cppSettings_->GetResourcesOffset();

	code += _T("// tree icon resources") + xCrLf;
	code += _T("//") + xCrLf;
	code += _T("#if !defined(_TREE_ICON_RES_H_)") + xCrLf;
	code += _T("#define _TREE_ICON_RES_H_") + xCrLf;
	code += xCrLf;
	projectIcons = project_->GetProjectIcons();
	icons = projectIcons->GetIconList();

	for (it = icons.begin(); it != icons.end(); it++) {
		wsprintf(buf, _T("%d"), i);
		code += _T("#define ") + it->second + xTab + buf + xCrLf;
		i++;
	}
	if (project_->GetMainDialog()->GetIconFileName().GetLength()) {
		wsprintf(buf, _T("%d"), i);
		code += _T("#define MAIN_DIALOG_ICON") + xTab + buf + xCrLf;
		i++;
	}
	code += xCrLf;

	code += _T("#define _TREE_ICON_RES_H_") + xCrLf;
	code += xCrLf;

	code += _T("#endif") + xCrLf;

	// save file
	//
	cmString genPath;
	cmString prefix;
	cmString fileName;

	genPath = cppSettings_->GetGenerationPath();
	prefix = cppSettings_->GetClassPrefix();

	fileName = genPath + _T("\\") + prefix + _T("\\project\\TreeIcons.h");

	SaveFile(fileName, code, false);
}

void CCppResourceGenerator::GenerateTreeResourceFile()
{
	CXmlProjectIcons* projectIcons;
	map<cmString, cmString> icons;
	map<cmString, cmString>::iterator it;
	cmString code;
	cmString iconFileName;
	cmString fileName;
	CPathSplit pathSplit;

	code += _T("// tree icon resources") + xCrLf;
	code += _T("//") + xCrLf;
	code += xCrLf;
	projectIcons = project_->GetProjectIcons();
	icons = projectIcons->GetIconList();

	if (cppSettings_->GetGUIGenerationEnabled()) {
		for (it = icons.begin(); it != icons.end(); it++) {
			iconFileName = it->first;
			pathSplit.Split(iconFileName);
			fileName = _T("\"res/");
			fileName += (const TCHAR*)pathSplit.GetFileName();
			fileName += (const TCHAR*)pathSplit.GetExtension();
			fileName += _T("\"");
			code += it->second + xTab + xTab + xTab + xTab + _T("ICON") + xTab + _T("DISCARDABLE") + xTab + fileName + xCrLf;
		}
		
		if (project_->GetMainDialog()->GetIconFileName().GetLength()) {
			iconFileName = project_->GetMainDialog()->GetIconFileName();
			pathSplit.Split(iconFileName);
			fileName = _T("\"res/");
			fileName += (const TCHAR*)pathSplit.GetFileName();
			fileName += (const TCHAR*)pathSplit.GetExtension();
			fileName += _T("\"");
			code += _T("MAIN_DIALOG_ICON") + xTab + xTab + xTab + xTab + _T("ICON") + xTab + _T("DISCARDABLE") + xTab + fileName + xCrLf;
		}

		code += xCrLf;
	}

	// save file
	//
	cmString genPath;
	cmString prefix;

	genPath = cppSettings_->GetGenerationPath();
	prefix = cppSettings_->GetClassPrefix();

	fileName = genPath + _T("\\") + prefix + _T("\\project\\TreeIcons.rc");

	SaveFile(fileName, code, false);
	
}
