using System;
using System.Reflection;
using System.Reflection.Emit;
using DotNetMock.Dynamic.Generate;
using NUnit.Framework;

namespace DotNetMock.Tests.Dynamic.Generate
{
	[TestFixture]
	public class MockClassBuilderTests
	{
		[Test] 
		[ExpectedException(typeof(InvalidOperationException))]
		public void ThrowsExceptionWhenNotCompiled()
		{
			MockClassBuilder classBuilder = createMockClassBuilder( );
			object mockClass = classBuilder.MockClass;
		}
		[Test] 
		[ExpectedException(typeof(InvalidOperationException))]
		public void ThrowsExceptionForHandlerFieldWhenNotCompiled()
		{
			MockClassBuilder classBuilder = createMockClassBuilder( );
			object mockClass = classBuilder.HandlerField;
		}
		[Test] 
		[ExpectedException(typeof(InvalidOperationException))]
		public void ThrowsExceptionWhenCompiledTwice()
		{
			MockClassBuilder classBuilder = createMockClassBuilder( );
			classBuilder.Compile();
			classBuilder.Compile();
		}
		[Test] 
		[ExpectedException(typeof(InvalidOperationException))]
		public void ThrowsExceptionWhenImplementMethodAfterCompiled()
		{
			MockClassBuilder classBuilder = createMockClassBuilder( );
			classBuilder.Compile();
			classBuilder.ImplementMockedMethod( "FooMethod", typeof(object), new Type[] { typeof(object) } );
		}

		private static MockClassBuilder createMockClassBuilder( )
		{
			AssemblyBuilder _assemblyBuilder;
			ModuleBuilder _moduleBuilder;
			_assemblyBuilder = newAssemblyBuilder( AssemblyBuilderAccess.Run );
			_moduleBuilder = _assemblyBuilder.DefineDynamicModule( "MockModule" );
			return new MockClassBuilder(
				_moduleBuilder,
				"MockObject",
				typeof ( object ),
				Type.EmptyTypes
				);
		}
		private static AssemblyBuilder newAssemblyBuilder( AssemblyBuilderAccess access )
		{
			AppDomain appDomain = AppDomain.CurrentDomain;
			AssemblyName assemblyName = new AssemblyName( );
			assemblyName.Name = "DynamicMockAssembly";
			return appDomain.DefineDynamicAssembly( assemblyName, access );
		}
	}
}
