using System.IO;
using System.Text.RegularExpressions;
using DotNetMock.Dynamic;
using DotNetMock.Dynamic.Predicates;
using NUnit.Framework;
namespace DotNetMock.Tests.Dynamic
{
	[TestFixture]
	public class PredicatesTest
	{
		private IPredicate p;
		[Test]
		public void AndToString( )
		{
			Assert.AreEqual(
				"(value is anything) and (value is anything)",
				new AndPredicate(
					new IsAnything( ), new IsAnything( )
					).ToString( )
				);
		}
		[Test]
		public void IsAnythingToString( )
		{
			Assert.AreEqual( "value is anything", new IsAnything( ).ToString( ) );
		}
		[Test]
		public void IsCloseToToString( )
		{
			Assert.AreEqual(
				"value is within 0.1 of 1",
				new IsCloseTo( 1, 0.1 ).ToString( )
				);
		}
		[Test]
		public void IsEqualToString( )
		{
			Assert.AreEqual(
				"value equals 3",
				new IsEqual( 3 ).ToString( )
				);
			Assert.AreEqual(
				"value equals 'whatever it is'",
				new IsEqual( "whatever it is" ).ToString( )
				);
		}
		[Test]
		public void IsEqualIgnoreCaseToString( )
		{
			Assert.AreEqual(
				"value equals 'abc' (ignore case)",
				new IsEqualIgnoreCase( "abc" ).ToString( )
				);
			Assert.AreEqual(
				"value equals 'whatever' (ignore case)",
				new IsEqualIgnoreCase( "whatever" ).ToString( )
				);
		}
		[Test]
		public void IsEqualIgnoreWhiteSpaceToString( )
		{
			Assert.AreEqual(
				"value equals 'a  b  c' (ignore whitespace)",
				new IsEqualIgnoreWhiteSpace( "a  b  c" ).ToString( )
				);
			Assert.AreEqual(
				"value equals 'what  ever' (ignore whitespace)",
				new IsEqualIgnoreWhiteSpace( "what  ever" ).ToString( )
				);
		}
		[Test]
		public void IsInToString( )
		{
			Assert.AreEqual(
				"value is in [1, 'two', 3.4]",
				new IsIn( 1, "two", 3.4 ).ToString( )
				);
		}
		[Test]
		public void IsMatchToString( )
		{
			Assert.AreEqual(
				"value matches /^abc$/",
				new IsMatch( "^abc$" ).ToString( )
				);
		}
		[Test]
		public void IsNullToString( )
		{
			Assert.AreEqual( "value is null", new IsNull( ).ToString( ) );
		}
		[Test]
		public void IsTypeOfToString( )
		{
			Assert.AreEqual(
				"value is a System.Object",
				new IsTypeOf( typeof ( object ) ).ToString( )
				);
		}
		[Test]
		public void NotEqualToString( )
		{
			Assert.AreEqual(
				"value is not equal to 3",
				new NotEqual( 3 ).ToString( )
				);
			Assert.AreEqual(
				"value is not equal to 'whatever it is'",
				new NotEqual( "whatever it is" ).ToString( )
				);
		}
		[Test]
		public void NotInToString( )
		{
			Assert.AreEqual(
				"value is not in [1, 'two', 3.4]",
				new NotIn( 1, "two", 3.4 ).ToString( )
				);
		}
		[Test]
		public void NotNullToString( )
		{
			Assert.AreEqual( "value is not null", new NotNull( ).ToString( ) );
		}
		[Test]
		public void NotToString( )
		{
			Assert.AreEqual(
				"not (value is anything)",
				new NotPredicate( new IsAnything( ) ).ToString( )
				);
		}
		[Test]
		public void OrToString( )
		{
			Assert.AreEqual(
				"(value is anything) or (value is anything)",
				new OrPredicate(
					new IsAnything( ), new IsAnything( )
					).ToString( )
				);
		}
		[Test]
		public void IsNull( )
		{
			p = new IsNull( );
			Assert.IsTrue( p.Eval( null ) );
			Assert.IsTrue( !p.Eval( new object( ) ) );
			Assert.IsTrue( !p.Eval( 1 ) );
			Assert.IsTrue( !p.Eval( true ) );
			Assert.IsTrue( !p.Eval( false ) );
		}
		[Test]
		public void NotNull( )
		{
			p = new NotNull( );
			Assert.IsTrue( !p.Eval( null ) );
			Assert.IsTrue( p.Eval( new object( ) ) );
		}
		[Test]
		public void IsEqual( )
		{
			object o1 = new object( );
			object o2 = new object( );
			p = new IsEqual( o1 );
			Assert.IsTrue( p.Eval( o1 ) );
			Assert.IsTrue( !p.Eval( o2 ) );
			Assert.IsTrue( !p.Eval( null ) );
			int i1 = 1;
			int i2 = 2;
			p = new IsEqual( i1 );
			Assert.IsTrue( p.Eval( i1 ) );
			Assert.IsTrue( p.Eval( 1 ) );
			Assert.IsTrue( !p.Eval( i2 ) );
			Assert.IsTrue( !p.Eval( 2 ) );
			p = new IsEqual( null );
			Assert.IsTrue( !p.Eval( "something" ) );
			Assert.IsTrue( p.Eval( null ) );
		}
		[Test]
		public void IsEqualArray( )
		{
			object[] array1 = new object[] {1};
			p = new IsEqual( array1 );
			Assert.IsTrue( !p.Eval( "hello" ) );
			Assert.IsTrue( !p.Eval( null ) );
			Assert.IsTrue( !p.Eval( new object[] {2, 3} ) );
			Assert.IsTrue( !p.Eval( new object[] {} ) );
			Assert.IsTrue( !p.Eval( new object[] {2} ) );
			Assert.IsTrue( p.Eval( array1 ) );
			Assert.IsTrue( p.Eval( new object[] {1} ) );
		}
		[Test]
		public void NotEqual( )
		{
			object o1 = new object( );
			object o2 = new object( );
			p = new NotEqual( o1 );
			Assert.IsTrue( !p.Eval( o1 ) );
			Assert.IsTrue( p.Eval( o2 ) );
			Assert.IsTrue( p.Eval( null ) );
			int i1 = 1;
			int i2 = 2;
			p = new NotEqual( i1 );
			Assert.IsTrue( !p.Eval( i1 ) );
			Assert.IsTrue( !p.Eval( 1 ) );
			Assert.IsTrue( p.Eval( i2 ) );
			Assert.IsTrue( p.Eval( 2 ) );
		}
		[Test]
		public void IsAnything( )
		{
			p = new IsAnything( );
			Assert.IsTrue( p.Eval( null ) );
			Assert.IsTrue( p.Eval( 0 ) );
			Assert.IsTrue( p.Eval( 99 ) );
			Assert.IsTrue( p.Eval( -2 ) );
			Assert.IsTrue( p.Eval( true ) );
			Assert.IsTrue( p.Eval( false ) );
			Assert.IsTrue( p.Eval( "" ) );
			Assert.IsTrue( p.Eval( "hello" ) );
			Assert.IsTrue( p.Eval( new object( ) ) );
		}
		[Test]
		public void IsType( )
		{
			p = new IsTypeOf( typeof ( TextReader ) );
			Assert.IsTrue( !p.Eval( null ) );
			Assert.IsTrue( p.Eval( new StringReader( "" ) ) );
			Assert.IsTrue( !p.Eval( new StringWriter( ) ) );
		}
		[Test]
		public void Not( )
		{
			Assert.IsTrue( new NotPredicate( new False( ) ).Eval( null ) );
			Assert.IsTrue( !new NotPredicate( new True( ) ).Eval( null ) );
		}
		[Test]
		public void And( )
		{
			Assert.IsTrue( new AndPredicate( new True( ), new True( ) ).Eval( null ) );
			Assert.AreEqual( "(N/A)", new True( ).ToString( ) );
			Assert.IsTrue( !new AndPredicate( new True( ), new False( ) ).Eval( null ) );
			Assert.IsTrue( !new AndPredicate( new False( ), new True( ) ).Eval( null ) );
			Assert.IsTrue( !new AndPredicate( new False( ), new False( ) ).Eval( null ) );
		}
		[Test]
		public void Or( )
		{
			Assert.IsTrue( new OrPredicate( new True( ), new True( ) ).Eval( null ) );
			Assert.IsTrue( new OrPredicate( new True( ), new False( ) ).Eval( null ) );
			Assert.IsTrue( new OrPredicate( new False( ), new True( ) ).Eval( null ) );
			Assert.IsTrue( !new OrPredicate( new False( ), new False( ) ).Eval( null ) );
		}
		[Test]
		public void IsIn( )
		{
			p = new IsIn( 2, 3, 5 );
			Assert.IsTrue( !p.Eval( 1 ) );
			Assert.IsTrue( p.Eval( 2 ) );
			Assert.IsTrue( p.Eval( 3 ) );
			Assert.IsTrue( !p.Eval( 4 ) );
			Assert.IsTrue( p.Eval( 5 ) );
			Assert.IsTrue( !p.Eval( 6 ) );
			Assert.IsTrue( !p.Eval( null ) );
			int[] array = {1, 2};
			p = new IsIn( array );
			Assert.IsTrue( p.Eval( 1 ) );
			Assert.IsTrue( p.Eval( 2 ) );
			Assert.IsTrue( !p.Eval( 3 ) );
		}
		[Test]
		public void NotIn( )
		{
			p = new NotIn( 1, 2 );
			Assert.IsTrue( !p.Eval( 1 ) );
			Assert.IsTrue( !p.Eval( 2 ) );
			Assert.IsTrue( p.Eval( 3 ) );
			int[] array = {1, 2};
			p = new NotIn( array );
			Assert.IsTrue( !p.Eval( 1 ) );
			Assert.IsTrue( !p.Eval( 2 ) );
			Assert.IsTrue( p.Eval( 3 ) );
		}
		[Test]
		public void IsEqualIgnoreCase( )
		{
			p = new IsEqualIgnoreCase( "heLLo" );
			Assert.IsTrue( p.Eval( "HELLO" ) );
			Assert.IsTrue( p.Eval( "hello" ) );
			Assert.IsTrue( p.Eval( "HelLo" ) );
			Assert.IsTrue( !p.Eval( "abcde" ) );
		}
		[Test]
		public void StripSpace( )
		{
			Assert.AreEqual( "Hello World", IsEqualIgnoreWhiteSpace.StripSpace( "Hello\n  \n World" ) );
			Assert.AreEqual( "Hello World", IsEqualIgnoreWhiteSpace.StripSpace( " Hello World " ) );
			Assert.AreEqual( "", IsEqualIgnoreWhiteSpace.StripSpace( "  " ) );
		}
		[Test]
		public void TestIsEqualIgnoreWhiteSpace( )
		{
			p = new IsEqualIgnoreWhiteSpace( "Hello World   how\n are we?" );
			Assert.IsTrue( p.Eval( "Hello World how are we?" ) );
			Assert.IsTrue( p.Eval( "   Hello World   how are \n\n\twe?" ) );
			Assert.IsTrue( !p.Eval( "HelloWorld how are we?" ) );
			Assert.IsTrue( !p.Eval( "Hello World how are we" ) );
		}
		[Test]
		public void IsMatch( )
		{
			p = new IsMatch( new Regex( @"^th[aeiou]\w* .*$" ) );
			Assert.IsTrue( p.Eval( "the world" ) );
			Assert.IsTrue( !p.Eval( "theworld" ) );
			Assert.IsTrue( !p.Eval( "ThE world" ) );
			Assert.IsTrue( !p.Eval( " the world" ) );
			Assert.IsTrue( p.Eval( "thats nice" ) );
			Assert.IsTrue( !p.Eval( new object( ) ) );
			Assert.IsTrue( !p.Eval( null ) );
			p = new IsMatch( @"^th[aeiou]\w* .*$" );
			Assert.IsTrue( p.Eval( "the world" ) );
			Assert.IsTrue( !p.Eval( "theworld" ) );
			Assert.IsTrue( !p.Eval( "ThE world" ) );
			p = new IsMatch( @"^th[aeiou]\w* .*$", false );
			Assert.IsTrue( p.Eval( "the world" ) );
			Assert.IsTrue( !p.Eval( "theworld" ) );
			Assert.IsTrue( !p.Eval( "ThE world" ) );
			p = new IsMatch( @"^th[aeiou]\w* .*$", true );
			Assert.IsTrue( p.Eval( "the world" ) );
			Assert.IsTrue( !p.Eval( "theworld" ) );
			Assert.IsTrue( p.Eval( "ThE world" ) );
		}
		[Test]
		public void Delegate( )
		{
			p = new Predicate( new Predicate.EvaluationMethod( myEval ) );
			myFlag = false;
			Assert.IsTrue( p.Eval( null ) );
			Assert.IsTrue( !p.Eval( null ) );
			Assert.IsTrue( p.Eval( null ) );
			Assert.IsTrue( !p.Eval( null ) );
		}
		[Test]
		public void IsCloseTo( )
		{
			p = new IsCloseTo( 3.0, 0.5 );
			Assert.IsTrue( p.Eval( 3.0 ) );
			Assert.IsTrue( p.Eval( 3.5 ) );
			Assert.IsFalse( p.Eval( 3.6 ) );
			Assert.IsTrue( p.Eval( 3.2 ) );
			Assert.IsFalse( p.Eval( 2.0 ) );
			Assert.IsTrue( p.Eval( 3.4 ) );
			Assert.IsFalse( p.Eval( null ) );
			Assert.IsFalse( p.Eval( "mock" ) );
		}
		private bool myFlag;
		private bool myEval( object val )
		{
			myFlag = !myFlag;
			return myFlag;
		}
		private class True : AbstractPredicate
		{
			public override bool Eval( object val )
			{
				return true;
			}
		}
		private class False : AbstractPredicate
		{
			public override bool Eval( object val )
			{
				return false;
			}
		}
	}
}