using System;
using System.CodeDom;
using System.Reflection;

namespace XTensions.OOCodeDOM
{
	public class Make
	{
		public static CompileUnit CompileUnit (params CodeNamespace[] nss)
		{
			CompileUnit cu = new CompileUnit();

			foreach (CodeNamespace ns in nss)
				cu.Namespaces.Add(ns);

			return cu;
		}

		public static CodeNamespace Namespace (string n, params CodeTypeDeclaration[] ts)
		{
			CodeNamespace ns = new CodeNamespace(n);

			foreach (CodeTypeDeclaration t in ts)
				ns.Types.Add(t);

			return ns;
		}

		public static CodeTypeDeclaration Declaration (string n, CodeTypeReference bt, TypeAttributes ta, params CodeTypeMember[] tms)
		{
			CodeTypeDeclaration td = new CodeTypeDeclaration(n);

			td.BaseTypes.Add(bt);

			td.TypeAttributes = ta;

			foreach (CodeTypeMember tm in tms)
				td.Members.Add(tm);

			return td;
		}

		public static CodeStatement Declaration (Type t, string n, CodeExpression i)
		{
			return new CodeVariableDeclarationStatement(t, n, i);
		}

		public static CodeMemberMethod Method (string n, 
			MemberAttributes ma,
			Type t,
			CodeParameterDeclarationExpression[] pdes,
			CodeStatement[] ss)
		{
			CodeMemberMethod cmm = new CodeMemberMethod();

			cmm.Name = n;
			cmm.Attributes = ma;
			cmm.ReturnType = new CodeTypeReference(t);

			foreach (CodeParameterDeclarationExpression pde in pdes)
				cmm.Parameters.Add(pde);

			foreach (CodeStatement s in ss)
				cmm.Statements.Add(s);

			return cmm;
		}

		public static CodeParameterDeclarationExpression[] Parameters (params CodeParameterDeclarationExpression[] pdes)
		{
			return pdes;
		}

		public static CodeStatement[] Statements (params CodeStatement[] ss)
		{
			return ss;
		}

		public static CodeTypeReference TypeReference (Type t)
		{
			return new CodeTypeReference(t);
		}

		public static CodeTypeReference TypeReference (string s)
		{
			return new CodeTypeReference(s);
		}

		public static CodeExpression This
		{
			get
			{
				return new CodeThisReferenceExpression();
			}
		}

		public static Expression VariableReference (string n)
		{
			return new Expression(new CodeVariableReferenceExpression(n));
		}

		public static CodeExpression Invoke (CodeExpression o, string n, CodeExpression[] es)
		{
			return new CodeMethodInvokeExpression(o, n, es);
		}

		public static CodeExpression[] Expressions (params CodeExpression[] es)
		{
			return es;
		}

		public static Expression Constant (object o)
		{
			return new Expression(new CodePrimitiveExpression(o));
		}

		public static CodeStatement Statement (CodeExpression e)
		{
			return new CodeExpressionStatement(e);
		}

		public static CodeStatement If (CodeExpression c, CodeStatement[] ts, CodeStatement[] fs)
		{
			return new CodeConditionStatement(c, ts, fs);
		}

		public static CodeExpression Snippet (string s)
		{
			return new CodeSnippetExpression(s);
		}

		public static CodeStatement Return (CodeExpression e)
		{
			return new CodeMethodReturnStatement(e);
		}

		public static CodeCastExpression Cast (Type t, CodeExpression e)
		{
			return new CodeCastExpression(t, e);
		}

		public static CodeParameterDeclarationExpression Parameter (Type t, string n, FieldDirection d)
		{
			CodeParameterDeclarationExpression pde = new CodeParameterDeclarationExpression(t, n);

			pde.Direction = d;

			return pde;
		}

		public static Expression FieldReference (CodeExpression o, string f)
		{
			return new Expression(new CodeFieldReferenceExpression(o, f));
		}

		public static CodeStatement For (CodeStatement i, CodeExpression t, CodeStatement u, CodeStatement[] b)
		{
			return new CodeIterationStatement(i, t, u, b);
		}

		public static CodeStatement AssignStatement (CodeExpression l, CodeExpression r)
		{
			return new CodeAssignStatement(l, r);
		}

		public static CodeExpression NewExpression (Type t, CodeExpression[] e)
		{
			return new CodeObjectCreateExpression(t, e);
		}

		public static CodeMemberField Field (Type t, string n, MemberAttributes ma)
		{
			CodeMemberField mf = new CodeMemberField(t, n);

			mf.Attributes = ma;

			return mf;
		}

		public static CodeTypeReferenceExpression Expression (CodeTypeReference r)
		{
			return new CodeTypeReferenceExpression(r);
		}
	}
}
