#region License
// Copyright (c) 2005 Griffin Caprio & Choy Rim. All rights reserved.
#endregion
#region Imports
using System;
using System.Data;
using System.Data.SqlClient;

using MbUnit.Core.Framework;
using MbUnit.Framework;

using DotNetMock.Framework.Data;
#endregion

namespace DotNetMock.Examples.MailingList
{
	[TestFixture]
	public class MailingListTests
	{
		private string _email = "fred.bloggs@an.address";
		private string _name = "Fred Bloggs";

		private MailingList _list = null;
		private MockListAction _mockListAction = null;
		private MockDbConnection _mockConnection = null;
		private MockCommand _mockCommand = null;
		private MockDataReader _mockReader = null;


		[SetUp]
		public void Init()
		{
			_list = new MailingList();
			_mockListAction = new MockListAction();
			_mockConnection = new MockDbConnection();
			_mockCommand = new MockCommand();
			_mockReader = new MockDataReader();
			_mockConnection.SetExpectedCommand(_mockCommand);
		}
		private void setGeneralExpectations()
		{
			_mockConnection.SetExpectedCreateCalls(1);
			_mockCommand.SetExpectedExecuteCalls(1);
			_mockConnection.SetExpectedCloseCalls(1);
		}
		private void setExpectationsForAddMember()
		{
			setGeneralExpectations();
			_mockCommand.SetExpectedCommandText(MailingList.INSERT_SQL);
			_mockCommand.SetExpectedParameter(new MockDataParameter("@email", _email));
			_mockCommand.SetExpectedParameter(new MockDataParameter("@name", _name));
		}
		private void setExpectationsForRemoveMember()
		{		
			setGeneralExpectations();
			_mockCommand.SetExpectedCommandText(MailingList.DELETE_SQL);
			_mockCommand.SetExpectedParameter(new MockDataParameter("@email", _email));
		
		}
		private void setExpectationsForListMember()
		{
			setGeneralExpectations();
			_mockCommand.SetExpectedReader(_mockReader);
			_mockCommand.SetExpectedCommandText(MailingList.SELECT_SQL);
		}
		private void verifyADO()
		{
			_mockCommand.Verify();
			_mockConnection.Verify();
		}
		[Test]
		public void AddNewMember()
		{
			setExpectationsForAddMember();
			
			_list.AddMember(_mockConnection, _email, _name);

			verifyADO();
		}		
		[Test]
		[ExpectedException(typeof(MailingListException))]
		public void AddExistingMember()
		{
			setExpectationsForAddMember();
			_mockCommand.SetExecuteException(new ConstraintException("Duplicate User"));
			_list.AddMember(_mockConnection, _email, _name);
		}
		[Test]
		public void CreateCommandFailsForAdd()
		{
			_mockConnection.SetCreateCommandException(new SystemException());
			_mockConnection.SetExpectedCreateCalls(1);

			try 
			{
				_list.AddMember(_mockConnection, _email, _name);
				Assertion.Fail("Should have thrown an exception.");
			}
			catch (SystemException)
			{
			}
			verifyADO();
		}
		[Test]
		public void RemoveMember()
		{
			setExpectationsForRemoveMember();
			_mockCommand.SetUpdateCount(1);

			_list.RemoveMember(_mockConnection, _email);

			verifyADO();
		}
		[Test]
		public void RemoveMissingMember()
		{
			_mockCommand.SetUpdateCount(0);
			setExpectationsForRemoveMember();

			try 
			{
				_list.RemoveMember(_mockConnection, _email);
			}
			catch (MailingListException)
			{
			}
			verifyADO();
		}
		[Test]
		public void ListOneMember() 
		{
			setExpectationsForListMember();
			object[,] values = new object[1,2];
			values[0,0] = _email;
			values[0,1] = _name;
			_mockReader.SetRows(values);
			_mockReader.SetExpectedReadCalls(2);

			_mockListAction.AddExpectedMember(_email, _name);
			_mockListAction.SetExpectedMemberCount(1);

			_list.ApplyToAllMembers(_mockConnection, _mockListAction);

			verifyADO();
			_mockReader.Verify();
			_mockListAction.Verify();

		}
		[Test]
		public void ListTwoMembers()
		{
			setExpectationsForListMember();
			object[,] values = new object[2,2];
			values[0,0] = _email;
			values[0,1] = _name;
			values[1,0] = _email;
			values[1,1] = _name;
			_mockReader.SetRows(values);

			_mockReader.SetExpectedReadCalls(3);

			_mockListAction.SetExpectedMemberCount(2);
			_mockListAction.AddExpectedMember(_email, _name);
			_mockListAction.AddExpectedMember(_email, _name);
			_list.ApplyToAllMembers(_mockConnection, _mockListAction);

			verifyADO();
			_mockReader.Verify();
			_mockListAction.Verify();
		}
		[Test]
		public void ListNoMembers()
		{
			setExpectationsForListMember();
			_mockReader.SetExpectedReadCalls(1);
			_mockListAction.SetExpectNoMembers();
			_list.ApplyToAllMembers(_mockConnection, _mockListAction);

			verifyADO();
			_mockReader.Verify();
			_mockListAction.Verify();
		}
		[Test]
		public void ListMemberFails()
		{
			setExpectationsForListMember();
			object[,] values = new object[2,2];
			values[0,0] = _email;
			values[0,1] = _name;
			values[1,0] = _email;
			values[1,1] = _name;
			_mockReader.SetRows(values);
			_mockReader.SetGetException(new ApplicationException("Mock Exception"));
			_mockReader.SetExpectedReadCalls(1);
			_mockListAction.SetExpectNoMembers();

			try 
			{
				_list.ApplyToAllMembers(_mockConnection, _mockListAction);
				Assertion.Fail("Should have thrown an exception.");
			} 
			catch (ApplicationException) 
			{
			}
			verifyADO();
			_mockReader.Verify();
			_mockListAction.Verify();
		}
	}
}
