#pragma once

#include <string>
#include <vector>
#include <iostream>

using namespace std;
class GroupProperty;
class Property;

namespace NDTS
{
	namespace SCO
	{
class SCO_API CodeGenerator
{
public:
	enum ManagedOrUnmanaged
	{
		Managed,
		Unmanaged
	};

	CodeGenerator(GroupProperty *pRoot);
	virtual ~CodeGenerator(void);
	void createCPPHeaderFile(const char *path, const char *namespaceName, const char *rootDeclaration, enum ManagedOrUnmanaged managedOrUnmanaged);
	void createEnumHeaderFile(const char *path, const char *namespaceName, enum ManagedOrUnmanaged managedOrUnmanaged);
	void createStringsHeaderFile(const char *path, const char *namespaceName, enum ManagedOrUnmanaged managedOrUnmanaged);


private:
	GroupProperty *pRoot;

	// General utilities
	string stripNonAlpha(const string &name);
	// Get a name from a property name.  The name is used directly in the Enum declaration
	string getNameFromPropName(Property *pProperty);
	// Get a variable name from a property
	// Unmanaged is pPropertyName managed has propertyName
	string getVariableNameFromPropName(Property *pProperty);

	// Enum generation
	void createEnumsForGroup(ostream &os, GroupProperty *pGroup);
	void listEnumNames(ostream &os, EnumProperty *pEnumProperty);

	// Property name generation
	bool isKnownType(Property *pProp);
	string getVariableTypeString(Property *pProp);
	void createVariableDeclarationsForGroup(ostream &os, GroupProperty *pGroup, std::vector<int> arraySizes);
	void createAssignmentsForGroup(ostream &os, GroupProperty *pGroup, int arrayDepth);
	string getArrayDeclarationsString(vector<int> arraySizes);
	string getArrayIndicesString(int arrayDepth);
	string getManagedArrayDeclarationsString(vector<int> arraySizes, string className);
	void createVariableAllocationsForGroup(ostream &os, GroupProperty *pGroup, vector<int> arraySizes);
	void createManagedArrayAllocationString(ostream &os, vector<int> arraySizes, string className, string variableName);

	// String declarations for the names
	void createStringsForGroup(ostream &os, GroupProperty *pGroup);
	
	enum ManagedOrUnmanaged managedOrUnmanaged;
};
	}}