using System.Threading;
using MbUnit.Framework;
using PlayingWithServices.Core;
using Rhino.Mocks;

namespace PlayingWithServices.Test {
	[TestFixture]
	public class AuthenticationServiceTest {
		private MockRepository _mockery;
		private IUserRepository _userRepository;

		[SetUp]
		public void Setup( ) {
			_mockery = new MockRepository( );
			_userRepository = _mockery.CreateMock< IUserRepository >( );
		}

		[Test]
		public void Should_Check_Repository_For_User( ) {
			IUser stubUser = _mockery.Stub< IUser >( );

			using ( _mockery.Record( ) ) {
				SetupResult.For( stubUser.UserName ).Return( "mo" );
				SetupResult.For( stubUser.Password ).Return( "NotPassword" );

				Expect.Call( _userRepository.FindBy( "mo" ) ).Return( stubUser );
			}

			using ( _mockery.Playback( ) ) {
				Assert.IsFalse( CreateSut( ).CheckCredentials( "mo", "password" ) );
			}
		}

		[Test]
		public void Should_Check_If_Credentials_Match_For_User( ) {
			const string userName = "mo";
			const string password = "password";

			IUser stubUser = _mockery.Stub< IUser >( );

			using ( _mockery.Record( ) ) {
				SetupResult.For( stubUser.UserName ).Return( userName );
				SetupResult.For( stubUser.Password ).Return( password );

				Expect.Call( _userRepository.FindBy( userName ) ).Return( stubUser );
			}

			using ( _mockery.Playback( ) ) {
				Assert.IsTrue( CreateSut( ).CheckCredentials( userName, password ), "should return true" );
			}
		}

		[Test]
		public void Should_Set_Current_Threads_Principal_To_Authenticated( ) {
			const string userName = "mo";
			const string password = "password";

			IUser stubUser = _mockery.Stub< IUser >( );

			using ( _mockery.Record( ) ) {
				SetupResult.For( stubUser.UserName ).Return( userName );
				SetupResult.For( stubUser.Password ).Return( password );

				Expect.Call( _userRepository.FindBy( userName ) ).Return( stubUser );
			}

			using ( _mockery.Playback( ) ) {
				CreateSut( ).CheckCredentials( userName, password );
				Assert.IsTrue( Thread.CurrentPrincipal.Identity.IsAuthenticated, "should set current thread to authenticated" );
			}
		}

		private IAuthenticationService CreateSut( ) {
			return new AuthenticationService( _userRepository );
		}
	}
}