using System;
using System.Threading;
using NUnit.Framework;
using DotNetMock;

namespace DotNetMock.Tests
{
	[TestFixture]
	public class VerifierTests
	{
		private delegate void VerifyAsync();

		private class OneVerifiable : MockObject 
		{
			private ExpectationValue _expectationValue = new ExpectationValue("Should Fail");
			
			private String _stringField;
			public int _intField = 5;
			
			public String StringField 
			{
				set {	_stringField = value;	}
				get	{	return _stringField;	}
			}

			public OneVerifiable() : base() 
			{
				_expectationValue.Expected = "Good";
			}
			public Object ActualValue 
			{
				set
				{
					_expectationValue.Actual = value;
				}
				get
				{
					return _expectationValue.Actual;
				}
			}
		}
		private class ClassA : MockObject
		{
			public ClassB classB = null;
			private ExpectationValue _expectationValue = new ExpectationValue( "Value A" );

			public ClassA() : base() {
				_expectationValue.Actual = "Value A";
			}
		}
		private class ClassB : MockObject 
		{
			public ClassA classA = null;
			private ExpectationValue _expectationValue = new ExpectationValue( "Value B" );

			public ClassB() : base() {
				_expectationValue.Actual = "Value B";
			}

		}
		private class InheritVerifiable : OneVerifiable {}

		private OneVerifiable _mockObject = null;

		public VerifierTests() {}

		[SetUp]
		public void SetUp()
		{
			_mockObject = new OneVerifiable();
		}
		
		[TearDown]
		public void TearDown() {}

		[Test]
		public void OneVerifiablePasses()
		{
			_mockObject.ActualValue = "Good";
			_mockObject.Verify();
		}

		[Test]
		[ExpectedException(typeof(AssertionException))]
		public void OneVerifiableFails()
		{
			_mockObject.ActualValue = "bad";
			_mockObject.Verify();
		}
		
		[Test]
		[ExpectedException(typeof(AssertionException))]
		public void InheritVerifiableFails()
		{
			InheritVerifiable inheritVerifiable = new InheritVerifiable();
			inheritVerifiable.ActualValue = "bad";
			inheritVerifiable.Verify();
		}
	    
		[Test]
		public void InheritVerifiablePasses()
		{        
			InheritVerifiable inheritVerifiable = new InheritVerifiable();
			inheritVerifiable.ActualValue = "Good";
			inheritVerifiable.Verify();
		}
		[Test]
		public void NoVerifiables()
		{
			new MockObject().Verify();
		}
		[Test]
		public void VerifierCircularReference()
		{
			ClassA a = new ClassA();
			ClassB b = new ClassB();

			a.classB = b;
			b.classA = a;
			VerifyAsync va = new VerifyAsync( a.Verify );
			IAsyncResult result = va.BeginInvoke( null, null );
			Thread.Sleep( 1000 );
			if ( ! result.IsCompleted ) 
			{
				throw new AssertionException( "Verify failed for circular reference" );
			}
			a.Verify();
		}
	}
}
