/*
 * Created on 24-Oct-2004
 * 
 * (c) 2003-2004 ThoughtWorks Ltd
 *
 * See license.txt for license details
 */
package com.thoughtworks.jbehave.core.minimock;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


/**
 * Syntactic sugar for MiniMock
 * 
 * @author <a href="mailto:dan.north@thoughtworks.com">Dan North</a>
 */
public class MiniMockSugar {
    public Constraint eq(final Object expectedArg) {
        return new Constraint() {
            public boolean matches(Object arg) {
                return arg == null ? expectedArg == null : arg.equals(expectedArg);
            }
            public String toString() {
                return "eq(" + expectedArg + ")";
            }
        };
    }
    
    public Constraint eq(float expectedArg) {
        return eq(new Float(expectedArg));
    }
    
    public Constraint eq(double expectedArg) {
        return eq(new Double(expectedArg));
    }
    
    public Constraint eq(int expectedArg) {
        return eq(new Integer(expectedArg));
    }
    
    public Constraint eq(long expectedArg) {
        return eq(new Long(expectedArg));
    }
    
    public Constraint eq(char expectedArg) {
        return eq(new Character(expectedArg));
    }
    
    public Constraint eq(short expectedArg) {
        return eq(new Short(expectedArg));
    }
    
    public Constraint eq(byte expectedArg) {
        return eq(new Byte(expectedArg));
    }
    
    public Constraint eq(boolean expectedArg) {
        return eq(expectedArg ? Boolean.TRUE : Boolean.FALSE);
    }
    
    // some useful constraints

    public Constraint same(final Object expectedArg) {
        return new Constraint() {
            public boolean matches(Object arg) {
                return expectedArg == arg;
            }
            public String toString() {
                return "same(" + expectedArg + ")";
            }
        };
    }

    public Constraint anything() {
        return new Constraint() {
            public boolean matches(Object arg) {
                return true;
            }
            public String toString() {
                return "anything";
            }
        };
    }

    public Constraint instanceOf(final Class type) {
        return new Constraint() {
            public boolean matches(Object arg) {
                return type.isInstance(arg);
            }
            public String toString() {
                return "instance of " + type.getName();
            }
        };
    }
    
    // boolean constraints - and, or, not
    
    public Constraint and(final Constraint a, final Constraint b) {
        return new Constraint() {
            public boolean matches(Object arg) {
                return a.matches(arg) && b.matches(arg);
            }
            public String toString() {
                return a + " and " + b;
            }
        };
    }
    
    public Constraint both(final Constraint a, final Constraint b) {
        return and(a, b);
    }
    
    public Constraint or(final Constraint a, final Constraint b) {
        return new Constraint() {
            public boolean matches(Object arg) {
                return a.matches(arg) || b.matches(arg);
            }
            public String toString() {
                return a + " or " + b;
            }
        };
    }
    
    public Constraint either(final Constraint a, final Constraint b) {
        return either(a, b);
    }
    
    public Constraint not(final Constraint c) {
        return new Constraint() {
            public boolean matches(Object arg) {
                return !c.matches(arg);
            }
            public String toString() {
                return "not " + c;
            }
        };
    }
    
    // some handy invocation handlers for setting up expectations
    
    public InvocationHandler returnValue(final Object result) {
        return new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) {
                return result;
            }
        };
    }
    
    public InvocationHandler throwException(final Throwable cause) {
        return new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                throw cause;
            }
        };
    }
    
    // yawn - box all the primitive types
    
    public InvocationHandler returnValue(byte result) {
        return returnValue(new Byte(result));
    }
    public InvocationHandler returnValue(char result) {
        return returnValue(new Character(result));
    }
    public InvocationHandler returnValue(short result) {
        return returnValue(new Short(result));
    }
    public InvocationHandler returnValue(int result) {
        return returnValue(new Integer(result));
    }
    public InvocationHandler returnValue(long result) {
        return returnValue(new Long(result));
    }
    public InvocationHandler returnValue(float result) {
        return returnValue(new Float(result));
    }
    public InvocationHandler returnValue(double result) {
        return returnValue(new Double(result));
    }
    public InvocationHandler returnValue(boolean result) {
        return returnValue(result ? Boolean.TRUE : Boolean.FALSE);
    }
}

@@ -755,32 +755,38 @@
  %7D;%0D%0A    %7D%0D%0A    
+ %0D%0A   
 %0D%0A    public Con
@@ -797,20 +797,27 @@
 int eq(f
-loat
+inal double
  expecte
@@ -844,50 +844,36 @@
 urn 
-eq(
 new 
-Float(expectedArg));
+Constraint() %7B
 %0D%0A    
-%7D%0D%0A
     
-%0D%0A
     
@@ -883,131 +883,121 @@
 lic 
-Constraint eq(double expectedArg) %7B%0D%0A        return eq(new Double(expectedArg))
+boolean matches(Object arg) %7B%0D%0A                Number n = (Number)arg
 ;%0D%0A    
-%7D%0D%0A
     
-%0D%0A
     
-public Constraint eq(int
+    return n.doubleValue() ==
  exp
@@ -996,35 +996,33 @@
 ) == expectedArg
-) %7B
+;
 %0D%0A        return
@@ -1019,43 +1019,34 @@
     
-return eq(new Integer(expectedArg))
+    %7D          %0D%0A        %7D
 ;%0D%0A 
@@ -1047,32 +1047,34 @@
  %7D;%0D%0A    %7D%0D%0A    
+  
 %0D%0A    public Con
@@ -1084,16 +1084,22 @@
 aint eq(
+final 
 long exp
@@ -1130,49 +1130,36 @@
 urn 
-eq(
 new 
-Long(expectedArg));
+Constraint() %7B
 %0D%0A    
-%7D%0D%0A
     
-%0D%0A
     
@@ -1169,134 +1169,119 @@
 lic 
-Constraint eq(char expectedArg) %7B%0D%0A        return eq(new Character(expectedArg))
+boolean matches(Object arg) %7B%0D%0A                Number n = (Number)arg
 ;%0D%0A    
-%7D%0D%0A
     
-%0D%0A
     
-public Constraint eq(short
+    return n.longValue() ==
  exp
@@ -1280,35 +1280,33 @@
 ) == expectedArg
-) %7B
+;
 %0D%0A        return
@@ -1303,41 +1303,34 @@
     
-return eq(new Short(expectedArg))
+    %7D          %0D%0A        %7D
 ;%0D%0A 
@@ -1366,20 +1366,20 @@
 aint eq(
-byte
+char
  expecte
@@ -1409,20 +1409,25 @@
  eq(new 
-By
+Charac
 te
+r
 (expecte
@@ -1434,32 +1434,39 @@
 dArg));%0D%0A    %7D%0D%0A
+     %0D%0A
     %0D%0A    public

remove some overloaded eq methods