module struct_wrapper;

public import utils;

/*
 * WrapStruct is required to instantiate the WrapStruct2 mixin at the scope
 * of the struct that we are wrapping
 */
char[] WrapStruct(char[] struct_name)()
{
	return 
`mixin WrapStruct2!("` ~ struct_name ~ `")`  ~ struct_name ~ `dummy;
mixin(`~ struct_name ~ `dummy.Gen());
`;
}

template WrapStruct2(char[] struct_name)
{
	char[] Gen()
	{
		char[] ret;
		
		auto names = GetNamesInAlias!(mixin(struct_name))();
		auto types = GetTypesInAlias!(mixin(struct_name))();
		const n = mixin(struct_name).tupleof.length;
				
		char[][] integers;
		char[][] doubles;
		
		for(int ii = 0; ii < n; ii++)
		{
			switch(types[ii])
			{
				case "int":
					integers ~= names[ii];
				break;
				case "double":
					doubles ~= names[ii];
				break;
				default:
			}
		}
		
		ret ~=
`class ` ~ struct_name ~ `Manager
{
	void IncrementIntegers(ref ` ~ struct_name ~ ` strct)
	{
`;
		foreach(val; integers)
		{
			ret ~= 
`		strct.` ~ val ~ ` += 1;
`;
		}
		ret ~= 
`	}

	void IncrementDoubles(ref ` ~ struct_name ~ ` strct)
	{
`;
		foreach(val; doubles)
		{
			ret ~= `strct.` ~ val ~ ` += 1.0;
`;
		}
		ret ~= 
`	}
	
	void Negate(ref ` ~ struct_name ~ ` strct)
	{
`;
		if(mixin(`is(typeof(` ~ struct_name ~ `.Negate))`))
		{
			ret ~= 
`		strct.Negate();
`;
		}
		ret ~= 
`	}
}`;
		return ret;
	}
}
